fix: mobile CJK input, terminal flicker, and layout overflow#47
Merged
Ark0N merged 1 commit intoArk0N:masterfrom Mar 24, 2026
Merged
Conversation
Terminal flicker: - Skip buffer-recovered/clear-terminal events during active buffer load to prevent competing clear+rewrite cycles (app.js) - Move viewport+scrollback clear inside dimension-change guard so resize without actual SIGWINCH doesn't blank the terminal (terminal-ui.js) - Sync _lastResizeDims on explicit resize to prevent redundant clears CJK input rewrite (input-cjk.js): - Use InputEvent.inputType to distinguish insertText (final) from insertCompositionText (tentative) — fixes Chinese punctuation and English text being swallowed during Android IME composition - Remove isComposing guard on Enter so it always sends - Phantom character (U+200B) keeps textarea non-empty so Android long-press backspace generates continuous deleteContentBackward events at the keyboard's native repeat rate CJK input settings: - Add "CJK Input" toggle in Settings > Input (index.html, settings-ui.js) - Store as device-specific setting (cjkInputEnabled), not synced to server - Replace INPUT_CJK_FORM env var dependency with user-controlled setting (env var still works as server override) Mobile layout: - Fix welcome screen overflow on phones by constraining .welcome-content to calc(100vw - 1.5rem) (mobile.css) - Move xterm helper textarea on-screen for touch devices to fix iOS keyboard input (styles.css) - Focus terminal synchronously in user-gesture context for iOS Safari keyboard activation (session-ui.js, app.js) - Refocus terminal on tap (not scroll) in touch handler (terminal-ui.js)
Ark0N
approved these changes
Mar 24, 2026
Owner
Ark0N
left a comment
There was a problem hiding this comment.
Thorough review, no issues found. Clean, well-documented work across all 8 files.
Highlights:
inputTypedispatch ininput-cjk.jscorrectly handles Android IME semantics —insertTextvsinsertCompositionTextis the right discriminator- Phantom character (
U+200B) for Android long-press backspace is clever and_flush()idempotency prevents double-sends from deferredcompositionend - Terminal flicker fix properly gates the clear sequence behind the dimension-change guard — no more blank flashes from clearing without a subsequent Ink redraw
- iOS Safari focus pattern (synchronous before
await) applied consistently acrossselectSession,runClaude, andrunOpenCode
Thank you very much for the many contributions already — this is excellent mobile work. 🎯
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
InputEvent.inputTypeto handle Android IME composition correctly — Chinese punctuation, English text, and long-press backspace all work nowDetails
Terminal flicker (
app.js,terminal-ui.js)buffer-recovered/clear-terminalSSE events while_isLoadingBufferis true\x1b[3J\x1b[H\x1b[2J(scrollback+viewport clear) inside the dimension-change guard — only clear when SIGWINCH is actually sent_lastResizeDimson explicit resize to prevent double-clearCJK input (
input-cjk.js)inputTypedispatch:insertTextduring composition → flush immediately (punctuation, confirmed words);insertCompositionText→ wait forcompositionend(pinyin candidates)!e.isComposingguard + force-reset_composing— Enter always sends on AndroidU+200B): textarea always contains a zero-width space so Android long-press backspace generates continuousdeleteContentBackwardevents at native repeat rateCJK settings (
index.html,settings-ui.js,app.js)cjkInputEnabledtoggle in Settings > Input sectionINPUT_CJK_FORM=ONenv var still works as server-side overrideMobile layout (
mobile.css,styles.css,session-ui.js).welcome-content:max-width: calc(100vw - 1.5rem)prevents horizontal overflow.touch-device .xterm-helper-textarea: move on-screen (1px×1px) so iOS Safari accepts keyboard inputterminal.focus()in user-gesture context for iOS keyboard activationTest plan
🤖 Generated with Claude Code