fix(client): harden inline rename against CJK, mid-rename deletion, and double-fire
Three follow-up fixes to the inline rename input introduced in #81:
1. IME composition guard. Pressing Enter to confirm a Chinese pinyin
candidate (or any IME composition) was committing the half-composed
text as the session name. Skip the keydown handler when isComposing
is true or when keyCode is the legacy 229 sentinel that older
Safari/Edge versions report on the Enter that triggers compositionend.
2. Ghost tab on mid-rename deletion. If a session was deleted via SSE
while its tab was being renamed, the render-skip flag suppressed
_renderSessionTabs() and the orphaned <input> stayed on screen until
blur — at which point the rename PUT 404'd against the dead session.
Replace the boolean _inlineRenameActive with a _activeRename
{sessionId, cancel} object so _cleanupSessionData can abort an
in-flight rename targeting the deleted session, and finishRename
skips the API call when the session is gone.
3. Stuck-flag risk. Move the settle-once guard into a closure-local
`settled` boolean so blur / Enter / Escape / external cancel all
converge to a single idempotent path. Register _activeRename only
after the input is fully wired so a throw earlier in setup can't
strand state.
Adds test/inline-rename.test.ts with 7 Playwright tests that drive
startInlineRename via page.evaluate() against a stubbed session and
synthetic .tab-name node — no real PTY/tmux needed, runs in ~1.3s.
Also fixes test/mobile/helpers/server.ts which imported the WebServer
via a path one directory short of the repo root, breaking the entire
mobile test suite under the main vitest config.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> A
arkon committed
7beec7194a316f29310aa57fde5032826e8b3f05
Parent: dcc814f