mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-06 15:39:41 +02:00
fix(mobile): close audit findings — desktop focus, claim wiring, CJK setting, ESC passthrough
Adversarial post-rebase audit (11 agents) confirmed four real issues; all fixed: - Desktop tab clicks stopped focusing the terminal: handleSessionTabClick passed preserveKeyboard:false on desktop (KeyboardHandler.keyboardVisible is mobile-only state) and selectSession's ternary mapped explicit false to 'never focus', skipping the gesture-stack focus master relies on. Focus policy now lives solely in _shouldFocusTerminalForTabSwitch() (desktop: always; touch: only while the keyboard is open). - Desktop sizing claims were almost never registered: selectSession's resizes run before _connectWs, so they went over HTTP (which never claims), leaving the arbitration inert in the canonical desktop+phone scenario. ws.onopen now sends a typed resize over the fresh socket — registering the claim and syncing PTY dims after (re)connects. - throttledResize (the main window-resize path) sent untyped HTTP resizes: a rotating phone bypassed a desktop claim, and a desktop narrowing past the tablet breakpoint never released its stale claim. It now sends typed resizes, WS-first, like sendResize. - The cjkInputEnabled App Settings toggle was silently ignored on touch phones/tablets (composer only reachable via the server inputCjkForm override, while the checkbox stayed visible and saveable). The user setting is honored everywhere again; mobile keeps native-input-by- default via the cjkInputEnabled:false mobile default. - _handleCjkInput appended multi-byte ESC sequences (hardware-keyboard arrows/Home/End on the composer) to local-echo pending text, typing raw ESC bytes into the prompt on Enter; they are now forwarded to the PTY like the onData path. Its backspace path also syncs the per-session flushed Maps the way onData does, so tab-switch restore no longer resurrects deleted characters. Defensive: Session.stop() clears desktop sizing claims (a hung client's socket close can lag teardown by a ping cycle), and the claims docblock documents the WS-only tradeoff explicitly. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -2060,6 +2060,12 @@ export class Session extends EventEmitter {
|
||||
* registers them on a desktop-typed resize and releases them on socket
|
||||
* close, so a mobile-only session (no desktop connected) keeps full control
|
||||
* of its own size — including narrowing below the spawn default.
|
||||
*
|
||||
* Deliberate tradeoff: claims are WS-only because only a socket has a
|
||||
* liveness signal. A desktop degraded to the stateless HTTP resize fallback
|
||||
* still applies its typed resizes but holds no claim, so a concurrent phone
|
||||
* can reflow it. This is cooperative UX arbitration, not a security
|
||||
* boundary — untyped (legacy/API) resizes bypass claims by design.
|
||||
*/
|
||||
private _desktopSizeClaims = new Set<symbol>();
|
||||
|
||||
@@ -2188,6 +2194,12 @@ export class Session extends EventEmitter {
|
||||
|
||||
this._clearAllTimers();
|
||||
|
||||
// Drop desktop sizing claims defensively. Sockets normally release their
|
||||
// own claim on close, but a hung client's close event can lag the session
|
||||
// teardown by up to a ping cycle — don't let a stale claim suppress
|
||||
// mobile resizes if this Session object sees any further use.
|
||||
this._desktopSizeClaims.clear();
|
||||
|
||||
// Immediately cleanup Promise callbacks to prevent orphaned references
|
||||
// during the rest of stop() processing (e.g., if mux kill times out)
|
||||
if (this.rejectPromise && !this._promptResolved) {
|
||||
|
||||
Reference in New Issue
Block a user