From 41a209e96ddac00710ed84d7bb748a05e1dcdb0a Mon Sep 17 00:00:00 2001 From: Teigen Date: Sat, 13 Jun 2026 18:49:57 +0800 Subject: [PATCH 1/2] fix(cjk): hide CJK textarea on welcome screen and fix vertical centering - Guard `_updateCjkInputState()` with `activeSessionId` check so the `position: fixed` CJK textarea doesn't float over the welcome overlay - Call `_updateCjkInputState()` in `showWelcome()`/`hideWelcome()` to sync CJK visibility on session enter/leave - Add `padding: 12px 10px` to `.cjk-input-visible textarea` for proper vertical centering of input text --- src/web/public/app.js | 8 +++++++- src/web/public/styles.css | 1 + src/web/public/terminal-ui.js | 6 ++++++ 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/web/public/app.js b/src/web/public/app.js index 29f76167..1d016e35 100644 --- a/src/web/public/app.js +++ b/src/web/public/app.js @@ -2103,7 +2103,13 @@ class CodemanApp { // Mobile defaults ship cjkInputEnabled: false (native terminal input by // default on touch), but an explicit user enable is honored everywhere — // the App Settings toggle must not be a silent no-op on phones. - const showCjk = this._serverCjkOverride || (settings.cjkInputEnabled ?? defaults.cjkInputEnabled ?? false); + // The welcome/home screen (no active session) has nothing to type into. + // Force-hide the CJK textarea there — otherwise the `position: fixed` + // `.cjk-input-visible` rule floats it over the welcome overlay and blocks + // content. Re-synced on session enter/leave via hideWelcome()/showWelcome(). + const cjkUserEnabled = + this._serverCjkOverride || (settings.cjkInputEnabled ?? defaults.cjkInputEnabled ?? false); + const showCjk = cjkUserEnabled && !!this.activeSessionId; cjkEl.classList.toggle('cjk-input-visible', !!showCjk); document.body.classList.toggle('cjk-input-visible', !!showCjk); cjkEl.style.display = showCjk ? 'block' : 'none'; diff --git a/src/web/public/styles.css b/src/web/public/styles.css index 2b5a0e91..39c8aa39 100644 --- a/src/web/public/styles.css +++ b/src/web/public/styles.css @@ -8778,6 +8778,7 @@ kbd { display: block; min-height: 44px; max-height: 96px; + padding: 12px 10px; border: 1px solid rgba(80, 120, 190, 0.55); border-left: none; border-right: none; diff --git a/src/web/public/terminal-ui.js b/src/web/public/terminal-ui.js index 1f8f8577..bba4f302 100644 --- a/src/web/public/terminal-ui.js +++ b/src/web/public/terminal-ui.js @@ -943,6 +943,9 @@ Object.assign(CodemanApp.prototype, { this.loadTunnelStatus(); this.loadHistorySessions(); } + // Home screen has no input target — hide the CJK textarea (activeSessionId + // is null by the time we get here). Guarded: defined on the app object. + this._updateCjkInputState?.(); }, hideWelcome() { @@ -956,6 +959,9 @@ Object.assign(CodemanApp.prototype, { clearTimeout(this._welcomeQrShrinkTimer); qrWrap.classList.remove('expanded'); } + // Entering a session — restore CJK textarea if the user has it enabled + // (activeSessionId is already set by selectSession before this call). + this._updateCjkInputState?.(); }, /** From 8ffb2b0644249d43776b70f7e0fa0361617f9e39 Mon Sep 17 00:00:00 2001 From: "Claude (Codeman maintainer)" Date: Sun, 14 Jun 2026 22:30:09 +0200 Subject: [PATCH 2/2] test(cjk): update the mobile server-override test for the welcome-screen gate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PR gates CJK textarea visibility on an active session (`showCjk = cjkUserEnabled && !!activeSessionId`) so the fixed-position textarea no longer floats over the welcome overlay. That intentionally changes the behavior the existing `shows the CJK textarea on mobile only for server override` test asserted — it set `_serverCjkOverride = true` on a fresh page (no active session) and expected the textarea visible, which now (correctly) resolves to hidden. The test lives in test/mobile/** (excluded from CI), so it wasn't caught by the PR's green CI. Update the test to verify the new, intended behavior: with the server override on it stays hidden on the welcome screen (no active session) and is revealed once a session is active. This is a co-authored review fix; the original change is TeigenZhang's. Verified: tsc, check:frontend-syntax, check:public-assets, prettier all clean. Co-Authored-By: Claude Opus 4.8 (1M context) --- test/mobile/keyboard.test.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/test/mobile/keyboard.test.ts b/test/mobile/keyboard.test.ts index 044c9a59..5032f653 100644 --- a/test/mobile/keyboard.test.ts +++ b/test/mobile/keyboard.test.ts @@ -528,15 +528,24 @@ describe('Virtual Keyboard', () => { expect(afterEnter.sentInputs).toEqual(['hello', '\r']); }); - it('shows the CJK textarea on mobile only for server override', async () => { + it('shows the CJK textarea on mobile for server override only inside an active session', async () => { const state = await page.evaluate(() => { - app._serverCjkOverride = true; - app._updateCjkInputState(); - const input = document.getElementById('cjkInput'); if (!(input instanceof HTMLElement)) return null; + + // Welcome screen (no active session): even with the server override on, the + // fixed-position textarea must stay hidden so it doesn't float over the overlay. + app.activeSessionId = null; + app._serverCjkOverride = true; + app._updateCjkInputState(); + const onWelcomeDisplay = getComputedStyle(input).display; + + // Entering a session reveals it. + app.activeSessionId = 'cjk-server-override-test'; + app._updateCjkInputState(); const cs = getComputedStyle(input); return { + onWelcomeDisplay, display: cs.display, position: cs.position, bottom: cs.bottom, @@ -546,6 +555,7 @@ describe('Virtual Keyboard', () => { }); expect(state).not.toBeNull(); + expect(state?.onWelcomeDisplay).toBe('none'); expect(state?.display).not.toBe('none'); expect(state?.position).toBe('fixed'); expect(Number(state?.zIndex)).toBeGreaterThan(50);