Favorites consent, visible mutuality, and honest copy - #1663
Favorites consent, visible mutuality, and honest copy#1663jackjackbits wants to merge 4 commits into
Conversation
The star read like a private bookmark but behaved like a friend
request plus an identity handshake: tapping it immediately notified
the peer ("alice favorited you") and transmitted the durable Nostr
public key — while the tapper saw nothing. And the load-bearing state,
mutuality (one-sided favorites do NOT enable offline delivery), was
invisible at the point of decision.
- One-time consent: the first favorite ever asks, naming the person
and disclosing the notification + key sharing (both star surfaces:
peer list and DM header). Acknowledged once; reset by panic wipe.
/fav (an explicit typed command) proceeds without a dialog.
- Mutuality visible where the decision happens: half star until
reciprocated, filled star when mutual, with tooltips and VoiceOver
state labels for both. The DM header state now carries
isMutualFavorite.
- FEATURES copy described favorites as notifications; it now leads
with the actual mechanism (offline messaging via nostr when mutual).
- Geohash block copy no longer implies a global block: identities are
derived per-geohash, so the same person appears as someone new in
other channels — the message says so now (both the context-menu and
/block paths).
7 new strings + 3 updated values, all 30 locales.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d4d78e85eb
ℹ️ 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".
| if !peer.isFavorite, !FavoriteConsent.isAcknowledged { | ||
| pendingFavorite = peer | ||
| } else { | ||
| onToggleFavorite(peer.peerID) |
There was a problem hiding this comment.
Apply consent to every favorite action
On a fresh install, choosing “Add favorite” from the row's context menu or VoiceOver custom actions still invokes onToggleFavorite directly at lines 223–224 and 248–249. Those paths therefore notify the peer and disclose the user's durable Nostr key without showing the newly required consent dialog; route all add-favorite actions through the pendingFavorite flow while allowing removals to remain immediate.
Useful? React with 👍 / 👎.
| .contentShape(Rectangle()) | ||
| } | ||
| .buttonStyle(.plain) | ||
| .help(peer.isMutualFavorite ? Strings.favoriteMutualTooltip : Strings.favoritePendingTooltip) |
There was a problem hiding this comment.
Show the pending tooltip only for actual favorites
For every non-favorite peer, both isMutualFavorite and isFavorite are false, so hovering the empty star displays “favorited — offline messaging starts when they favorite you back” even though the user has not favorited that peer. Select an add-favorite tooltip for the unfavorited state, and reserve favoritePendingTooltip for one-sided favorites.
Useful? React with 👍 / 👎.
…tooltip - Codex P1: the context-menu and VoiceOver "add favorite" actions called onToggleFavorite directly, bypassing the one-time consent dialog and disclosing the nostr key without asking. All add-favorite entry points now route through requestFavoriteToggle (consent gate); removals stay immediate. - Codex P2: the empty star showed the "favorited — offline messaging starts when they favorite you back" tooltip on peers that weren't favorited at all. The pending/mutual copy now applies only once isFavorite; an unfavorited star reads "add favorite". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Both Codex findings addressed: every add-favorite entry point (star button, context menu, VoiceOver custom action) now routes through |
- CommandProcessorTests still asserted the old "blocked … in geohash chats" copy that this branch rewrote to the per-channel wording. - The `mesh_peers.state.favorite` state constant was replaced by the mutual/pending pair and left unused — Periphery (now blocking) flagged it. Removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tier-1 batch 5/6. The star read like a private bookmark but behaved like a friend request + identity handshake: it immediately notified the peer and transmitted your durable Nostr key, while the tapper saw nothing — and mutuality (the state that actually gates offline delivery) was invisible at the point of decision. Now: a one-time consent dialog before the first favorite (both star surfaces; /fav as an explicit typed command proceeds without a dialog; acknowledged flag resets on panic wipe); half star until reciprocated with tooltips + VoiceOver labels; FEATURES copy leads with the real mechanism instead of notifications; and geohash block copy says the block is per-channel (identities are derived per-geohash) on both the context-menu and /block paths. 7 new strings + 3 updated values × 30 locales.
🤖 Generated with Claude Code