mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-08 00:19:42 +02:00
feat(mobile): shell keyboard bar with a one-shot Ctrl modifier (#262)
The mobile accessory bar was built around coding-agent commands, so a shell session had no way to send Ctrl chords at all. A shell-mode session now gets its own bar automatically: Ctrl, Esc, Tab, four arrows, paste, dismiss. Agent sessions (claude, codex, opencode, gemini, antigravity) keep the existing bar unchanged. Ctrl is a one-shot modifier: tap it and it lights up, the next character typed on the system keyboard is sent as its control byte, and Ctrl disarms. Tapping it again cancels. That puts Ctrl+C/D/Z/R/L/A/E/W/U/K on a nine-button bar without a button per chord. Implementation notes: * The interception lives in terminal.onData, not a keydown handler: a virtual keyboard reports no usable key events, so the character only exists as onData text. It sits after shouldSuppressTerminalQueryResponse (xterm answers DA/CPR queries through onData too, and letting one of those spend the modifier would silently eat the user's Ctrl) and before every send path, so the control byte follows the normal control-char route. * ctrlByteFor() maps `code & 0x1f` over @A-Z[\]^_ and a-z, plus Ctrl+Space = NUL and Ctrl+? = DEL. Characters with no control equivalent pass through unchanged, like a hardware keyboard. * The bar now separates the base layout (the extendedKeyboardBar setting) from the effective one, resolved per session by refreshForActiveSession(). A settings save during a shell session cannot yank the bar away, and switching back to an agent tab restores the user's choice. * Ctrl disarms on use, a second tap, any other accessory key, a session switch, keyboard dismissal and a layout swap. * Ctrl joins the refocus set, so tapping it keeps the terminal focused and the keyboard open. * The armed style needs three classes to outrank mobile.css's light-skin .accessory-btn rule at (0,2,1). Verified end to end against a real shell session on an isolated instance: tapping Ctrl then typing c interrupted a running `sleep 300` (^C in the pane), the modifier disarmed, plain typing stayed literal, Ctrl+L cleared, and a cancelled Ctrl typed a literal c. Tests: test/mobile-shell-keyboard.test.ts (new, runs in CI) covers the mapping table, layout selection per session mode, base-mode memory and every disarm path; test/mobile/keyboard.test.ts adds nine browser regressions that drive the real xterm with page.keyboard.type() and assert on the bytes that would go out. Closes #262 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -848,9 +848,11 @@ class CodemanApp {
|
||||
SwipeHandler.init();
|
||||
VoiceInput.init();
|
||||
KeyboardAccessoryBar.init();
|
||||
// Apply keyboard bar mode from settings
|
||||
// Apply keyboard bar mode from settings. Always set it (not only when the
|
||||
// extended bar is on) so the bar's remembered agent-session layout matches
|
||||
// the setting before the first shell session swaps in the terminal bar.
|
||||
const _kbSettings = this.loadAppSettingsFromStorage();
|
||||
if (_kbSettings.extendedKeyboardBar) KeyboardAccessoryBar.setMode('extended');
|
||||
KeyboardAccessoryBar.setMode(_kbSettings.extendedKeyboardBar ? 'extended' : 'simple');
|
||||
this.applyHeaderVisibilitySettings();
|
||||
this.restorePlanUsageChip();
|
||||
this.applySkin();
|
||||
@@ -4457,6 +4459,10 @@ class CodemanApp {
|
||||
this.loadAttachmentHistory?.(sessionId);
|
||||
}
|
||||
this._updateLocalEchoState();
|
||||
// Shell sessions get the terminal keyboard bar, agent sessions the command
|
||||
// bar (issue #262). Also disarms a one-shot Ctrl left over from the tab we
|
||||
// just left, so it can never fire against the session we just opened.
|
||||
if (typeof KeyboardAccessoryBar !== 'undefined') KeyboardAccessoryBar.refreshForActiveSession();
|
||||
|
||||
// Restore flushed offset AND text IMMEDIATELY so backspace/typing work during
|
||||
// the async buffer load. Without this, the offset is 0 during the
|
||||
|
||||
Reference in New Issue
Block a user