Skip to content

feat(mobile): Telegram-style tap menu and long-press selection on Android - #4005

Merged
DoodleBears merged 9 commits into
mainfrom
claude/android-island-spec
Nov 11, 2026
Merged

DoodleBears merged 9 commits into
mainfrom
claude/android-island-spec

Conversation

@DoodleBears

Copy link
Copy Markdown
Contributor

Part of #3955. Stacked on #4001 (composer island). Product request: align message tap, long press and multi-select with Telegram Android, keeping our own actions. Android only.

1. Islands are one spec

The header pills, composer field and jump-to-latest button drew the same look from two token sets. Now:

  • one island token set feeds islandStyle, islandRim, islandHighlight and islandShadow (React Native) and composeIsland (Compose);
  • DESIGN.md gains an Islands rule: floating chrome over content is an opaque raised fill with a hairline rim, a top inner highlight and a soft shadow, never a blur, and edges fade with island.fade.

The tap menu and the selection bars below use it.

2. Tap opens the menu next to the message

  • A tap opens the menu right away, anchored to the bubble: a reaction island above it, then the bubble, then an action island card with each icon before its label.
  • The old Compose ModalBottomSheet is gone. The anchored menu moves to message-popover.tsx, and message-actions.tsx and message-actions.android.tsx both re-export it (iOS keeps its own sheet).
  • Double-tap 👍 is off on Android (Human decision). A failed message's tap still retries.

3. Long press selects

  • A long press selects the message, with a light haptic. While selecting, a tap or long press toggles a message.
  • Header: ✕ / "已选择 N 项" / an island with Copy and Screenshot, all Compose islands in place of the Back, title and action row.
  • Bottom: Reply and Feedback islands replace the composer, enabled when exactly one message that can take them is selected. Feedback only appears where feedback is offered. Reply exits selection and starts a reply; Feedback exits and opens the feedback screen.
  • These are existing actions only; nothing new on the Host, so no CLI change. iOS keeps its SelectionBar.

Not in this PR

  • Native Recycler rows get no taps yet. They only draw, and touches don't route back to JS. With EXPO_PUBLIC_NATIVE_ROWS on, plain-text and Markdown native rows won't open the menu or select. The flag is off by default; routing taps from ChatRecyclerView is a follow-up.
  • expo-blur and masked-view cleanup, as before.

Verification

  • New tests:
    • island.test.ts: the island helpers.
    • message-popover-android.test.tsx: reaction island and actions; a reaction toggles and closes; an action runs and closes.
    • message-bubble.test.tsx: on Android with selection, a long press selects and two taps don't react.
  • The old Android bottom-sheet tests are removed. The rest of the mobile suite passes, except account-hosts and pairing-certificate, which expect English text and fail under this machine's Chinese locale.
  • pnpm lint, pnpm format:check, pnpm changelog:check and the mobile typecheck pass.
  • Physical Android phone, Release 23addd8cf201, baseline arm (default flags, React rows), light and dark:
    • a tap opens the anchored island menu;
    • a long press shows the selection header islands and the 回复 / 反馈 islands;
    • a tap on a second message goes to "已选择 2 项";
    • ✕ exits.
    • The in-app appearance was set back to light afterwards.

🤖 Generated with Claude Code

DoodleBears and others added 3 commits November 11, 2026 20:45
The header pills, composer field and jump-to-latest button drew the same
rim, highlight and shadow from two token sets. One `island` token set now
feeds `islandStyle` (React Native) and `composeIsland` (Compose), and
DESIGN.md states the rule so new floating chrome reuses it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… press

Android follows Telegram: a tap opens the menu anchored to the bubble (reaction
island above, action island below, icons first), a long press selects the
message, and selection turns the header into close, count and Copy/Screenshot
islands with Reply and Feedback islands in place of the composer. Double tap no
longer reacts on Android. iOS and the Web are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tion

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Nov 11, 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 6 minutes.

Check out review usage here.

View limit details

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

Learn how review limits work.

Review configuration:

Run configuration

  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 7e712cdd-8117-4711-9e2a-4dd209369a24
Commits

Reviewing files that changed from the base of the PR and between 96770c0 and 7aac772.

Files selected for processing: 22

  • apps/mobile/DESIGN.md
  • apps/mobile/src/ui/chat/chat-header-surface.android.tsx
  • apps/mobile/src/ui/chat/composer-chrome.tsx
  • apps/mobile/src/ui/chat/conversation-screen.tsx
  • apps/mobile/src/ui/chat/conversation-top-bar.android.tsx
  • apps/mobile/src/ui/chat/conversation-top-bar.tsx
  • apps/mobile/src/ui/chat/jump-to-latest.tsx
  • apps/mobile/src/ui/chat/message-actions.android.tsx
  • apps/mobile/src/ui/chat/message-actions.tsx
  • apps/mobile/src/ui/chat/message-bubble.tsx
  • apps/mobile/src/ui/chat/message-popover.tsx
  • apps/mobile/src/ui/chat/message-selection-ui.tsx
  • apps/mobile/src/ui/design/island-compose.android.ts
  • apps/mobile/src/ui/design/island.ts
  • apps/mobile/src/ui/design/tokens.ts
  • apps/mobile/src/ui/strings.ts
  • apps/mobile/test/edge-fade.test.ts
  • apps/mobile/test/island.test.ts
  • apps/mobile/test/message-bubble.test.tsx
  • apps/mobile/test/message-popover-android.test.tsx
  • apps/mobile/test/message-sheet-native.test.tsx
  • changes/3955-android-message-tap-select.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

DoodleBears and others added 2 commits November 11, 2026 21:03
The root typecheck includes the mobile tests; importing the theme type pulled
React Native's timer globals into the Node packages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@DoodleBears
DoodleBears changed the base branch from claude/android-composer-island to main November 11, 2026 12:08
@DoodleBears
DoodleBears merged commit 21adebc into main Nov 11, 2026
2 checks 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.

1 participant