Skip to content

fix(mobile): Android composer picker scrolls past the first four rows - #15856

Open
shivamhwp wants to merge 5 commits into
mainfrom
t3code/android-file-picker-scroll
Open

shivamhwp wants to merge 5 commits into
mainfrom
t3code/android-file-picker-scroll

Conversation

@shivamhwp

@shivamhwp shivamhwp commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

On Android, the composer pickers in an open thread (@ files, $ skills, / commands, #) showed four rows and wouldn't scroll, so anything past the fourth result was unreachable. Taps worked. Swipes went to the chat behind the picker instead.

The picker hung above the composer with absolute bottom-full, outside its parent's bounds. Android only sends drags to views inside their parent's bounds, so the picker's list never got the swipe.

On Android the picker now renders into ComposerPopoverHost, a full-size layer inside the composer's KeyboardStickyView. That layer covers the picker, so Android delivers its swipes, and it moves with the keyboard, so the picker stays right above the composer without any keyboard timing. The anchor re-measures the composer's resting position with measureLayout against the host after each composer render, and when the composer or the host resizes. iOS keeps the old wrapper.

Testing

Xiaomi POCO M3 Pro, Android 13, dev build. Same steps in both videos: type $, swipe up three times inside the skills list, then swipe down three times.

Before: the list stays on babysit-pr, the chat behind it scrolls After: the list scrolls down to test-t3-app and back, the chat stays put
Before: skills list does not scroll After: skills list scrolls
Full video Full video

The @ file picker on the fixed code, before and after one swipe. It moves from threads down to files:

@ picker before and after a swipe

Also checked on the fixed code: the picker sits right above the composer with the keyboard up and down and keeps scrolling in both, and it isn't shown over thread settings. Mobile typecheck and lint on the changed files pass. iOS isn't tested since that path is unchanged.

Closes #15658

🤖 Generated with Claude Code

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M 30-99 changed lines (additions + deletions). labels Oct 5, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 5, 2026
@macroscopeapp

macroscopeapp Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This targeted Android UI fix introduces a stateful popover host, cross-view measurement, and a structural wrapper around the production composer and keyboard layer. Because those changes affect runtime layout and touch handling beyond a simple local edit, focused human review is warranted.

You can add or adjust custom eligibility rules. Learn more.

@shivamhwp shivamhwp changed the title fix(mobile): Android composer picker scrolls again fix(mobile): Android composer picker scrolls past the first four rows Oct 5, 2026
@github-actions

github-actions Bot commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

Provider Metric Main baseline This PR Impact PR ceiling
Codex Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Codex Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Codex Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Codex Live turn WebSocket decoded 20.9 KiB 20.9 KiB 0 B (0.0%) 29.3 KiB ✅
Codex Live turn messages 2 2 0 (0.0%) 8 ✅
Claude Total thread wire 5.0 KiB 5.0 KiB 0 B (0.0%) 6.8 KiB ✅
Claude Thread snapshot wire 3.8 KiB 3.8 KiB 0 B (0.0%) 4.9 KiB ✅
Claude Live turn WebSocket wire 1.2 KiB 1.2 KiB 0 B (0.0%) 2.0 KiB ✅
Claude Live turn WebSocket decoded 21.2 KiB 21.2 KiB 0 B (0.0%) 29.3 KiB ✅
Claude Live turn messages 1 1 0 (0.0%) 8 ✅

Baseline: a1d9d72 · PR result: bd654f7 · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 108.5 KiB
  • Claude decoded thread snapshot: 108.8 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 5, 2026
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 5, 2026 02:51

Dismissing prior approval to re-evaluate b85d6d1

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 5, 2026
@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: a40c9059-195f-4d10-9cc8-95c0bb7eb842
📥 Commits

Reviewing files that changed from the base of the PR and between d7c8378 and bd654f7.

📒 Files selected for processing (3)
  • apps/mobile/src/features/threads/ComposerPopoverAnchor.android.tsx
  • apps/mobile/src/features/threads/ComposerPopoverHost.tsx
  • apps/mobile/src/features/threads/ThreadDetailScreen.tsx

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.


📝 Walkthrough

Walkthrough

The change adds a host for composer popover content and an anchor for positioning it. ThreadDetailScreen provides the host, and ThreadComposer uses the anchor for ComposerCommandPopover. On Android, the anchor measures its position relative to the host and updates the popover position.

Changes

Composer popover hosting and anchoring

Layer / File(s) Summary
:--- :---
Host context and screen wiring
apps/mobile/src/features/threads/ComposerPopoverHost.tsx, apps/mobile/src/features/threads/ThreadDetailScreen.tsx
ComposerPopoverHost provides a host view, content setter, and layout version through context. ThreadDetailScreen wraps its existing floating composer overlay in the host.
Anchor positioning
apps/mobile/src/features/threads/ComposerPopoverAnchor.tsx, apps/mobile/src/features/threads/ComposerPopoverAnchor.android.tsx
The shared anchor renders children above the composer. On Android, it measures its position relative to the host, updates host content with the measured position, and clears that content on unmount.
ThreadComposer integration
apps/mobile/src/features/threads/ThreadComposer.tsx
ThreadComposer wraps ComposerCommandPopover in ComposerPopoverAnchor instead of an absolute bottom-aligned View.

Priority: ➖ Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to bd654

No actionable issue remains before merge under normal checks. Android gesture delivery has not been independently verified at runtime.

Security Architecture Review

Security architecture risk: ⚪ Minimal · up to bd654

The change relocates the Android picker without changing command-selection permissions or thread binding. Each screen owns its picker state, and closing the picker clears the hosted content. No material security risk was identified in this change.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The introduced mutable projection is scoped to a host instance in the thread screen. The current topology has one anchor under each host, so separate screen instances do not share the projection slot.

Trust Boundaries and Controls

  • observed — Picker visibility and selection remain controlled by ThreadComposer’s existing menu. Its menu retains owner, environment, and current-thread inputs; ThreadDetailScreen continues passing the same thread/environment props. The host relocation does not add a command handler or permission bypass in this flow.

Resilience and Maintainability Implications

  • inferred — Closing or unmounting the anchor clears hosted content. A late measurement callback updates only the originating anchor’s local state and cannot directly republish into the host after unmount. The setter has no owner token, but the inspected single-writer topology does not exercise competing-owner cleanup.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 5 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Issue #15658 requires the Android picker in an open thread to scroll beyond the visible rows. ThreadComposer now uses ComposerPopoverAnchor; on Android, the anchor renders the picker in `ComposerP…
Out of Scope Changes check ✅ Passed The host, anchor, and ThreadDetailScreen wrapper support the Android picker fix in issue #15658. The shared picker includes the @, $, /, and # entries identified in the issue. The iOS fallba…
Title check ✅ Passed The title clearly identifies the Android composer picker scrolling fix and uses a concise conventional format.
Description check ✅ Passed The description explains the problem, the change, and focused verification, including before-and-after evidence and test limitations. It links issue #15658 but does not state that the issue was triage…
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@macroscopeapp
macroscopeapp Bot dismissed their stale review October 5, 2026 03:07

Dismissing prior approval to re-evaluate 9e603f9

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:M 30-99 changed lines (additions + deletions). labels Oct 5, 2026
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 5, 2026
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 5, 2026 03:11

Dismissing prior approval to re-evaluate 80e96b6

macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Oct 5, 2026
@macroscopeapp
macroscopeapp Bot dismissed their stale review October 5, 2026 03:41

Dismissing prior approval to re-evaluate d7c8378

shivamhwp and others added 5 commits October 5, 2026 03:50
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…e keyboard settles

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… composer

The overlay portal sat outside the keyboard transform, so the picker had to be
re-measured on keyboard events and landed in the wrong place. Render it into a
full-size host inside the composer's KeyboardStickyView instead, which moves
with the keyboard and still covers the picker so Android delivers its scrolls.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@shivamhwp
shivamhwp force-pushed the t3code/android-file-picker-scroll branch from d7c8378 to bd654f7 Compare October 5, 2026 03:55

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Android: composer @ picker cannot be scrolled, so results past the fourth are unreachable

2 participants