Skip to content

feat(ui): floating ball with configurable bindings, new gestures & full i18n - #982

Open
unixcs wants to merge 9 commits into
spacering-net:mainfrom
unixcs:feat/floating-ball
Open

unixcs wants to merge 9 commits into
spacering-net:mainfrom
unixcs:feat/floating-ball

Conversation

@unixcs

@unixcs unixcs commented Oct 18, 2026

Copy link
Copy Markdown

Summary

Rebased on latest main (supersedes the earlier #979, which was based on the previous release and has been closed).

Floating ball enhancements:

  • Configurable action bindings for tap / double-tap / swipe gestures (9 new bindable actions with guards and feedback)
  • Expanded gesture vocabulary: arrow-style swipes (up/down/left/right, diagonals) recognized
  • Three ball sizes; gesture hint pill; per-binding settings labels with full i18n (zh/en locale files rebuilt on upstream base)
  • Fixed layout: keep the ball clear of the composer and status bar

Tested on Linux (server build + web) — real-device usage verified across two machines.

Thanks for reviewing!

fengx added 9 commits October 18, 2026 15:42
Replaces the Tampermonkey userscript, which could not work on the phone
(Chrome has no extensions there) and whose stop action matched a button
label codeg never renders.

The gesture vocabulary is MindFS's blue-ring menu, kept in a pure module so
the tracking rules are unit-tested: tap/double tap/long press plus eight
cardinal and diagonal strokes, with two-stage folds anchored at each turn.

Actions dispatch through the workspace contexts this controller already
owns (tabs, panels, zoom, the active ACP connection), so nothing has to
synthesize keyboard events. Off by default; enabled from Appearance
settings, which also resets the stored position.
Adds a component suite for the ball (hidden until enabled, tap/double
tap/long press, swipe and two-stage trails, drag persistence, Escape) and
stubs the providers it now reaches in the chrome-controller test, which
was failing to import the ACP context through the new imports.

jsdom has no PointerEvent coordinates, so the helpers dispatch MouseEvents
carrying the pointer event's type instead.
The bottom-right default landed on the status bar's MCP light and alerts
badge (measured at 390x844 and 1280x800), and the composer's send button
sits just above it. Default to the right edge at 55% height, the one band
empty on both phone and desktop, and cap the panel height to the space
left on its side so the action list scrolls instead of running off-screen.
- 12 new path gestures: down family single strokes (down/downLeft/downRight
  now first-class) and the compound pairs from the owner's list (downUp,
  upThenDownRight, downThenUpRight, rightThenUp/Down, downThenRight/Left,
  downRightThenUp, downLeftThenUp)
- foldTrail gains all 9 missing folds: without them the jitter-replacement
  rule silently turned 8 of the 12 requested compounds into other gestures
- end() no longer requires origin displacement: a round trip drawn cleanly
  back to its start used to be dropped
- 10 new actions in the vocabulary (todos/canvas/agents/rename/cycle...)
  with default bindings; stopGenerating stays on an inconspicuous compound
- tests: 13 passing, downward-stroke semantics reversed per new table
…ture hint pill, three ball sizes

- bindings overrides: per-gesture action map in appearance settings
  (null = user-cleared, missing key = default), persisted per window,
  cross-window synced; fire() and the cheat sheet read the override
- gesture feedback: the ball follows the finger during a swipe and a hint
  pill names the action the trail would fire (previewGesture in the engine,
  so pill and commit can never disagree); snap-back via transform
- three size presets (small 36 / medium 40 / large 46, default large) with
  icon scaling, plus a 6px transparent hit-slop halo so the small preset
  still meets the 44px touch minimum
- settings UI: size select, per-gesture binding rows, favorite-agent chips
  (cap 3) — all under the existing floating-ball section
- i18n: 12 new gesture names + 10 new action names + settings copy across
  all ten locales
…nd feedback

- openTodos/openTodosNew/openAutomations/openCanvas route the workbench;
  openTodosNew parks a task draft so the composer opens on an already-active
  tasks route too
- openAgents/openSystemAdmin open the settings window at the section
- renameConversation dispatches a global event carrying the DB id; the
  conversation header whose id matches opens its rename dialog (multi-tab
  safe); drafts get a toast instead
- openSessionFolder opens the aux file tree, guarded on an active folder
- cycleAgent cycles enabled+available agents on the active draft tab via
  confirmDraftAgent; on a saved conversation it opens a fresh draft pinned
  (forceAgent) to the next agent; cycleFavoriteAgent restricts the cycle to
  the user's favorite list from floating-ball settings
- FloatingBall.toasts i18n keys across all 12 locale files
- Settings screen gesture/action labels now read the translated
  FloatingBall namespace (arrows: ↑↓←→, compound '↑ then ←'), instead of
  the untranslated AppearanceSettings English mirror
- New actions: openBallBindings, cycleRunningSessions (0/1/2+ running
  semantics via ACP connection status), cycleRecentSessions (LRU queue
  + depth setting 2-4), deleteCurrentConversation (reuses header
  confirm dialog), openImportSessions, togglePinConversation,
  focusModeSelector (signal prop chain to MessageInput),
  togglePlanFullAccess (plan substring + matchFullAccessMode),
  openCollaboration; new actions ship unbound by default
- New modules: recent-sessions-prefs (localStorage LRU, capacity 8,
  corrupted-storage tolerant), floating-ball-session-events
  (conversationId-filtered CustomEvents, null-matches-null)
- tab-store: remember recent conversation on focusTab/bindConversationTab
- 10 locales updated (parity test enforced); 2 new unit test files
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