Skip to content

feat(mobile): share into Buzz from the iOS share sheet - #9433

Merged
brow merged 8 commits into
mainfrom
mobile-share-extension-design
Nov 13, 2026
Merged

brow merged 8 commits into
mainfrom
mobile-share-extension-design

Conversation

@brow

@brow brow commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

Lets people share screenshots, screen recordings, photos, URLs and text from any iOS app into Buzz. Today Buzz doesn't appear in the share sheet at all.

  • Plain Buzz icon: opens a new Solo chat with the items in its composer.
  • Suggested conversation: iOS offers channels and DMs the person recently sent top-level messages in. Choosing one opens that conversation with the items in its composer. When the conversation is already open, the share goes to that page's composer instead of opening a second one; if another page covers it, Buzz stays where it is and shows "Go back to that conversation to finish sharing", and the items join the draft when the person goes back.
  • The share extension has no UI and sends nothing. It copies the items into the app group and opens Buzz, which prefills the normal composer, so drafts, attachments, mentions and failed-send handling all stay the app's (see the ADR).
  • If the conversation already has a draft, Buzz asks whether to add the shared items to it or replace it.
  • A share to a conversation that's no longer available (a removed community or channel, or an unreadable share) shows "That conversation isn't available". A share while signed out shows "Sign in to share".

Suggestions come from an outgoing INSendMessageIntent the app donates after a top-level send or a new Solo chat. The notification extension no longer donates incoming messages, so receiving a message never makes a conversation a suggestion; it still turns the push into a communication notification with the sender's avatar. Both use the same conversation identifier, now the plain community and channel IDs instead of a hash, because the extension needs to hand the identifier back to the app.

Before After
Share sheet without Buzz Share sheet with Buzz
Buzz icon: new Solo chat Suggested DM with a draft After Add
New Solo chat with the shared photo Add to your draft prompt Draft with the shared link and photo added
share-demo.mp4

Regressions

  • Nothing changes for people who never use the share sheet, except that sending a top-level message or starting a Solo chat now makes one local INInteraction.donate call (skipped while the age restriction is on, which still purges every interaction).
  • Communication notifications look the same. Dropping the incoming donation removes work (and a deletion fence) from the notification extension's time budget.
  • The share hand-off reuses the existing deep link dispatcher. A share link is a new link type; notification and message links take the same paths as before.

Validation

  • Added tests:
    • Dispatcher hand-off: a share to a suggested channel opens it with the shared text and files; shares to a removed community, an unlisted channel, an unknown manifest version or a missing manifest show the error and delete the pending share; share links accept only the extension's UUID ids.
    • Composer delivery: with an existing draft, Add appends the shared text on a new line and attaches the file, Replace clears the draft first, and the app group copy is deleted either way.
    • Notification presenter: specializes the notification from the intent, or falls back to the ordinary content when that throws (replaces the donation and deletion-fence tests).
  • Full mobile Flutter suite and BuzzPushKit Swift tests pass.
  • Automated app run on an iPhone 17 Pro simulator (iOS 27, dev relay test community), recorded above: sent a DM, shared a photo from Photos with the Buzz icon from a cold start (new Solo chat with the photo attached), then handed a link and photo to a DM that had a draft and chose Add. Also checked that a share's pending files are deleted after delivery.
  • Limitation: the iOS simulator never shows share-sheet conversation suggestions (it has no coreduetd), so the suggested-DM step in the video is staged by writing the same pending share and link the extension writes. Choosing a real suggestion still needs a check on a device.
  • Known gaps, all confined to sharing: suggestions have no avatar image yet; a suggestion for a conversation left after signing out shows "isn't available"; choosing Later in the unfinished-chat dialog keeps the share until the next new chat; and a pending share the app never receives (for example when Buzz doesn't open) stays in the app group.

Before merge

  • On a real iPhone, choose a suggested conversation in the share sheet and confirm the shared items open in that conversation's composer (the simulator can't show suggestions). Waived before merge: the managed test iPhone shows no share-sheet suggestions for any app, so this will be checked on a personal phone after landing.

Adds an iOS share extension that hands shared photos, videos, URLs and text to the app, which prefills the chosen conversation's composer. Conversations a person sends top-level messages in are donated as share-sheet suggestions; the plain Buzz icon opens a new Solo chat. The notification extension stops donating incoming interactions.

Signed-off-by: Tom Brow <[email protected]>
@brow

brow commented Nov 13, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 13, 2026 •

Copy link
Copy Markdown
Codex Review Summary: ✅ Completed

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-13T02:12:56.409111Z 36b6aa0 Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3162c414fe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

A share whose files can't be copied still adds its text to the composer and shows an error for the files. A suggestion donation that completes after an age restriction took effect requests the age gate's durable interaction cleanup.

Signed-off-by: Tom Brow <[email protected]>
The send paths read the active community before awaiting the send, so a send that finishes after navigation no longer reads a disposed ref. Notifications keep grouping under the hashed conversation key they were already delivered with; only the intent's conversation identifier carries the plain IDs. The share delivery test waits on the pending share's deletion instead of fixed sleeps.

Signed-off-by: Tom Brow <[email protected]>
A share whose files can't be copied and that has no text now shows the file error without offering Add or Replace, so Replace can no longer clear an existing draft and add nothing.

Signed-off-by: Tom Brow <[email protected]>
A share to a conversation whose page is already open now returns to that page instead of pushing a second one, so one composer owns the draft and its attachments. It walks out through nested navigators such as Home's conversation pane, pops covering pages the way Back would, and stops at a page that refuses to close; the share still goes to the open composer.

Signed-off-by: Tom Brow <[email protected]>
…sation

Returning to an open conversation by popping the pages over it could discard another page's unsent draft or work. A share to a conversation that is already open now never closes anything: its composer takes the share once it is on screen, and when another page covers it, a toast says to go back to that conversation to finish sharing.

Signed-off-by: Tom Brow <[email protected]>
A second share for a conversation that hadn't taken the first one yet replaced it and deleted its items. Shares now wait in order, and the composer offers each in turn.

Signed-off-by: Tom Brow <[email protected]>
@brow
brow marked this pull request as ready for review November 13, 2026 02:10
@brow
brow requested a review from a team as a code owner November 13, 2026 02:10

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 36b6aa0b59

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

The share extension counts items it couldn't load or copy in the manifest, and the composer reports them alongside whatever did arrive.

Signed-off-by: Tom Brow <[email protected]>

@kazemek21 kazemek21 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kyle reviewed the PR and the Nexus review-tracker notes.

Posted by Codex (gpt-6.1-sol) on behalf of kylez

.read(composerShareInboxProvider.notifier)
.deliver(composeDraftKey(newSoloComposerKey), share);
// Completes only when the chat closes; later links needn't wait.
unawaited(openNewSoloChat(context, ref));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Keep one owner for the open Solo draft

When a New chat composer already contains a caption and photo, another plain-icon share pushes a second composer with the same new-solo key. The new page restores the caption but not the photo, because attachments remain owned by the covered composer. Could this reuse the existing draft route, or allocate a separate draft key when starting an independent chat?

Posted by Codex (gpt-6.1-sol) on behalf of kylez

@brow
brow merged commit 2b428f5 into main Nov 13, 2026
58 of 60 checks passed
@brow
brow deleted the mobile-share-extension-design branch November 13, 2026 06:57
bostonaholic added a commit that referenced this pull request Nov 13, 2026
Co-authored-by: mboston.Engineer <932d3b6ebea6cc83e091551ae46d1c7e7f8f7d0fa8e9cef5e6facc8544af413b@buzz.block.builderlab.xyz>

* origin/main:
  fix(mobile): require Builderlab consent for existing identities (#8823)
  feat(mobile): use HTTP/2 on iOS through app-wide URLSessions (#8897)
  fix(relay): publish a git push only when refs changed; check the protocol by refinement (#9425)
  fix(mobile): show shared chats under Solo (#9348)
  chore(release): release Buzz Desktop version 0.5.29 (#9456)
  feat(mobile): render messages with gpt_markdown 1.3.4 plusparse (#8945)
  fix(acp): bound observer retention by bytes (#7987) (#9436)
  Tune release codegen for faster/smaller binaries (#9434)
  feat(desktop): add dismissible banner pointing to the new buzz app (#9379)
  fix(mobile): keep publishing presence while the app is open (#9441)
  feat(mobile): share into Buzz from the iOS share sheet (#9433)
  fix(mobile): qualify every namesake mention and keep authored mention casing (#9325)
  fix(mobile): match browser GIF timing in the iOS reaction sheet (#9437)
  fix(mobile): play short-delay animation frames at browser speed (#9432)
  buzz-search: read profile names without the profile_name_fields function (#9397)
  buzz-db: build the community deletion lock key in Rust (#9396)
  fix(cli): pair for the active community, skip stopped desktops, accept a bare relay host (#9417)
  test(mobile): run push tests without a gateway dart-define (#9423)
  fix(mobile): never pop Home when archiving from channel settings (#9387)
  perf(acp): reduce observer CPU and lock overhead (#9381)

Signed-off-by: Matthew Boston <[email protected]>
bostonaholic added a commit that referenced this pull request Nov 13, 2026
…count-backfill

Co-authored-by: mboston.Engineer <932d3b6ebea6cc83e091551ae46d1c7e7f8f7d0fa8e9cef5e6facc8544af413b@buzz.block.builderlab.xyz>

* bostonaholic--agent-reply-count:
  fix(mobile): require Builderlab consent for existing identities (#8823)
  feat(mobile): use HTTP/2 on iOS through app-wide URLSessions (#8897)
  fix(relay): publish a git push only when refs changed; check the protocol by refinement (#9425)
  fix(mobile): show shared chats under Solo (#9348)
  chore(release): release Buzz Desktop version 0.5.29 (#9456)
  feat(mobile): render messages with gpt_markdown 1.3.4 plusparse (#8945)
  fix(acp): bound observer retention by bytes (#7987) (#9436)
  Tune release codegen for faster/smaller binaries (#9434)
  feat(desktop): add dismissible banner pointing to the new buzz app (#9379)
  fix(mobile): keep publishing presence while the app is open (#9441)
  feat(mobile): share into Buzz from the iOS share sheet (#9433)
  fix(mobile): qualify every namesake mention and keep authored mention casing (#9325)
  fix(mobile): match browser GIF timing in the iOS reaction sheet (#9437)
  fix(mobile): play short-delay animation frames at browser speed (#9432)
  buzz-search: read profile names without the profile_name_fields function (#9397)
  buzz-db: build the community deletion lock key in Rust (#9396)
  fix(cli): pair for the active community, skip stopped desktops, accept a bare relay host (#9417)
  test(mobile): run push tests without a gateway dart-define (#9423)
  fix(mobile): never pop Home when archiving from channel settings (#9387)
  perf(acp): reduce observer CPU and lock overhead (#9381)

Signed-off-by: Matthew Boston <[email protected]>
brow added a commit that referenced this pull request Nov 14, 2026
…igned (#9489)

iOS release builds of main fail at export with "No profiles for
`xyz.block.buzz.dogfood.mobile.ShareExtension` were found"
([buzz-mobile-releases build
62](https://buildkite.com/cash/buzz-mobile-releases/builds/62)). [#9433
iOS share sheet](#9433) added a
ShareExtension target, and the release signing setup has no app ID or
provisioning profile for it yet.

This unhooks the ShareExtension target from the Xcode project (target,
embed step and build settings) so the app builds and signs as it did
before #9433. Nothing else changes:

- The extension's sources stay in `mobile/ios/ShareExtension/`, so
restoring it once the profiles exist is a revert of this commit.
- The app's share hand-off code and outgoing share suggestions stay.
Without the extension, Buzz just doesn't appear in the share sheet, as
before #9433, and the hand-off never runs.

### Regressions

- Sharing into Buzz from the iOS share sheet goes away until the
profiles are registered. That's the point of this PR.
- The app still donates `INSendMessageIntent` after a send. iOS only
shows those as share suggestions for an app whose share extension
declares the intent, so they stay invisible until the extension returns.

### Validation

- iOS simulator debug build of the app succeeds with the target removed.
- No other target referenced ShareExtension (it had no target
dependencies).
- Automated full-app run skipped: this only removes a build target, and
the app code is unchanged.

Signed-off-by: Tom Brow <[email protected]>
Co-authored-by: Tom Brow <[email protected]>

This branch was successfully deployed

No deployments
codex-review — b63bf280 Deployed Nov 13, 2026 by brow via Run Codex Security Review #14799
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.

3 participants