Skip to content

feat(activity): badge person avatars with the token the row moved in - #1386

Merged
bmc08gt merged 1 commit into
code/cashfrom
feat/activity-token-badge
Aug 31, 2026
Merged

feat(activity): badge person avatars with the token the row moved in#1386
bmc08gt merged 1 commit into
code/cashfrom
feat/activity-token-badge

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

An activity row for a tip or a peer send draws the counterparty's face, so nothing in it names the token — a tip in dollars and a tip in a creator coin read identically. This draws the mint as a small coin over the avatar's bottom-right corner, per node 9717:14138: a 40dp avatar centred in a 48dp slot, with a 20dp badge ringed 2dp in the page background.

Only person-shaped avatars carry one. TokenIcon and SwapTokens rows already are the token, so badging them would repeat it. Rows reserve the full 48dp slot whether or not they badge, so titles stay aligned down the list.

The resolution path

The badge needed a new one. observeTokenCache() only ever holds mints the user has an account for, and a tip commonly arrives in a creator coin the recipient holds nothing of — so exactly the rows this design targets would never resolve a token.

ensureBadgeToken fetches such a mint once and memoizes it, following the existing ensureProfile shape: an in-flight key set collapses concurrent misses, a MutableStateFlow memo keeps the answer, and it only fires for rows that have a counterparty. A mint therefore costs at most one request for the process. That bound is the point — the design this replaces called getTokenMetadata per item inside the paging transform, with nowhere to put the answer for an unheld mint, so every page emission re-fetched the same mints until the wallet locked up. Held-token metadata is layered over the memo so balance-driven refreshes win, and the memo clears on loss of API access.

The coordinator's three duplicated message-to-row mapping blocks are collapsed into one resolveRow along the way.

Notes

  • The token-info screen (recentTransactions(mint, limit)) will now badge every person row with the same token as the screen itself. Arguably redundant, but I kept the rule uniform rather than making a per-surface exception here.
  • Figma's ring is #19191A; this uses CodeTheme.colors.background to match the ring SwapAvatar already draws.
  • The older features/transactions FeedItem UI is a separate screen and is untouched.

An activity row for a tip or a peer send draws the counterparty's face, so
nothing in it names the token: a tip in dollars and a tip in a creator coin
read identically. Draw the mint as a small coin over the avatar's
bottom-right corner (node 9717:14138) — 40dp avatar centred in a 48dp slot,
20dp badge ringed in the page background. Only person-shaped avatars get one;
a token or swap avatar already is the token.

Rows reserve the full 48dp slot whether or not they badge, so titles stay
aligned down the list.

The badge needed a new resolution path. `observeTokenCache()` only ever holds
mints the user has an account for, and a tip commonly arrives in a creator
coin the recipient holds nothing of, so those rows would never resolve a
token. `ensureBadgeToken` fetches such a mint once and memoizes it, following
the existing `ensureProfile` shape: an in-flight key set collapses concurrent
misses and the memo keeps the answer, so a mint costs at most one request.
That matters here — the design this replaces called `getTokenMetadata` per
item inside the paging transform, re-fetching never-cached mints on every
emission until the wallet locked up. Held-token metadata is layered over the
memo so balance-driven refreshes win, and the memo clears on loss of API
access.

Also collapses the coordinator's three duplicated message-to-row mapping
blocks into one `resolveRow`.
@bmc08gt bmc08gt self-assigned this Aug 31, 2026
@github-actions github-actions Bot added the type: feature New functionality label Aug 31, 2026
@bmc08gt
bmc08gt merged commit 4f94c6e into code/cash Aug 31, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: feature New functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant