From ffe9637c8d5d1e6901806f6e9ea9257ef27d7261 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Jul 2026 15:58:47 +0000 Subject: [PATCH] feat(relayauth): resolve real venue names in the auth prompt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The venue prompt said generic "this room"; now it names the actual place. rememberVenueLabel resolves a public chat channel's title (by event id), a live activity's title (by address), or a community's d-identifier (its NIP-72 name), falling back to the address d-tag / short id when the venue isn't cached. So the prompt reads "Post to nostr-dev?" / "Open ?" with a matching consequence ("…your message to nostr-dev won't be posted."), reusing the same who-slot as the person purposes. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01EZjmYpgHP4pf79Sav5QT8a --- .../compose/RelayAuthPromptHost.kt | 39 ++++++++++++++++--- amethyst/src/main/res/values/strings.xml | 8 ++-- 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/authCommand/compose/RelayAuthPromptHost.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/authCommand/compose/RelayAuthPromptHost.kt index ff2edc8014..da8bac82c8 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/authCommand/compose/RelayAuthPromptHost.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/relayClient/authCommand/compose/RelayAuthPromptHost.kt @@ -63,6 +63,7 @@ import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture import com.vitorpamplona.amethyst.ui.note.UsernameDisplay import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes +import com.vitorpamplona.quartz.nip01Core.core.Address import com.vitorpamplona.quartz.nip01Core.core.HexKey /** Above this many counterparties for a purpose, collapse the named rows into an avatar facepile. */ @@ -108,7 +109,14 @@ private fun RelayAuthPromptDialog( // The action the user was actually doing drives the title and the "if you don't" consequence, // so the out-of-context prompt reconnects to their intent. val primary = remember(prompt) { prompt.purposes.primaryNamed() } - val who = primary?.let { counterpartyLabel(it.counterparties, accountViewModel) } + val who = + primary?.let { p -> + when (p.kind) { + AuthPurposeKind.POST_VENUE, AuthPurposeKind.READ_VENUE -> + p.venues.firstOrNull()?.let { rememberVenueLabel(it, accountViewModel) } + else -> counterpartyLabel(p.counterparties, accountViewModel) + } + } val showLabels = prompt.purposes.size > 1 AlertDialog( @@ -292,8 +300,8 @@ private fun titleFor( AuthPurposeKind.SEND_DM -> stringRes(R.string.relay_auth_title_send_dm, who ?: "") AuthPurposeKind.NOTIFY_INBOX -> stringRes(R.string.relay_auth_title_notify, who ?: "") AuthPurposeKind.READ_OUTBOX -> stringRes(R.string.relay_auth_title_read, who ?: "") - AuthPurposeKind.POST_VENUE -> stringRes(R.string.relay_auth_title_post_venue) - AuthPurposeKind.READ_VENUE -> stringRes(R.string.relay_auth_title_read_venue) + AuthPurposeKind.POST_VENUE -> stringRes(R.string.relay_auth_title_post_venue, who ?: "") + AuthPurposeKind.READ_VENUE -> stringRes(R.string.relay_auth_title_read_venue, who ?: "") else -> stringRes(R.string.relay_auth_prompt_title) } @@ -306,8 +314,8 @@ private fun consequenceFor( AuthPurposeKind.SEND_DM -> stringRes(R.string.relay_auth_consequence_send_dm, who ?: "") AuthPurposeKind.NOTIFY_INBOX -> stringRes(R.string.relay_auth_consequence_notify, who ?: "") AuthPurposeKind.READ_OUTBOX -> stringRes(R.string.relay_auth_consequence_read, who ?: "") - AuthPurposeKind.POST_VENUE -> stringRes(R.string.relay_auth_consequence_post_venue) - AuthPurposeKind.READ_VENUE -> stringRes(R.string.relay_auth_consequence_read_venue) + AuthPurposeKind.POST_VENUE -> stringRes(R.string.relay_auth_consequence_post_venue, who ?: "") + AuthPurposeKind.READ_VENUE -> stringRes(R.string.relay_auth_consequence_read_venue, who ?: "") else -> null } @@ -322,6 +330,27 @@ private fun counterpartyLabel( return if (pubkeys.size > 1) stringRes(R.string.relay_auth_name_and_others, name) else name } +/** + * A display name for a venue id — a public chat channel (64-hex event id), a NIP-53 live activity, + * or a NIP-72 community. Uses the cached channel title where available (the venue is one we're + * actively using, so it's usually loaded), falling back to the address's d-identifier, which is the + * community name in NIP-72. + */ +@Composable +private fun rememberVenueLabel( + venueId: String, + accountViewModel: AccountViewModel, +): String = + remember(venueId) { + val resolved = + when { + venueId.length == 64 -> accountViewModel.getPublicChatChannelIfExists(venueId)?.toBestDisplayName() + venueId.startsWith("30311:") -> Address.parse(venueId)?.let { accountViewModel.getLiveActivityChannelIfExists(it)?.toBestDisplayName() } + else -> null + } + resolved ?: venueId.substringAfterLast(':').ifEmpty { venueId.take(8) } + } + /** The best display name for [pubkey], reactive to metadata arriving from relays. */ @Composable private fun rememberDisplayName( diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index 43702d9c8a..55f35185b4 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -835,14 +835,14 @@ Send your message to %1$s? Notify %1$s? Load posts from %1$s? - Post to this room? - Open this room? + Post to %1$s? + Open %1$s? If you don\'t, your message to %1$s won\'t be delivered. If you don\'t, %1$s won\'t be notified about this. If you don\'t, you won\'t see posts from %1$s here. - If you don\'t, your message won\'t be posted. - If you don\'t, you won\'t see it here. + If you don\'t, your message to %1$s won\'t be posted. + If you don\'t, you won\'t see %1$s here. %1$s and others Send your private message to: Notify: