Skip to content

fix(mobile): Android Back closes in-screen surfaces first - #2343

Merged
DoodleBears merged 8 commits into
mainfrom
claude/project-thread-m7tsnr-back
Oct 21, 2026
Merged

DoodleBears merged 8 commits into
mainfrom
claude/project-thread-m7tsnr-back

Conversation

@DoodleBears

@DoodleBears DoodleBears commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Vain · project thread

Why the change

On Android, Back skipped over surfaces the user was looking at. With the composer's attach tray open, Back left the chat. In the full client, Back exited instead of going to the previous page. The android-material skill (#2339) requires Back to close the topmost surface first.

Refs: second PR from the Android Material 3 audit in the project thread (the first is #2342).

Special things to note

  • Merge risk: Android only. Both usePreventRemove hooks are gated on Platform.OS === 'android', so iOS swipe-back and the iOS WebView's back-forward gestures are unchanged. Review focus: the full client's exit button sets an exiting flag, so the prevented removal is dispatched instead of stepping back in web history. No native input changes.
  • Predictive back preview is not in this PR. An earlier revision set android.predictiveBackGestureEnabled. On the Android 16 emulator (targetSdk 36) it showed no preview anywhere: not on a pushed chat, not on the Settings sheet, and not even the system back-to-home on the Chats root. Logcat shows TYPE_CALLBACK from React Native 0.86's ReactActivity, which registers an always-enabled OnBackPressedCallback, so the system has nothing to animate. The flag was removed and DESIGN.md records the gap instead of claiming support. A real preview needs that callback disabled whenever the root route cannot go back, which is native work for a separate change.
  • Known gap: full-client web history on a physical phone. The full client goes back in web history only when the WebView reports canGoBack. On a Xiaomi phone (Android System WebView 155.0.8059.43), a hash-only navigation never reported it: with history.length at 2, Back still left the full client in 3 of 3 tries (phone/2c-back-left-full-client-FAIL.png). The same test passed on the emulator. In normal use the web client adds no history entries itself, so users currently fall back to the old behaviour (Back leaves) and nothing regresses. Making it reliable needs an injected script that reports web history over postMessage, which is left for a follow-up.
  • Verification:
Check Android 16 emulator Xiaomi phone, Android 16
Attach tray: Back closes the tray, then goes to Chats (button and edge swipe) PASS PASS
Full client: Back goes to the previous web page, then leaves PASS FAIL (see known gap)
Full client: floating exit leaves at once PASS PASS
Drawer: Back closes it PASS PASS
  • CI test plan: affected (mobile only).

Change outline

  • Before: Back with the attach tray open leaves the chat; Back in the full client leaves it.
  • After, on Android:
    • The composer holds the screen with Expo Router's usePreventRemove while the attach tray is open, and Back closes the tray.
    • The full client tracks the WebView's canGoBack. While it has history, Back goes to the previous web page. The floating exit always leaves.
  • DESIGN.md records the Back rule, the predictive back gap, and that new surfaces don't add BackHandler listeners.

Physical phone (Xiaomi, Android 16; status bar and computer name redacted):

Attach tray open Back: tray closed Back: Chats Full client: Back left (FAIL)
2343-android-back/phone/1b-tray-open.png 2343-android-back/phone/1c-back-tray-closed.png 2343-android-back/phone/1d-back-chats.png 2343-android-back/phone/2c-back-left-full-client-FAIL.png

Android 16 emulator:

Attach tray open Back: tray closed Back: Chats
2343-android-back/1b-tray-open.png 2343-android-back/1c-back-tray-closed.png 2343-android-back/1d-back-chats.png
Full client, page 2 Back: previous web page Back: leaves
2343-android-back/2b-full-client-page2.png 2343-android-back/2c-back-previous-web-page.png 2343-android-back/2d-back-leaves.png
Floating exit leaves Drawer open Back: drawer closed
2343-android-back/2e-floating-exit-leaves.png 2343-android-back/4a-drawer-open.png 2343-android-back/4b-back-drawer-closed.png

https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T


Generated by Claude Code

Turn on android.predictiveBackGestureEnabled. Back closes the composer's
attach tray through Expo Router's usePreventRemove, and the full client
steps back through its web history before leaving; the floating exit
still leaves at once.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
@coderabbitai

coderabbitai Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 23 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 2 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 2bd7aade-8516-434f-94b9-853c361d0cea
📥 Commits

Reviewing files that changed from the base of the PR and between 28d81b5 and a4a0796.

⛔ Files ignored due to path filters: 21
  • .github/pr-screenshots/2343-android-back/1a-chat.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/1b-tray-open.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/1c-back-tray-closed.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/1d-back-chats.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/2a-full-client-dm.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/2b-full-client-page2.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/2c-back-previous-web-page.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/2d-back-leaves.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/2e-floating-exit-leaves.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/4a-drawer-open.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/4b-back-drawer-closed.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/1a-chat.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/1b-tray-open.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/1c-back-tray-closed.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/1d-back-chats.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/2a-full-client-dm.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/2b-full-client-page2.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/2c-back-left-full-client-FAIL.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/2e-floating-exit-leaves.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/4a-drawer-open.png is excluded by !**/*.png
  • .github/pr-screenshots/2343-android-back/phone/4b-back-drawer-closed.png is excluded by !**/*.png
📒 Files selected for processing: 8
  • apps/mobile/DESIGN.md
  • apps/mobile/app/full-client.tsx
  • apps/mobile/src/ui/chat/composer.tsx
  • apps/mobile/src/ui/full-client-view.tsx
  • apps/mobile/test/composer-dictation.test.tsx
  • apps/mobile/test/conversation-navigation.test.tsx
  • apps/mobile/test/full-client-back-android.test.tsx
  • changes/2343-android-back.md
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
@DoodleBears DoodleBears self-assigned this Oct 19, 2026
DoodleBears added a commit that referenced this pull request Oct 19, 2026
Captured on an Android 16 x86_64 emulator with gesture navigation and a
debug dev client built from main plus #2342 and #2343. Light and dark at the default font, plus the largest font (2.0) for Usage and the Activity filter.
Computer names are redacted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DoodleBears and others added 2 commits October 20, 2026 05:40
Captured on an Android 16 x86_64 emulator with gesture navigation and a
debug dev client built from main plus #2342 and #2343. Before/after pairs for Back on the attach tray, full client and drawer, and held back swipes.
Computer names are redacted.

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

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
@DoodleBears DoodleBears changed the title feat(mobile): Android predictive back; Back closes in-screen surfaces first fix(mobile): Android Back closes in-screen surfaces first Oct 19, 2026
DoodleBears added a commit that referenced this pull request Oct 19, 2026
Recaptured on an Android 16 x86_64 emulator with gesture navigation and a
fresh debug dev client built from main 55c8848 plus #2342 and #2343. Light and dark at the default font, plus the radio-list fallback at the largest font (2.0).
Computer names are redacted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Recaptured on an Android 16 x86_64 emulator with gesture navigation and a
fresh debug dev client built from main 55c8848 plus #2342 and #2343. Back on the attach tray, full client and drawer; the predictive-swipe frames are dropped with the claim.
Computer names are redacted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@DoodleBears
DoodleBears marked this pull request as ready for review October 19, 2026 23:24
DoodleBears added a commit that referenced this pull request Oct 20, 2026
Captured on a Xiaomi phone (Android 16, HyperOS 3, arm64, gesture
navigation) running a debug dev client of main 55c8848 plus #2342 and
#2343, in the zh-CN locale. Light and dark, plus the radio-list fallback at font scale 2.0. Status bar and computer names are
redacted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DoodleBears and others added 3 commits October 20, 2026 13:51
Captured on a Xiaomi phone (Android 16, HyperOS 3, arm64, gesture
navigation) running a debug dev client of main 55c8848 plus #2342 and
#2343, in the zh-CN locale. 2c shows Back leaving the full client although the WebView had a history entry. Status bar and computer names are
redacted.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T
DoodleBears added a commit that referenced this pull request Oct 21, 2026
* feat(mobile): use Material 3 selection controls on Android

Segmented, PercentageSlider and Chip gain Android variants built on
@expo/ui Jetpack Compose (segmented buttons, Slider, FilterChip). The
Activity options sheet uses a Compose RadioButton through a new RadioMark
primitive, and its unread-only switch moves to the Toggle primitive.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* chore(mobile): add #2342 change fragment and drop prohibited comments

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* fix(mobile): rebuild Android segmented row when its options change

Compose reads each SegmentedButton's position from its parent once, so a
row that grows from two to four options (Usage, once longer periods are
supported) kept the two-item shapes: the selected middle segment drew a
rounded end. Key the row on its option values.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* fix(mobile): fall back to a radio list when Android segments cannot fit

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* docs(mobile): add Android emulator screenshots for #2342

Captured on an Android 16 x86_64 emulator with gesture navigation and a
debug dev client built from main plus #2342 and #2343. Light and dark at the default font, plus the largest font (2.0) for Usage and the Activity filter.
Computer names are redacted.

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

* fix(mobile): outline unselected Android segments and chips on a transparent container

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* docs(mobile): recapture Android emulator screenshots for #2342

Recaptured on an Android 16 x86_64 emulator with gesture navigation and a
fresh debug dev client built from main 55c8848 plus #2342 and #2343. Light and dark at the default font, plus the radio-list fallback at the largest font (2.0).
Computer names are redacted.

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

* docs(mobile): add physical-phone screenshots for #2342

Captured on a Xiaomi phone (Android 16, HyperOS 3, arm64, gesture
navigation) running a debug dev client of main 55c8848 plus #2342 and
#2343, in the zh-CN locale. Light and dark, plus the radio-list fallback at font scale 2.0. Status bar and computer names are
redacted.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
@DoodleBears
DoodleBears merged commit 504fbf0 into main Oct 21, 2026
11 checks passed
DoodleBears added a commit that referenced this pull request Oct 21, 2026
)

* feat(mobile): use Material 3 selection controls on Android

Segmented, PercentageSlider and Chip gain Android variants built on
@expo/ui Jetpack Compose (segmented buttons, Slider, FilterChip). The
Activity options sheet uses a Compose RadioButton through a new RadioMark
primitive, and its unread-only switch moves to the Toggle primitive.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* chore(mobile): add #2342 change fragment and drop prohibited comments

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* fix(mobile): rebuild Android segmented row when its options change

Compose reads each SegmentedButton's position from its parent once, so a
row that grows from two to four options (Usage, once longer periods are
supported) kept the two-item shapes: the selected middle segment drew a
rounded end. Key the row on its option values.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* feat(mobile): use Material 3 segmented lists for Android grouped rows

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* chore(mobile): add #2348 change fragment

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* fix(mobile): fall back to a radio list when Android segments cannot fit

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* docs(mobile): add Android emulator screenshots for #2342

Captured on an Android 16 x86_64 emulator with gesture navigation and a
debug dev client built from main plus #2342 and #2343. Light and dark at the default font, plus the largest font (2.0) for Usage and the Activity filter.
Computer names are redacted.

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

* fix(mobile): outline unselected Android segments and chips on a transparent container

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* fix(mobile): keep segmentCorners in a pure design module so the root typecheck stays on Node timers

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SJ8gcMTgoRjSRBNFswZT9T

* docs(mobile): recapture Android emulator screenshots for #2342

Recaptured on an Android 16 x86_64 emulator with gesture navigation and a
fresh debug dev client built from main 55c8848 plus #2342 and #2343. Light and dark at the default font, plus the radio-list fallback at the largest font (2.0).
Computer names are redacted.

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

* docs(mobile): add physical-phone screenshots for #2348

Captured on a Xiaomi phone (Android 16, HyperOS 3, arm64, gesture navigation,
zh-CN) running an arm64 debug dev client of main 48f35fb with this branch's
JavaScript, in light, dark and font scale 2.0. Settings groups and the Activity filter sheet: gaps between rows, large outer and small inner corners.
Status bar and computer names are redacted.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
@DoodleBears
DoodleBears deleted the claude/project-thread-m7tsnr-back branch October 28, 2026 04:24
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