You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Op Android is de chat-invoerbalk (schrijfbox) niet zichtbaar wanneer het on-screen toetsenbord actief is. De invoerbalk schuift achter het toetsenbord. Pas wanneer het toetsenbord wordt verkleind (of gesloten) wordt de schrijfbox weer zichtbaar.
The chat input/composer is hidden behind the on-screen keyboard on Android. Only when the keyboard is shrunk or closed does the input box become visible again.
Het toetsenbord verschijnt en bedekt de schrijfbox; de box is niet te zien of aan te raken zonder het toetsenbord te verkleinen.
Verwacht gedrag / Expected behavior
Wanneer het Android-toetsenbord opent, moet de layout worden verkleind zodat de schrijfbox boven het toetsenbord zichtbaar blijft (vergelijkbaar met android:windowSoftInputMode="adjustResize" of correcte IME-inset-afhandeling). Dezelfde bug in de opencode web-UI is eerder gefixt in anomalyco/opencode#15842.
Omgeving / Environment
App: OpenCode Mobile (Android)
Server: opencode 1.18.18 (opencode serve, verbonden via Tailscale)
Reacted by Mai Thanh Minh, Brisk, ijaron, Haven Madray, Wojciech Kuliński, Shaleen Jain, JuanPardos, Samuel Austin, Eliot Woodrich, Christian and 1 more
Fixed by the merge of #182 into the Qiiks/opencode-mobile maintenance branch (maint/v0.4.16) — shipping in release v0.4.16-maint.1 (APK will be attached there). Upstream review of #182 is still recommended; this merge keeps the fork usable while it waits.
Tested on a physical Pixel 11 Pro running Android 17. Play v0.4.15 reproduces this with both Gboard and a custom Trime IME. The keyboard change in #182 improves the layout but is still 56 dp short: the TextInput overlapped the IME by 106 px in the measured build.
I opened focused follow-up PR #201, which offsets by the complete native-header height (insets.top + 56) and keeps the full composer above the IME in the patched device build.
Follow-up on #201: physical testing caught one more regression in the first offset-based revision — after dismissing the IME, React Native 0.81.5 retained stale bottom padding and the composer did not return to the bottom.
PR #201 has now been updated to use Android keyboardDidShow / keyboardDidHide metrics directly: show applies the reported IME height; hide resets padding to zero. The rebuilt side-by-side APK passed the complete open/close cycle on the Pixel 11 Pro: full composer visible above the keyboard, then restored to the bottom after dismissal.
Can confirm this reproduces consistently when connecting to a self-hosted opencode serve — the composer stays fully behind the soft keyboard while typing. Thanks for looking into it, looking forward to #193/#201 landing. Much appreciated!
Tracking the broader Android IME regression here rather than opening a duplicate.
Authoritative Android evidence covers two keyboard-visible states: (1) a multi-choice question card whose lower choices cannot be usefully scrolled above the IME, and (2) a long multiline composer whose editable viewport/caret becomes unusably constrained. The contribution will preserve recoverable question navigation, use keyboard-aware bounded composer growth with internal scrolling, and cover resize/orientation, accessibility scaling, dismissal, and iOS non-regression.
Reserved clean contribution branch: fix/android-ime-scroll-composer-upstream, based on upstream main at 646f9cbf7743e08115c8121d98c82f48d088a8f4. No implementation, release, or merge has occurred. Device reproduction, root-cause evidence, tests, and independent QA/design review will be attached before a PR is requested.
Passed: npm test (340), npm run typecheck, npm run check:versions; independent code and QA/design review completed.
The physical Pixel 8 Pro post-change install/smoke is deferred: the capacity broker denied the Android build while an active 10 GB iOS build lane holds capacity. No bypass was attempted. Existing reproduction evidence remains at /var/folders/fc/xccpf99d62b5_sc13zpgvjd80000gn/T/opencode/mobile-ime-repro-20260920/.
Physical Pixel candidate smoke result for PR #208: BLOCKED by test environment connectivity. Candidate commit 95b001d loaded on Pixel 8 Pro 38141FDJG00BG7 at 1008x2244; bundle markers and repository gates verified. The installed dev client persisted 127.0.0.1:12400 and could not reach a session; therefore authoritative question-choice and multiline-composer screenshots were not honestly claimable. Evidence: file:///var/folders/fc/xccpf99d62b5_sc13zpgvjd80000gn/T/opencode/mobile-ime-repro-20260920/candidate/. No feature code changed; device/Metro/lease cleanup completed.
PR #208 is ready for maintainer review at 95b001d after final bug-focused review PASS. Pixel 8 Pro QA validated scrollable keyboard-visible choices, pinned navigation, and a usable multiline internal composer viewport: /Users/josh/agents/media/mobile-ime-qa-95b001d-20260921/. Gates: 340 tests, typecheck, version parity. Design PASS; residual risk is one Pixel/IME combination. No merge performed.
Claiming this as the owning lead — Ember, OpenCode Mobile task agent.
Task: fix the Android keyboard hiding the chat input (#194, #156). Branch: fix/keyboard-ime-194. Scope: Android composer + connection-form IME handling only — evaluate open PRs #193/#201/#206/#208 (and #203), merge the best one or land an equivalent fix. No applicationId or dependency changes.
Work Log row: "Fix Android keyboard hiding chat input (#194, #156) — merge one of PRs #193/#201/#206/#208".
Keyboard IME fix — context pack (maintained, DONE, 2026-11-13)
Stage: DONE — merged. Lead: Ember (OpenCode Mobile task agent). Branch: fix/keyboard-ime-194 (head 484e227d305ae76bfaca1be94f2d34a4965ed81d, from main e8444931). Work Log: "Fix Android keyboard hiding chat input (#194, #156) — merge one of PRs #193/#201/#206/#208" (Done). No design/PRD links exist for this fix.
Scope / acceptance: Android composer + connection forms. (a) composer visible above keyboard on open; (b) usable multiline typing (caret/viewport, internal scroll); (c) returns to bottom on dismiss, no stale padding; (d) connection add/edit usable with keyboard; (e) no iOS regression (padding, offset 90).
Stage 1 decisions: All six candidates OPEN + mergeable=false / dirty, stale bases, no CI checks reported on any branch — merge none as-is. Re-implement from scratch: #201 live-IME-height mechanism (base) + #208 bounded multiline composer + scrollable QuestionPrompt; reject #206 (stale v0.4.16 release commit), #203 new dep (owner call), #193 adjustPan (connection part already landed via #216), #182/#208 static insets.top offset alone (contradicted by #201 Pixel 11 Pro measurement: 56 dp / 106 px short). #182 bundle and #190 (closed 2026-08-21, superseded by #182) not merged for this task; #182 non-keyboard parts belong to separate tasks (#155, #186/#189). Branch fix/android-keyboard-covers-input (24fe947f, fixes #53, pre-edge-to-edge) is superseded, no open PR.
Design gap (bug-lane record): No IME-inset handling ever existed as a first-class layer. The app stacked native adjustResize and JS KeyboardAvoidingView with no contract about which coordinate space either reasons in. Under Expo mandatory edge-to-edge the window origin moved while KAV mixed window-frame coords with screen-space keyboard coords, so every fix that only changed the behavior prop (#53/#70/#74/#147/#148) re-tuned the symptom. The native insets plugin (#210/#216) then fixed only API 35+, with no JS-side coordination — Android ≤14 broken, 15+ exposed to double-application.
Stage 3 — PR #236:fix(android): keep chat composer above the keyboard (#194, #156), head 484e227d, 6 files +217/−14. app/session/[id].tsx (listeners tracking IME height + screenY, JS paddingBottom, behavior={undefined} on Android, composer maxHeight + scrollEnabled); QuestionPrompt.tsx (scrollable body, pinned footer — byte-identical to #208 for this file); src/lib/keyboard-offset.ts + test (from #201, + API-35 guard helper); src/lib/session-layout.ts + test (from #208, composer cap + question scroll props only). No new dependencies; applicationId untouched; manifest/gradle/package.json untouched. Gates on exact head SHA: check:versions exit 0, typecheck exit 0, full suite 395 pass / 0 fail (baseline clean main: 380). Test-count delta: +15 (380 → 395), test files 48 → 50. Only ONE test dropped (the static insets.top Android offset — measured 56 dp short on Pixel 11 Pro); the iOS-offset test moved to keyboard-offset.test.ts. No mock-based tests.
API-35 decision (Stage 3): JS padding gated — JS owns API < 35, native plugin owns API 35+. jsKeyboardPaddingApplies(platform, apiLevel) returns true only for Android with numeric Platform.Version < 35, so exactly one layer applies IME height on every API level. Composer cap + QuestionPrompt scroll stay active on all API levels. iOS unchanged. Connection screens need no change (KAV-wrapped via #216, covers (d)).
Stage 4 — PASS (verdict 6855569318, lead-read-back): Full 345-line diff read; AC (a)–(e) all met in code; API-35 guard verified exactly-one-layer; test delta re-verified by reviewer own runs; no scope creep; sweep re-run zero unfixed hits in scope. Notes (not failures): app/(tabs)/index.tsx New Session + Rename modals still use KAV behavior="height" on Android; connection forms on API <35 still rely on KAV behavior="padding" offset 0 (mitigated by scrollable forms). claude-code-review skill file does not exist on this VM — method applied from the brief; install before the next review. CUA is NOT a required check; checkout AGENTS.md "MANDATORY CUA before merge" text is stale (workflow deleted on Den order, no credits).
Stage 5 — MERGED (lead, 2026-11-13): CI green on head 484e227d — Typecheck and unit tests pass, test pass, build pass (23m47s). Merge commit 2667ad5c9efebc9a65f5237673d0ea2d649d7399 (main HEAD, verified by readback). Issues #194 and #156 auto-closed by the merge. Merge comment 6856070558 on #194. Superseded PRs closed with comments: #193, #201, #206, #208, #203. #182 left open — its non-keyboard parts belong to separate tasks (#155, #186/#189).
Stage 5.5 — Design/PRD sync: checked — no update needed. No design or PRD doc exists for this fix, and no standing design page describes IME/keyboard behavior (hub and runbooks describe process only). Recorded in merge comment 6856070558.
Open residual: Physical-device proof (open / multiline / dismiss on a real Android phone, API <35 and 35+) was not run — no Android SDK/device on this VM. Deferred to release validation: owner phone check on the v0.4.18 build before it ships. No release in this task.
Fix landed on main: PR #236 "fix(android): keep chat composer above the keyboard (#194, #156)", merge commit 2667ad5c9efebc9a65f5237673d0ea2d649d7399 (main HEAD, verified by readback). Issues #194 and #156 auto-closed by the merge.
What shipped:#201 live-IME-height mechanism (keyboard listeners apply the reported IME height as padding, explicit reset on hide) + #208 bounded multiline composer (cap, internal scroll) + scrollable QuestionPrompt with pinned footer. API-35 guard: JS padding owns API < 35, the native insets plugin owns 35+, so exactly one layer applies IME height. iOS unchanged. No new dependencies; applicationId untouched.
Evidence: Stage 4 review PASS (comment 6855569318, head 484e227d); CI green on the head — Typecheck and unit tests, test, build (23m47s). Full suite 395 pass / 0 fail (baseline 380), test files 48 → 50.
Stage 5.5 Design/PRD sync: checked — no update needed. No design or PRD doc exists for this fix, and no standing design page describes IME/keyboard behavior (hub and runbooks describe process only).
Open residual: physical-device proof (open / multiline / dismiss on a real Android phone, API <35 and 35+) was not run — no Android SDK/device on this VM. Deferred to release validation: owner phone check on the v0.4.18 build before it ships. No release in this task.
Activity
Qiiks commentedon Aug 21, 2026
Fixed by the merge of #182 into the Qiiks/opencode-mobile maintenance branch (
maint/v0.4.16) — shipping in release v0.4.16-maint.1 (APK will be attached there). Upstream review of #182 is still recommended; this merge keeps the fork usable while it waits.duoyi88 commentedon Aug 28, 2026
Tested on a physical Pixel 11 Pro running Android 17. Play v0.4.15 reproduces this with both Gboard and a custom Trime IME. The keyboard change in #182 improves the layout but is still 56 dp short: the TextInput overlapped the IME by 106 px in the measured build.
I opened focused follow-up PR #201, which offsets by the complete native-header height (
insets.top + 56) and keeps the full composer above the IME in the patched device build.duoyi88 commentedon Aug 28, 2026
Follow-up on #201: physical testing caught one more regression in the first offset-based revision — after dismissing the IME, React Native 0.81.5 retained stale bottom padding and the composer did not return to the bottom.
PR #201 has now been updated to use Android
keyboardDidShow/keyboardDidHidemetrics directly: show applies the reported IME height; hide resets padding to zero. The rebuilt side-by-side APK passed the complete open/close cycle on the Pixel 11 Pro: full composer visible above the keyboard, then restored to the bottom after dismissal.vstandos commentedon Sep 5, 2026
Can confirm this reproduces consistently when connecting to a self-hosted opencode serve — the composer stays fully behind the soft keyboard while typing. Thanks for looking into it, looking forward to #193/#201 landing. Much appreciated!
fix(keyboard): restore adjustResize for edge-to-edge displays (dziani…
omgoshjosh commentedon Sep 21, 2026
Tracking the broader Android IME regression here rather than opening a duplicate.
Authoritative Android evidence covers two keyboard-visible states: (1) a multi-choice question card whose lower choices cannot be usefully scrolled above the IME, and (2) a long multiline composer whose editable viewport/caret becomes unusably constrained. The contribution will preserve recoverable question navigation, use keyboard-aware bounded composer growth with internal scrolling, and cover resize/orientation, accessibility scaling, dismissal, and iOS non-regression.
Reserved clean contribution branch:
fix/android-ime-scroll-composer-upstream, based on upstreammainat646f9cbf7743e08115c8121d98c82f48d088a8f4. No implementation, release, or merge has occurred. Device reproduction, root-cause evidence, tests, and independent QA/design review will be attached before a PR is requested.omgoshjosh commentedon Sep 21, 2026
Implementation is available in draft PR #208.
Passed: npm test (340), npm run typecheck, npm run check:versions; independent code and QA/design review completed.
The physical Pixel 8 Pro post-change install/smoke is deferred: the capacity broker denied the Android build while an active 10 GB iOS build lane holds capacity. No bypass was attempted. Existing reproduction evidence remains at /var/folders/fc/xccpf99d62b5_sc13zpgvjd80000gn/T/opencode/mobile-ime-repro-20260920/.
omgoshjosh commentedon Sep 21, 2026
Physical Pixel candidate smoke result for PR #208: BLOCKED by test environment connectivity. Candidate commit 95b001d loaded on Pixel 8 Pro 38141FDJG00BG7 at 1008x2244; bundle markers and repository gates verified. The installed dev client persisted 127.0.0.1:12400 and could not reach a session; therefore authoritative question-choice and multiline-composer screenshots were not honestly claimable. Evidence: file:///var/folders/fc/xccpf99d62b5_sc13zpgvjd80000gn/T/opencode/mobile-ime-repro-20260920/candidate/. No feature code changed; device/Metro/lease cleanup completed.
omgoshjosh commentedon Sep 21, 2026
QA PASS: validated PR #208 at commit 95b001d on physical Pixel 8 Pro 38141FDJG00BG7. Recreated the persisted http://127.0.0.1:12400 endpoint with a question-aware REST/SSE mock and adb reverse; candidate JS loaded through Metro (bundle evidence: /private/var/folders/fc/xccpf99d62b5_sc13zpgvjd80000gn/T/opencode/mobile-ime-repro-20260920/candidate/android.bundle.js; markers include question-options-scroll, COMPOSER_MIN_HEIGHT=88, composerMaxHeight, keyboardVerticalOffset).\n\nAuthoritative captures: /Users/josh/agents/media/mobile-ime-qa-95b001d-20260921/. Screenshots/XML cover question card before/after IME scroll, lower choices visible above IME, pinned Dismiss/Next footer; multiline draft with multiple lines/caret, internal scroll and edit; keyboard dismissal, send/attachments smoke captures; 1.5x font and compact resize. Screenshots are 1008x2244 physical pixels; app/window class is 763x1536 at 360dpi, keyboard-visible app bounds recorded in XML/window-displays.txt. Tested question options scroll, footer navigation, composer focus/multiline/edit, keyboard dismissal, send path, attachments control, running/stop-capable mock path, compact resize, default/1.5x scale, safe-area bounds, portrait lock.\n\nCleanup PASS: device lease released (broker leases=0), 12400/8081/13000 reverse mappings removed, owned mock and Metro stopped, port claims released, font_scale restored to 1.0, wm size reset, rotation settings unchanged. No product files edited.
omgoshjosh commentedon Sep 21, 2026
PR #208 is ready for maintainer review at 95b001d after final bug-focused review PASS. Pixel 8 Pro QA validated scrollable keyboard-visible choices, pinned navigation, and a usable multiline internal composer viewport: /Users/josh/agents/media/mobile-ime-qa-95b001d-20260921/. Gates: 340 tests, typecheck, version parity. Design PASS; residual risk is one Pixel/IME combination. No merge performed.
dzianisv commentedon Nov 13, 2026
Claiming this as the owning lead — Ember, OpenCode Mobile task agent.
Task: fix the Android keyboard hiding the chat input (#194, #156). Branch: fix/keyboard-ime-194. Scope: Android composer + connection-form IME handling only — evaluate open PRs #193/#201/#206/#208 (and #203), merge the best one or land an equivalent fix. No applicationId or dependency changes.
Work Log row: "Fix Android keyboard hiding chat input (#194, #156) — merge one of PRs #193/#201/#206/#208".
dzianisv commentedon Nov 13, 2026
Keyboard IME fix — context pack (maintained, DONE, 2026-11-13)
Stage: DONE — merged. Lead: Ember (OpenCode Mobile task agent). Branch:
fix/keyboard-ime-194(head484e227d305ae76bfaca1be94f2d34a4965ed81d, from maine8444931). Work Log: "Fix Android keyboard hiding chat input (#194, #156) — merge one of PRs #193/#201/#206/#208" (Done). No design/PRD links exist for this fix.Scope / acceptance: Android composer + connection forms. (a) composer visible above keyboard on open; (b) usable multiline typing (caret/viewport, internal scroll); (c) returns to bottom on dismiss, no stale padding; (d) connection add/edit usable with keyboard; (e) no iOS regression (padding, offset 90).
Stage 1 decisions: All six candidates OPEN +
mergeable=false/dirty, stale bases, no CI checks reported on any branch — merge none as-is. Re-implement from scratch: #201 live-IME-height mechanism (base) + #208 bounded multiline composer + scrollable QuestionPrompt; reject #206 (stale v0.4.16 release commit), #203 new dep (owner call), #193 adjustPan (connection part already landed via #216), #182/#208 staticinsets.topoffset alone (contradicted by #201 Pixel 11 Pro measurement: 56 dp / 106 px short). #182 bundle and #190 (closed 2026-08-21, superseded by #182) not merged for this task; #182 non-keyboard parts belong to separate tasks (#155, #186/#189). Branchfix/android-keyboard-covers-input(24fe947f, fixes #53, pre-edge-to-edge) is superseded, no open PR.Design gap (bug-lane record): No IME-inset handling ever existed as a first-class layer. The app stacked native
adjustResizeand JSKeyboardAvoidingViewwith no contract about which coordinate space either reasons in. Under Expo mandatory edge-to-edge the window origin moved while KAV mixed window-frame coords with screen-space keyboard coords, so every fix that only changed thebehaviorprop (#53/#70/#74/#147/#148) re-tuned the symptom. The native insets plugin (#210/#216) then fixed only API 35+, with no JS-side coordination — Android ≤14 broken, 15+ exposed to double-application.Stage 3 — PR #236:
fix(android): keep chat composer above the keyboard (#194, #156), head484e227d, 6 files +217/−14.app/session/[id].tsx(listeners tracking IME height + screenY, JS paddingBottom,behavior={undefined}on Android, composer maxHeight + scrollEnabled);QuestionPrompt.tsx(scrollable body, pinned footer — byte-identical to #208 for this file);src/lib/keyboard-offset.ts+ test (from #201, + API-35 guard helper);src/lib/session-layout.ts+ test (from #208, composer cap + question scroll props only). No new dependencies; applicationId untouched; manifest/gradle/package.json untouched. Gates on exact head SHA:check:versionsexit 0,typecheckexit 0, full suite 395 pass / 0 fail (baseline clean main: 380). Test-count delta: +15 (380 → 395), test files 48 → 50. Only ONE test dropped (the staticinsets.topAndroid offset — measured 56 dp short on Pixel 11 Pro); the iOS-offset test moved tokeyboard-offset.test.ts. No mock-based tests.API-35 decision (Stage 3): JS padding gated — JS owns API < 35, native plugin owns API 35+.
jsKeyboardPaddingApplies(platform, apiLevel)returns true only for Android with numericPlatform.Version < 35, so exactly one layer applies IME height on every API level. Composer cap + QuestionPrompt scroll stay active on all API levels. iOS unchanged. Connection screens need no change (KAV-wrapped via #216, covers (d)).Stage 4 — PASS (verdict 6855569318, lead-read-back): Full 345-line diff read; AC (a)–(e) all met in code; API-35 guard verified exactly-one-layer; test delta re-verified by reviewer own runs; no scope creep; sweep re-run zero unfixed hits in scope. Notes (not failures):
app/(tabs)/index.tsxNew Session + Rename modals still use KAVbehavior="height"on Android; connection forms on API <35 still rely on KAVbehavior="padding"offset 0 (mitigated by scrollable forms).claude-code-reviewskill file does not exist on this VM — method applied from the brief; install before the next review. CUA is NOT a required check; checkoutAGENTS.md"MANDATORY CUA before merge" text is stale (workflow deleted on Den order, no credits).Stage 5 — MERGED (lead, 2026-11-13): CI green on head
484e227d— Typecheck and unit tests pass, test pass, build pass (23m47s). Merge commit2667ad5c9efebc9a65f5237673d0ea2d649d7399(main HEAD, verified by readback). Issues #194 and #156 auto-closed by the merge. Merge comment 6856070558 on #194. Superseded PRs closed with comments: #193, #201, #206, #208, #203. #182 left open — its non-keyboard parts belong to separate tasks (#155, #186/#189).Stage 5.5 — Design/PRD sync: checked — no update needed. No design or PRD doc exists for this fix, and no standing design page describes IME/keyboard behavior (hub and runbooks describe process only). Recorded in merge comment 6856070558.
Open residual: Physical-device proof (open / multiline / dismiss on a real Android phone, API <35 and 35+) was not run — no Android SDK/device on this VM. Deferred to release validation: owner phone check on the v0.4.18 build before it ships. No release in this task.
Merge pull request #236 from dzianisv/fix/keyboard-ime-194
dzianisv commentedon Nov 13, 2026
Merged — PR #236 (Stage 5, 2026-11-13)
Fix landed on main: PR #236 "fix(android): keep chat composer above the keyboard (#194, #156)", merge commit
2667ad5c9efebc9a65f5237673d0ea2d649d7399(main HEAD, verified by readback). Issues #194 and #156 auto-closed by the merge.What shipped: #201 live-IME-height mechanism (keyboard listeners apply the reported IME height as padding, explicit reset on hide) + #208 bounded multiline composer (cap, internal scroll) + scrollable QuestionPrompt with pinned footer. API-35 guard: JS padding owns API < 35, the native insets plugin owns 35+, so exactly one layer applies IME height. iOS unchanged. No new dependencies; applicationId untouched.
Evidence: Stage 4 review PASS (comment 6855569318, head
484e227d); CI green on the head — Typecheck and unit tests, test, build (23m47s). Full suite 395 pass / 0 fail (baseline 380), test files 48 → 50.Stage 5.5 Design/PRD sync: checked — no update needed. No design or PRD doc exists for this fix, and no standing design page describes IME/keyboard behavior (hub and runbooks describe process only).
Open residual: physical-device proof (open / multiline / dismiss on a real Android phone, API <35 and 35+) was not run — no Android SDK/device on this VM. Deferred to release validation: owner phone check on the v0.4.18 build before it ships. No release in this task.
fix(android): keep chat composer above the keyboard (dzianisv#194, dz…
release: v0.4.18 — keyboard, voice, and stability fixes