Skip to content

fix: mobile CJK input, terminal flicker, and layout overflow#47

Merged
Ark0N merged 1 commit intoArk0N:masterfrom
TeigenZhang:fix/mobile-cjk-input-and-layout
Mar 24, 2026
Merged

fix: mobile CJK input, terminal flicker, and layout overflow#47
Ark0N merged 1 commit intoArk0N:masterfrom
TeigenZhang:fix/mobile-cjk-input-and-layout

Conversation

@TeigenZhang
Copy link
Contributor

Summary

  • Terminal flicker fix: prevent buffer-load race conditions and redundant viewport clears during resize — terminal no longer flashes blank on mobile
  • CJK input rewrite: use InputEvent.inputType to handle Android IME composition correctly — Chinese punctuation, English text, and long-press backspace all work now
  • Settings UI: add "CJK Input" toggle (Settings > Input) so users can enable/disable the dedicated IME input field without server env vars
  • Mobile layout: fix welcome screen horizontal overflow on phones (<430px)

Details

Terminal flicker (app.js, terminal-ui.js)

  • Skip buffer-recovered / clear-terminal SSE events while _isLoadingBuffer is true
  • Move \x1b[3J\x1b[H\x1b[2J (scrollback+viewport clear) inside the dimension-change guard — only clear when SIGWINCH is actually sent
  • Sync _lastResizeDims on explicit resize to prevent double-clear

CJK input (input-cjk.js)

  • inputType dispatch: insertText during composition → flush immediately (punctuation, confirmed words); insertCompositionText → wait for compositionend (pinyin candidates)
  • Enter key: removed !e.isComposing guard + force-reset _composing — Enter always sends on Android
  • Phantom character (U+200B): textarea always contains a zero-width space so Android long-press backspace generates continuous deleteContentBackward events at native repeat rate
  • Composition start clears phantom; flush restores it

CJK settings (index.html, settings-ui.js, app.js)

  • New cjkInputEnabled toggle in Settings > Input section
  • Device-specific (not synced to server) — mobile and desktop can have different defaults
  • INPUT_CJK_FORM=ON env var still works as server-side override

Mobile 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 input
  • Synchronous terminal.focus() in user-gesture context for iOS keyboard activation
  • Tap-to-refocus on terminal touch area

Test plan

  • Mobile (Android + Chinese IME): verify Chinese characters, punctuation (,。!), and English text all input correctly with CJK Input enabled
  • Mobile: long-press backspace deletes continuously
  • Mobile: welcome screen fits within viewport (no horizontal scroll)
  • Mobile: terminal doesn't flicker on tab switch or resize
  • Desktop: CJK Input toggle off by default, no regressions
  • Settings > Input: CJK Input toggle shows/hides the textarea immediately on save

🤖 Generated with Claude Code

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)
Copy link
Owner

@Ark0N Ark0N left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thorough review, no issues found. Clean, well-documented work across all 8 files.

Highlights:

  • inputType dispatch in input-cjk.js correctly handles Android IME semantics — insertText vs insertCompositionText is the right discriminator
  • Phantom character (U+200B) for Android long-press backspace is clever and _flush() idempotency prevents double-sends from deferred compositionend
  • 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 across selectSession, runClaude, and runOpenCode

Thank you very much for the many contributions already — this is excellent mobile work. 🎯

@Ark0N Ark0N merged commit b1d3b27 into Ark0N:master Mar 24, 2026
1 check passed
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.

2 participants