Report a Problem requires a description of at least 200 characters and improvements to submission process #159

Closed
opened 2026-07-02 20:48:23 +00:00 by JMR-dev · 0 comments
JMR-dev commented 2026-07-02 20:48:23 +00:00 (Migrated from github.com)

Context

ReportReviewScreen.kt / ReportReviewViewModel.kt today collect an optional, unvalidated
comment (OutlinedTextField, label "What went wrong? (optional)") and submit unconditionally
(the Submit button is disabled only while SubmitUiState.SUBMITTING). There is no minimum length,
no content-quality check, and no email field at all — DebugReport (reporting/DebugReport.kt)
has no field to carry one. This ticket adds friction against low-effort submissions and collects a
reply-to address.

Scope

  • Minimum length, enforced: require 200 characters in the comment field before Submit is
    enabled (mirror the existing enabled = state.submit != SubmitUiState.SUBMITTING check in
    ReportReviewScreen.kt with an added length condition, backed by new validation state in
    ReportReviewViewModel).
  • Live counter: show "x/200" below the text field, updating as the user types.
  • Invalid-submit feedback: if the user taps Submit while under the threshold (relevant once
    the button itself is only disabled, some users tap disabled controls or arrive via
    accessibility tools) — or, if the button stays enabled and this is meant as inline validation
    instead, tapping Submit under-length turns the counter text and the field's outline red.
    Resolve which of these two interaction models is intended before implementing (the ticket's
    wording suggests the button both stays non-functional under threshold and gives red
    error feedback on an attempted tap — clarify with the reporter if ambiguous).
  • English-only note: a short static string near the comment field noting the maintainer
    only reads English.
  • Low-effort content heuristic: reject comments that are nonsensically repeating characters,
    repeated whitespace runs, or otherwise don't resemble real words/language. This needs to stay
    a cheap heuristic (e.g. longest repeated-character run, repeated-whitespace run, ratio of
    distinct "word" tokens to total length) — not a language model or dictionary lookup. Define
    the exact thresholds during implementation and unit-test them against both false positives
    (real short complaints) and the obvious abuse cases ("aaaaaaa...", "asdf asdf asdf",
    etc.). On failure, show exactly: "Please ensure your message is detailed enough for
    submission." — deliberately generic, so the heuristic itself isn't disclosed/game-able.
  • Password-mention escalation: if the comment contains the word "password" or a
    1-character-edit variant of it (insertion/deletion/substitution/transposition — i.e.
    Levenshtein/Damerau-Levenshtein distance 1), raise the required length for that submission
    from 200 to 2000 characters. Define this as a small pure function so it's unit-testable in
    isolation (ContactPermissionDecision-style, see contacts/ContactPermissionDecision.kt for
    the pattern this repo already uses for this kind of pure decision logic).
  • Required email field: add an email OutlinedTextField (standard email-format
    validation — e.g. android.util.Patterns.EMAIL_ADDRESS), required for Submit to be enabled.
    This needs a new field end-to-end: ReportReviewState.email, a setter on the view model, and
    a new field on DebugReport (reporting/DebugReport.kt) so it round-trips through
    toSubmissionPayload()/toStorageJson()/fromStorageJson() — it's a flat JSON DTO with no
    Room migration involved, so this is a straightforward addition there.
  • Password-support notice: add a static notice on the review/submit screen: "LibreMail
    does not help with lost/forgotten password issues." (Pairs with #161's confirmation copy,
    which reiterates that submissions aren't guaranteed a response.)

Acceptance criteria

  • Submit cannot succeed with fewer than 200 characters (2000 if a password-like word appears), a
    missing/invalid email, or content that fails the low-effort heuristic.
  • The counter, red-state feedback, English-only note, and password-support notice are all visible
    on the review screen.
  • JVM unit tests cover the length thresholds, the password 1-edit-distance detection, and the
    low-effort heuristic's true/false positives.

Relevant files

  • ui/reporting/ReportReviewScreen.kt, ui/reporting/ReportReviewViewModel.kt,
    reporting/DebugReport.kt, res/values/strings.xml (report_* block).

