Skip to content

fix(two-thumb): clear stale stroke buffer so re-typed words don't accumulate geometry (#7)#9

Open
SHAWNERZZ wants to merge 1 commit into
mainfrom
fix/two-thumb-stale-stroke-on-retry
Open

fix(two-thumb): clear stale stroke buffer so re-typed words don't accumulate geometry (#7)#9
SHAWNERZZ wants to merge 1 commit into
mainfrom
fix/two-thumb-stale-stroke-on-retry

Conversation

@SHAWNERZZ

Copy link
Copy Markdown
Owner

Fixes #7.

Problem

Building a word from a tap stem + a swipe (e.g. tap do, swipe the rest → doesn't) is the intended multi-part flow, and space stays the word-submission point. But when such a word mis-recognized and you backspaced to retry, the previous stroke geometry stuck around and each retry built an ever-longer garbage word.

Root cause (traced end-to-end)

  • The merged stroke lives in WordComposer.mInputPointers. It's intentionally not cleared by reset()/backspace (so a gesture commit can re-feed it via setBatchInputWord), and ResizableIntArray.addAt(index) overwrites in place without shrinking the length.
  • So after a word is abandoned via backspace, the raw buffer keeps its length. Re-typing the stem overwrites only the leading indices; the stale tail survives. The next swipe snapshots the whole stale buffer as the merged-trail extend base → an ever-longer word that grows with each retry.
  • PR fix(two-thumb): clear stale merged-trail extend-base on delete + gesture lifecycle AsafMah/LeanType#61 cleared the extend-base flag and mLiveStroke, but not the mInputPointers buffer the base is re-armed from — so the leak persisted through that fix.

Fix

Reset mInputPointers when the first tap of a fresh word lands (newIndex == 0 in WordComposer.applyProcessedEvent). This:

  • covers every abandonment path (whole-word / batch / per-char-to-empty / cursor move),
  • never touches the gesture-commit flow (batch mode is guarded),
  • preserves multi-part composition (a tap extending a gesture has newIndex > 0),
  • can't disturb mid-word backspace coordinates for normal typing.

Testing

  • New WordComposerTest.testFreshWordResetsStaleInputPointers: a stale 5-point buffer surviving reset() is dropped to 1 point on the first fresh tap (fails pre-fix).
  • Full :app:testOfflineDebugUnitTest: 243 tests, 12 failed = main baseline (242) + this PR's 1 new test, with the identical 12 pre-existing/environment-dependent failures. Zero new failures; normal-typing/autocorrect/recorrection tests unaffected.
  • Validated on-device: re-typing a mis-recognized multi-part word now recognizes cleanly each retry instead of growing; technology/silo-style multi-part and normal typing still work.

🤖 Generated with Claude Code

…umulate geometry (#7)

When a multi-part word (tap a stem, then swipe the rest — e.g. "do" + swipe ->
"doesn't") mis-recognizes and the user backspaces to retry, the previous stroke
geometry stuck around and each retry built an ever-longer garbage word.

Root cause: the merged stroke lives in WordComposer.mInputPointers, which is
intentionally NOT cleared by reset()/backspace (so a gesture commit can re-feed
it via setBatchInputWord), and ResizableIntArray.addAt(index) overwrites in place
WITHOUT shrinking the length. So after a word is abandoned via backspace, the raw
buffer keeps its length; re-typing the stem overwrites only the leading indices and
the stale tail survives. The next swipe then snapshots the whole stale buffer as the
merged-trail extend base, producing an ever-longer word that grows with each retry.
PR AsafMah#61 cleared the extend-base flag and mLiveStroke, but not the mInputPointers
buffer the base is re-armed from, so the leak persisted through that fix.

Fix: reset mInputPointers when the FIRST tap of a fresh word lands (newIndex == 0 in
WordComposer.applyProcessedEvent). This covers every abandonment path (whole-word /
batch / per-char-to-empty / cursor move), never touches the gesture-commit flow
(batch mode is guarded above), preserves multi-part composition (a tap EXTENDING a
gesture has newIndex > 0), and can't disturb mid-word backspace coordinates for
normal typing. Space remains the word-submission point.

Test: WordComposerTest.testFreshWordResetsStaleInputPointers asserts a stale 5-point
buffer surviving reset() is dropped to 1 point on the first fresh tap. Full
:app:testOfflineDebugUnitTest shows zero new failures vs the main baseline (same 12
pre-existing/environment-dependent failures).

Fixes #7.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

Two-thumb: gesture stroke isn't cleared on backspace — re-typing a mis-recognized word accumulates geometry (words grow each retry)

1 participant