Skip to content

feat(mobile): share text, links and files to a Bot from any app - #2401

Merged
DoodleBears merged 10 commits into
mainfrom
claude/ios-qol-pull-to-compose-t1kgmy
Oct 20, 2026
Merged

DoodleBears merged 10 commits into
mainfrom
claude/ios-qol-pull-to-compose-t1kgmy

Conversation

@DoodleBears

@DoodleBears DoodleBears commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Vain · project thread

Before: there was no way to send a page, photo or file from another app to a Bot. You had to copy it, open DeepSeekBot, find the chat, then paste it or pick the file again.

After: DeepSeekBot shows up in the system share sheet on iOS and Android.

  • Sharing text, a link, photos, videos or files opens a Send to (发送到) sheet. It has a title and a ✕, a preview of what arrived, and the paired Host's chats below.
  • Picking a chat opens it. The text goes below any unsent draft, and the files wait as attachment tiles. Nothing is sent until you tap Send.
  • ✕ closes the sheet without keeping anything.
  • If no computer is paired, the sheet says so and offers Pair with your computer.

This is the last item of the native QoL batch Vain approved after #2364 and #2380.

How:

  • expo-sharing, already a dependency (SDK 58), can receive shares.
    • On iOS it generates a Share Extension that opens <scheme>://expo-sharing.
    • On Android it adds SEND / SEND_MULTIPLE intent filters to the main activity.
    • app.config.js applies its plugin with the first scheme. The plugin writes config.scheme into the extension's Info.plist as a single string, and our dev config has three schemes.
  • +native-intent sends that deep link to the new /share route (share-path.ts). This check runs before the cloud mapping, which would otherwise rewrite the bundle-id scheme.
  • incoming-share.ts turns the resolved payloads into draft text and PickedFiles.
    • Text and links become draft text, one per line.
    • Files become PickedFiles, up to the composer's limit of 10.
    • deliverShare appends the text to the chat's persisted source draft and holds the files. The conversation screen takes the held files when it mounts, through its existing mount ref.
  • Cloud channels are not share targets yet.

Screenshots (iOS 27 Simulator)

Light Dark
Send to: link
Send to: 2 photos
Chat after sharing a link
Chat after sharing 2 photos
No computer paired

Release build, cold start from a share:

Send to Draft in chat ✕ lands on Chats

Notes

  • Needs a native rebuild: expo prebuild adds a new extension target and an app group. On a local signed build, the default app group group.ai.botharness.deepseekbot.dev (or group.app.deepseekbot.mobile for the store variant) must be registered with the team. EAS registers it on its own.
  • Verification:
    • pnpm lint, pnpm format:check, mobile tsc and the mobile vitest suite pass. The new incoming-share.test.ts covers the payload mapping, the attachment cap, appending to a draft, the one-time file hand-off and the deep-link match.
    • iOS 27 Simulator, dev build: sharing a Safari link, appending to a 4-line unsent draft, sharing 2 photos (en and zh), the no-computer state, and the title and ✕ all pass. The Host was checked, and nothing was sent.
    • iOS Release build: a share while the app is closed opens the chat with the link in the draft, and ✕ lands on Chats. Both pass.
    • Android device checks are queued on the Windows lane.

🤖 Generated with Claude Code

https://claude.ai/code/session_01TYsJ1DZQ7Vd8sKVs6MMhdF

Enable expo-sharing's share extension (iOS) and SEND intent filters
(Android). The share deep link opens a Send to screen listing the paired
Host's chats; picking one appends the text to that chat's unsent draft
and hands the files to its composer as attachments.

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

coderabbitai Bot commented Oct 20, 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 49 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: dc4afe46-9255-4ef1-81f6-0666d1380101
📥 Commits

Reviewing files that changed from the base of the PR and between d220792 and dff56c4.

⛔ Files ignored due to path filters: 16
  • .github/pr-screenshots/2401/chat-2-photos-d.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/chat-2-photos-l.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/chat-link-d.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/chat-link-l.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/cold-chat-draft-l.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/cold-close-chats-l.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/cold-send-to-l.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/sheet-2-photos-d.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/sheet-2-photos-l.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/sheet-2-photos-zh-d.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/sheet-2-photos-zh-l.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/sheet-link-d.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/sheet-link-l.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/unpaired-d.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/unpaired-l.png is excluded by !**/*.png
  • .github/pr-screenshots/2401/unpaired-pair-screen-l.png is excluded by !**/*.png