Dependencies / notes

  • The new required email field is PII collected specifically for a user-initiated submission (data
    the user is choosing to hand over for a reply, distinct from the report's own best-effort
    anonymization). If/when the Cloudflare ingest pipeline (#33/#34) lands, make sure its
    PII-anonymization pass (#34) doesn't strip or clash with this intentionally supplied contact
    address, and that its handling is covered by the same privacy documentation referenced there.
  • Pairs with #161 (submission confirmation experience).
## Context `ReportReviewScreen.kt` / `ReportReviewViewModel.kt` today collect an optional, unvalidated `comment` (`OutlinedTextField`, label "What went wrong? (optional)") and submit unconditionally (the Submit button is disabled only while `SubmitUiState.SUBMITTING`). There is no minimum length, no content-quality check, and no email field at all — `DebugReport` (`reporting/DebugReport.kt`) has no field to carry one. This ticket adds friction against low-effort submissions and collects a reply-to address. ## Scope - [ ] **Minimum length, enforced:** require 200 characters in the comment field before Submit is enabled (mirror the existing `enabled = state.submit != SubmitUiState.SUBMITTING` check in `ReportReviewScreen.kt` with an added length condition, backed by new validation state in `ReportReviewViewModel`). - [ ] **Live counter:** show "x/200" below the text field, updating as the user types. - [ ] **Invalid-submit feedback:** if the user taps Submit while under the threshold (relevant once the button itself is only *disabled*, some users tap disabled controls or arrive via accessibility tools) — or, if the button stays enabled and this is meant as inline validation instead, tapping Submit under-length turns the counter text and the field's outline red. Resolve which of these two interaction models is intended before implementing (the ticket's wording suggests the button *both* stays non-functional under threshold *and* gives red error feedback on an attempted tap — clarify with the reporter if ambiguous). - [ ] **English-only note:** a short static string near the comment field noting the maintainer only reads English. - [ ] **Low-effort content heuristic:** reject comments that are nonsensically repeating characters, repeated whitespace runs, or otherwise don't resemble real words/language. This needs to stay a cheap heuristic (e.g. longest repeated-character run, repeated-whitespace run, ratio of distinct "word" tokens to total length) — not a language model or dictionary lookup. Define the exact thresholds during implementation and unit-test them against both false positives (real short complaints) and the obvious abuse cases (`"aaaaaaa...`", `"asdf asdf asdf"`, etc.). On failure, show exactly: "Please ensure your message is detailed enough for submission." — deliberately generic, so the heuristic itself isn't disclosed/game-able. - [ ] **Password-mention escalation:** if the comment contains the word "password" or a 1-character-edit variant of it (insertion/deletion/substitution/transposition — i.e. Levenshtein/Damerau-Levenshtein distance 1), raise the required length for *that* submission from 200 to 2000 characters. Define this as a small pure function so it's unit-testable in isolation (`ContactPermissionDecision`-style, see `contacts/ContactPermissionDecision.kt` for the pattern this repo already uses for this kind of pure decision logic). - [ ] **Required email field:** add an email `OutlinedTextField` (standard email-format validation — e.g. `android.util.Patterns.EMAIL_ADDRESS`), required for Submit to be enabled. This needs a new field end-to-end: `ReportReviewState.email`, a setter on the view model, and a new field on `DebugReport` (`reporting/DebugReport.kt`) so it round-trips through `toSubmissionPayload()`/`toStorageJson()`/`fromStorageJson()` — it's a flat JSON DTO with no Room migration involved, so this is a straightforward addition there. - [ ] **Password-support notice:** add a static notice on the review/submit screen: "LibreMail does not help with lost/forgotten password issues." (Pairs with #161's confirmation copy, which reiterates that submissions aren't guaranteed a response.) ## Acceptance criteria - Submit cannot succeed with fewer than 200 characters (2000 if a password-like word appears), a missing/invalid email, or content that fails the low-effort heuristic. - The counter, red-state feedback, English-only note, and password-support notice are all visible on the review screen. - JVM unit tests cover the length thresholds, the password 1-edit-distance detection, and the low-effort heuristic's true/false positives. ## Relevant files - `ui/reporting/ReportReviewScreen.kt`, `ui/reporting/ReportReviewViewModel.kt`, `reporting/DebugReport.kt`, `res/values/strings.xml` (`report_*` block). ## Dependencies / notes - The new required email field is PII collected specifically for a user-initiated submission (data the user is choosing to hand over for a reply, distinct from the report's own best-effort anonymization). If/when the Cloudflare ingest pipeline (#33/#34) lands, make sure its PII-anonymization pass (#34) doesn't strip or clash with this *intentionally supplied* contact address, and that its handling is covered by the same privacy documentation referenced there. - Pairs with #161 (submission confirmation experience).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: JMR-dev/LibreMail#159