Skip to content

feat(chat): render share-profile widget messages as a bubble - #919

Merged
bmc08gt merged 4 commits into
mainfrom
feat/share-profile-widget
Sep 30, 2026
Merged

bmc08gt merged 4 commits into
mainfrom
feat/share-profile-widget

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

Renders the share-profile widget (messaging.v1.WidgetContent.share_profile) as a chat bubble, following Figma node 10588:1979. Builds on #916 (merged), which brings in the 0.13.0 contract and the ShareProfileWidget domain struct.

Only the server sends widgets. The widget's username decides whose profile the card shows and shares:

  • Own username: the cell draws OwnProfileCard, built in ConversationScreen from the session profile and profileAvatars, with no lookup.
  • Any other username: it resolves through the person link-card lookup (LinkCardSource / linkCardFeed) with loading and not-found states. Until that answers, the @handle stands in for the name.

Changes:

  • Model: ConversationMessage.Content.widget is .shareProfile or .unrecognized. ConversationMessage.init no longer drops widgets. An unrecognized variant renders the existing "Update Flipcash to see it" bubble.
  • Persistence: widgets are cached as kind 4. Database.schemaVersion goes from 43 to 44, since older builds can't read that kind.
  • Share: this is the same TipCodeShareItem path as UserProfileScreen.share(). URL.tipcard(for:username:) now delegates to the new Username.profileURL.
  • Receive-only: .widget is not encodable in asProto(), and a decrypted widget stays DecryptFailure.unsupported, because EncryptedContent allows only text, media and reply. There is no Report. Reply and reactions follow the chat's speaker rules through conversationGate(session:rules:rates:), the same check that decides whether the composer is live: a DM or a chat you can speak in allows both, while never, an unmet balance or staff requirement, or not being a member removes both. The in-card Share button is not gated.
  • Chat list, Spotlight and reply quotes: these show "Shared a profile". The notification extension shows the @handle, since it has no lookup.
  • Styling: BubbleBackgroundView chrome, .appTextLarge / .appTextCaption, ContactAvatarView with the initials muted to 40% (new initialsColor parameter, default unchanged), and a .filledCompact button (44pt, 6pt radius). The card measures about 204pt tall against the design's 207.

ShareProfileWidgetRenderTests lays out the real ChatShareProfileCell in a window and checks its size. It writes a PNG when SHARE_PROFILE_WIDGET_PNG is set. ShareProfileWidgetGatingTests runs real ConversationRules through conversationGate for the open, never, unmet-balance and unmet-staff cases.

@bmc08gt bmc08gt self-assigned this Sep 30, 2026
@bmc08gt
bmc08gt added this pull request to stack #923 September 30, 2026 17:08
An error occurred while trying to automatically change base from chore/flipcash2-3d6de707 to main September 30, 2026 17:08
Carry widget messages through ConversationMessage instead of dropping
them. A share-profile widget draws a card with the person's avatar,
name and handle (looked up by username through the link-card feed) and
a Share button that opens the share sheet on their public profile link.
Unrecognized widget variants render the existing unsupported bubble.
Adds a localized-style preview line and persists widgets in the
conversation cache (schema 44).
…on profile

A widget naming the signed-in user's handle now skips the link-card lookup and
uses the session profile's name and avatar. Widgets are server-sent, so they
offer Reply only (no Report) and the chat-list preview no longer names a sender.
Adds a rendering test for the card at the designed width.
… rule

A share-profile widget has no author, so its Reply and reactions now follow
the same conversationGate speaker verdict as the composer: a never rule, an
unmet balance or an unmet staff requirement withholds both. Report stays off.
The screen hands ConversationLoadCoordinator a canSpeak closure evaluated in the
observation scope; MessageCapability.resolve and ChatItem.from take it.
ContactAvatarView takes an initialsColor (default unchanged); the widget passes
textMain at 0.4, as the design draws them (node 10588:1979).
@bmc08gt
bmc08gt force-pushed the feat/share-profile-widget branch from fe01710 to b0de3aa Compare September 30, 2026 17:11
@bmc08gt
bmc08gt deleted the branch main September 30, 2026 17:12
@bmc08gt bmc08gt closed this Sep 30, 2026
@bmc08gt bmc08gt reopened this Sep 30, 2026
@bmc08gt
bmc08gt removed this pull request from stack #923 September 30, 2026 17:14
@bmc08gt
bmc08gt changed the base branch from chore/flipcash2-3d6de707 to main September 30, 2026 17:14
@bmc08gt
bmc08gt added this pull request to stack #924 September 30, 2026 17:14
@bmc08gt
bmc08gt merged commit 871e415 into main Sep 30, 2026
@bmc08gt
bmc08gt deleted the feat/share-profile-widget branch October 5, 2026 15:13
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