Skip to content

feat(symbols): swipe-up on a key emits its popup symbol (#32 MVP)#69

Closed
AsafMah wants to merge 4 commits into
devfrom
feat/c2a-swipe-up-symbol
Closed

feat(symbols): swipe-up on a key emits its popup symbol (#32 MVP)#69
AsafMah wants to merge 4 commits into
devfrom
feat/c2a-swipe-up-symbol

Conversation

@AsafMah

@AsafMah AsafMah commented Jun 7, 2026

Copy link
Copy Markdown
Owner

Implements the MVP of #32 (C2a) — swipe-up on a key for fast symbols, built by a subagent, coordinator-reviewed + compiled.

What

A quick swipe-up on a non-top-row key emits that key's first popup-key (the symbol you'd get from long-press) with no long-press delay. New PointerTracker.tryStartSwipeUpSymbol, called in onMoveEvent right after the existing shortcut-row gate.

How it stays safe

  • Same vertical-swipe threshold as the shipped shortcut-row gate (>=~10dp up, |dY|>|dX|).
  • Guarded to non-top rows (mShortcutTopRowSwipeAllowed) so it doesn't collide with the top-row shortcut up-swipe; down-swipe shortcut unchanged.
  • Sets mIsDetectingGesture=false + cancelTrackingForAction() so glide is unaffected and the base letter isn't typed.
  • Emits through the standard listener (onCodeInput / onTextInput for multi-codepoint or outputText popups); no-op if the key has no popup.

Needs on-device check (please feel out)

  1. Glide interference: middle-row keys now have a vertical-swipe gate they didn't before — confirm an upward glide isn't caught as a symbol-swipe.
  2. Semantics: for letter keys the first popup is usually an accent (é for e), symbols only on symbol keys. Is “first popup” the right thing, or should swipe-up map to a number/symbol layer? (That'd be a design follow-up.)
  3. No haptic/press feedback on the swipe-up emit (consistent with the shortcut-row path) — tell me if you want it.

Base dev.

Quick swipe-up on a non-top-row key emits that key's primary popup-key (the symbol
you'd get from long-press) without the long-press delay. Reuses the shortcut-row
vertical-swipe gate's threshold (>=~10dp up, |dY|>|dX|), guarded to non-top rows
(mShortcutTopRowSwipeAllowed) so it doesn't collide with the top-row shortcut
up-swipe; bottom-row down-swipe shortcut unchanged. Sets mIsDetectingGesture=false
and cancelTrackingForAction so glide is unaffected and the base letter isn't typed.

Emits via the standard listener (onCodeInput / onTextInput for multi-codepoint or
outputText popups). No-op if the key has no popup.
@AsafMah AsafMah marked this pull request as draft June 7, 2026 08:26
…de (#32)

The first version decided 'symbol' on the first 10dp of upward motion in onMoveEvent
and killed gesture detection there, so it preempted every upward glide. Reworked:

- Decision moved to finger-UP (onUpEventInternal), placed AFTER the sInGesture path
  returns — so a real glide is handled by the gesture path and never reaches the
  symbol check. Gesture detection is never touched during the move.
- Fires only for a deliberate up-flick: >= 2 steps up, more vertical than horizontal,
  drift <= one key width, on a key that has a popup. Emits the start key's first
  popup symbol instead of the base letter.
- Gated behind new opt-in pref PREF_SWIPE_UP_SYMBOL (default OFF), in Two-Thumb
  Typing settings, so glide users are unaffected unless they enable it.
- Captures the down key + position (mSwipeUpStart*) since mStartX/Y get adjusted
  during slider moves. Removed the broken onMove path.
@AsafMah AsafMah marked this pull request as ready for review June 7, 2026 08:38
AsafMah added 2 commits June 7, 2026 11:46
… commit) (#32)

Previous rework placed the check AFTER the sInGesture path, so an up-flick that
engaged the gesture recognizer (most flicks do) was treated as a glide and the
symbol never fired. Move the check BEFORE the gesture commit: a clear vertical
up-flick (>=2 steps up, |dY|>|dX|, drift <= one key width) cancels any in-progress
batch (cancelBatchInput) and emits the symbol. Horizontal glides aren't flicks ->
fall through untouched -> glide still works.
The 'buy' case proved net-displacement can't tell an up-flick from an upward glide
(b->u->y is net-up). The only honest discriminator on the middle rows is a HOLD: a
glide is continuous, a deliberate symbol-access is up-then-pause.

- On an upward flick from the start key, arm a hold timer; every subsequent move
  restarts it, so it only fires once the finger STILLS (a continuous glide never
  lets it fire). Does NOT consume the move event, so gesture detection runs in
  parallel and gliding (incl. 'buy') is unaffected.
- On fire (via onLongPressed), open the START key's popup-keys panel like long-press
  (drag to pick), cancelling any in-progress gesture.
- Replaces the on-release emit. Still opt-in (PREF_SWIPE_UP_SYMBOL, default off).
@AsafMah

AsafMah commented Jun 7, 2026

Copy link
Copy Markdown
Owner Author

Shelving this approach. A fluid swipe-up-to-symbol can't coexist with glide on the middle/bottom rows: 'up' there is a glide direction (e.g. gliding "buy" = b->u->y is net-upward, indistinguishable from a deliberate up-flick by shape). Tried: eager-on-move (broke glide), decide-on-release (couldn't fire / 'buy' still triggered it), and swipe-up+hold (kills the fluidity that's the whole point, and the hold never reliably fired). The only fluid+unambiguous up-motion is off the TOP edge, which the shortcut-row swipe already uses. Branch feat/c2a-swipe-up-symbol kept for reference if we revisit with a non-glide-overlapping trigger.

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