Skip to content

fix(dictionary): add full email/URL token to personal dictionary#23

Merged
leinss merged 1 commit into
mainfrom
feature/email-dict
Jul 12, 2026
Merged

fix(dictionary): add full email/URL token to personal dictionary#23
leinss merged 1 commit into
mainfrom
feature/email-dict

Conversation

@leinss

@leinss leinss commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary

The "Add to dictionary" toolbar key (and its long-press-Enter action) added the whole token only when text was selected. With no selection it fell back to getWordRangeAtCursor, which splits on . and @ (word separators) unless URL detection is enabled — and URL detection is off by default. So tapping the key after typing an email address added only the trailing fragment (e.g. xyz of newsletter@leinss.xyz), never the full address, and there was no obvious way to add the address without first manually selecting it.

Changes

  • StringUtils: add pure, unit-tested getWhitespaceDelimitedTokenAtCursor() — returns the whitespace-delimited token straddling the cursor, trimming only outer word separators while keeping interior . / @ / _ so a full email or URL is preserved.
  • RichInputConnection: add getWhitespaceDelimitedTokenAtCursor() that fetches the surrounding text and delegates to the pure helper.
  • InputLogic: the no-selection add-to-dictionary path now uses it instead of getWordRangeAtCursor (drops the now-unused script argument).
  • Tests: cover email at end / mid-token / followed by text, trailing-punctuation and bracket trimming, URL, plain word, whitespace-only, and empty input.

Why this is the minimal fix

Capture reads committed text via the InputConnection, so it is independent of composing state and input type. It works in a native email field, a web email field, and a generic web text field (where only the fragment composes). No change to the suggestion engine or tokenizer, and automatic learning stays gated per field type — only this explicit user action writes to the system user dictionary.

Test plan

  • make check — unit tests + lint: 350 tests, 0 failures, 7 skipped; lint clean (0 non-baseline errors)
  • Emulator E2E (Pixel 6 API 34):
    • Native email field (Contacts editor, textEmailAddress): typed newsletter@leinss.xyz, tapped Add-to-dictionary → toast Added "newsletter@leinss.xyz" to dictionary (full address)
    • Fresh generic field: typed prefix newsl → full address suggested → tapped suggestion → full address inserted
    • Browser <input type="email">: whole token composes; add works
    • Browser <input type="text"> (only the xyz fragment composes — the reported case): Add-to-dictionary still added the full newsletter@leinss.xyz

The "Add to dictionary" toolbar key added the whole token only when text
was selected; with no selection it fell back to getWordRangeAtCursor,
which splits on "." and "@" (word separators) unless URL detection is
enabled — off by default. Tapping the key after typing an email therefore
added only the trailing fragment (e.g. "xyz" of "newsletter@leinss.xyz"),
never the address.

Capture the whole whitespace-delimited token straddling the cursor for the
no-selection path, trimming only outer word separators while keeping the
interior "." / "@" that make it an email or URL. Reads committed text via
the InputConnection, so it works regardless of the composing state or input
type (native email field, web email field, or generic web text field where
only the fragment composes). Learning stays gated per field type; this
explicit action writes straight to the system user dictionary.

- StringUtils: add pure getWhitespaceDelimitedTokenAtCursor()
- RichInputConnection: fetch surrounding text and delegate to it
- InputLogic: use it for the no-selection add-to-dictionary path
- tests: cover email/URL/bracket/punctuation/whitespace cases
@leinss
leinss merged commit 7e288a1 into main Jul 12, 2026
1 check passed
@leinss
leinss deleted the feature/email-dict branch July 12, 2026 12:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant