feat(tipping): send a tip to a scanned user's tip card - #1127
Merged
Conversation
Surface counterparty avatars in chat notifications and rows: - NotificationService loads the sender's remote avatar via Coil and falls back to the profile display name / social handle for TIP_DM senders (no device contact exists for them). - Add displayName + image to ConversationReference so chat rows can render name and avatar. - ContactAvatar crops (ContentScale.Crop) to avoid letterboxing. - MediaItem.rendition()/url() default the preferred rendition to ORIGINAL, making the argument optional.
Adds the end-to-end tipping flow: scan (or deeplink) another user's tip
card, choose an amount, and send them a tip that opens the resulting DM
chat.
- TippingCoordinator (shared/tipping): resolves the recipient's tip
card, holds the tip selection (amount + token + send state), derives
region-aware presets and min/max (send limit ∩ balance) amounts,
enforces the send limit, and runs the transfer via TransactionController.
- Scanner: ScannableDecorator dispatch (Payable/TipCard), TipUserModal
(presets, token, slide-to-confirm), affordability gating, and a
post-tip handoff into the tipped user's chat with the tips list beneath.
- Custom tip-amount entry (features/tipping) with region/currency change
and below-min / over-balance gating (add-money prompt on insufficient).
- Session/nav wiring: TipCardDelegate, /tip/{userId} deeplink, routes,
and MainActivity LocalTipCoordinator provision.
- Tip-card sharing via the share sheet; token-selection wired for Tip.
bmc08gt
added a commit
that referenced
this pull request
Jul 24, 2026
* feat(chat): show avatars for chat and push notifications
Surface counterparty avatars in chat notifications and rows:
- NotificationService loads the sender's remote avatar via Coil and
falls back to the profile display name / social handle for TIP_DM
senders (no device contact exists for them).
- Add displayName + image to ConversationReference so chat rows can
render name and avatar.
- ContactAvatar crops (ContentScale.Crop) to avoid letterboxing.
- MediaItem.rendition()/url() default the preferred rendition to
ORIGINAL, making the argument optional.
* feat(tipping): send a tip to a scanned user's tip card
Adds the end-to-end tipping flow: scan (or deeplink) another user's tip
card, choose an amount, and send them a tip that opens the resulting DM
chat.
- TippingCoordinator (shared/tipping): resolves the recipient's tip
card, holds the tip selection (amount + token + send state), derives
region-aware presets and min/max (send limit ∩ balance) amounts,
enforces the send limit, and runs the transfer via TransactionController.
- Scanner: ScannableDecorator dispatch (Payable/TipCard), TipUserModal
(presets, token, slide-to-confirm), affordability gating, and a
post-tip handoff into the tipped user's chat with the tips list beneath.
- Custom tip-amount entry (features/tipping) with region/currency change
and below-min / over-balance gating (add-money prompt on insufficient).
- Session/nav wiring: TipCardDelegate, /tip/{userId} deeplink, routes,
and MainActivity LocalTipCoordinator provision.
- Tip-card sharing via the share sheet; token-selection wired for Tip.
bmc08gt
added a commit
that referenced
this pull request
Jul 24, 2026
On cold launch, MainRoot.buildNavGraphForLaunch bundles a tip-card deeplink into pendingAction (alongside OpenCashLink and Login) and MainRoot fires it eagerly via App.kt's onPendingAction callback. But that callback only handled OpenCashLink and Login — PresentTipCard fell into the no-op `else` branch and was dropped, and the subsequent `deepLink = null` erased the link before the fallback LaunchedEffect(deepLink, currentRoute) could recover it. The tip card was silently lost on every cold start. Warm launches were unaffected because the app is already past Loading, so the fallback effect (which does handle PresentTipCard) processes the link directly. Add the missing PresentTipCard branch to onPendingAction so it calls session.resolveTipCard(userId) eagerly, mirroring the cash-link path. The gap was introduced in c46c130 (#1127), which wired PresentTipCard into buildNavGraphForLaunch and the fallback effect but not the eager onPendingAction dispatcher.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
End-to-end tipping: scan (or deeplink) another user's tip card, choose an amount, and send them a tip that opens the resulting DM chat with the tips list beneath it.
Coordinator (
shared/tipping)TippingCoordinatorresolves the recipient's tip card, holds the tip selection (amount + token + send state), and runs the transfer viaTransactionController.min= lowest preset,max= send limit ∩ balance).hasGiveableBalance) mirrors the send/currency-creator dual-gating pattern.Scanner
ScannableDecoratordispatch (Payable/TipCard) replacing the container's hardcodedwhen.TipUserModal(presets, token row, slide-to-confirm) + affordability gating; no-balance routes to add-money/discover and dismisses the card.navigateAll([Tips, Chat])) so back returns to the tips list.Amount entry (
features/tipping)Wiring
TipCardDelegate,/tip/{userId}deeplink + routes,MainActivityLocalTipCoordinatorprovision, tip-card sharing, and token-selection wired for theTippurpose.Notes
foundation-layoutversion-catalog entry (scanner animation) andModal.verticalArrangement(used only byTipUserModal).TippingCoordinatorTestcovers the send-limit / max-amount logic.