📒 Files selected for processing: 15
  • apps/mobile/DESIGN.md
  • apps/mobile/app.config.js
  • apps/mobile/app.json
  • apps/mobile/app/+native-intent.tsx
  • apps/mobile/app/_layout.tsx
  • apps/mobile/app/share.tsx
  • apps/mobile/src/host/pick-files.ts
  • apps/mobile/src/ui/chat/conversation-screen.tsx
  • apps/mobile/src/ui/share/incoming-share.ts
  • apps/mobile/src/ui/share/share-path.ts
  • apps/mobile/src/ui/share/share-screen.tsx
  • apps/mobile/src/ui/strings.ts
  • apps/mobile/test/incoming-share.test.ts
  • changes/2401-share-to-bot.md
  • tsconfig.json
  • 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.

claude and others added 9 commits October 20, 2026 10:50
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsJ1DZQ7Vd8sKVs6MMhdF
It imports expo-sharing, whose types pull Expo's ProcessEnv into the
root program, like the other excluded mobile tests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TYsJ1DZQ7Vd8sKVs6MMhdF
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_01TYsJ1DZQ7Vd8sKVs6MMhdF
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
… paired

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

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_01TYsJ1DZQ7Vd8sKVs6MMhdF
@DoodleBears
DoodleBears marked this pull request as ready for review October 20, 2026 13:40
@DoodleBears
DoodleBears merged commit 976a738 into main Oct 20, 2026
12 of 13 checks passed
DoodleBears added a commit that referenced this pull request Oct 20, 2026
…screenshots

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

Copy link
Copy Markdown
Contributor Author

Android phone result: PASS with findings (Xiaomi, Android 16 / HyperOS 3, release build of latest main, isolated QA Host, deepseek-v4.1-flash)

Screenshots: 2401-share-to-bot/phone (commit 6e4a78c)

Scene Files
Text shared from Chrome opens the 发送到 sheet 1-send-to-text-*
Picked chat opens with the text in the draft, nothing sent 2-text-in-draft-*
2 images shared from Photos open the sheet 3-send-to-images-*
Picked chat opens with 2 attachment tiles, nothing sent 4-two-attachments-*

Findings:

  1. The image share preview only says "2 个附件"; no thumbnails.
  2. Attachment tiles land in reverse order (QA 2, QA 1) compared with the selection order.
  3. In the light run the on-screen keyboard stayed up (the composer had focus before sharing) and covered the lower half of the chat list in the sheet.
  4. Chrome's shared text carries extra quotes and a #:~:text= link; that is Chrome's own share format, noted only.

Generated by Claude Code

DoodleBears added a commit that referenced this pull request Oct 21, 2026
…#2401 (#2422)

* fix(mobile): Android hardware Enter with WeType, attachment ✕, flick-up and shortcut icons

- Treat an input-method Enter that echoes a hardware Enter as that key, so
  Enter and Ctrl+Enter send with WeType and similar input methods.
- Stop the hidden measuring text in the composer from taking taps meant for
  the attachment ✕ and the mention list.
- Lower the Android flick-up speed to 0.3 dp/ms.
- Use the launcher icon for Android app shortcuts, which cannot draw SF Symbols.

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

* docs(changes): link #2422

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

* fix(ci): keep the recent-chats test out of the root typecheck

recent-chats.ts now imports react-native, whose timer globals clash with
Node's in the root program, like the other excluded mobile tests.

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

* fix(mobile): show shared image thumbnails and hide the keyboard on Send to

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

* fix(mobile): send when an input method types the newline for a hardware Enter

WeType on HyperOS types a newline into the field instead of sending the Enter
key again. The view now watches the focused field and turns a newline typed
within 500 ms of a sending hardware Enter into a send. Also recheck the
clipboard once Android gives the window focus back, and name shared files
that arrive as bare media ids after their type.

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

* fix(mobile): keep the keyboard down while Send to is open

Android can bring the keyboard back for the chat underneath after the share
sheet opens. Hide it again whenever it shows or the app becomes active.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
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