From cc33bdbb92dce69f01da8f005d80eb4f83f57108 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 26 Apr 2026 22:57:40 +0000 Subject: [PATCH] feat(audio-rooms): share-room as naddr1 (T2 #4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a "Share room" action to the room overflow menu (visible to EVERYONE — share isn't host-restricted; the host-only "Edit room" row is now gated alongside it). Builds an `nostr:naddr1...` URI from the room's kind / hostPubkey / dTag via Quartz's `ATag.toNAddr()` helper and hands it to the system share sheet with the room title as a preview blurb. shareRoomNaddr(context, event): aTag = ATag(event.kind, event.pubKey, event.dTag(), null) naddr = aTag.toNAddr() text = " — nostr:<naddr>" Intent.ACTION_SEND → createChooser AudioRoomFullScreen — overflow menu now visible to all members. Share row appears for everyone; Edit row appears only when the local user is the room's host. Strings: audio_room_share_action. Step 3 (zap entry points) is intentionally NOT in this commit — the existing zap UI is built around the per-note ZapReaction in ReactionsRow.kt with long-press-to-set-amount + click-to-zap, which is heavy to embed inside the audio room. The reactions sub already pulls kind 9735 receipts so paid zaps SURFACE in the floating overlay; the SEND path can ship as a follow-up that wires the existing `accountViewModel.zap(note, amount, ...)` flow with ZapPaymentHandler from inside the participant context sheet. --- .../audiorooms/room/AudioRoomFullScreen.kt | 57 +++++++++++++++---- amethyst/src/main/res/values/strings.xml | 1 + 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomFullScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomFullScreen.kt index 723caf50c..a769b4f9a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomFullScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomFullScreen.kt @@ -63,6 +63,7 @@ import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.theme.Size35dp import com.vitorpamplona.amethyst.ui.theme.Size40dp import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag +import com.vitorpamplona.quartz.nip19Bech32.toNAddr import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ParticipantTag @@ -111,18 +112,28 @@ internal fun AudioRoomFullScreen( modifier = Modifier.weight(1f), ) } - if (isHost) { - Box { - androidx.compose.material3.IconButton(onClick = { showHostMenu = true }) { - Icon( - symbol = MaterialSymbols.MoreVert, - contentDescription = stringRes(R.string.audio_room_overflow_menu), - ) - } - androidx.compose.material3.DropdownMenu( - expanded = showHostMenu, - onDismissRequest = { showHostMenu = false }, - ) { + // Overflow menu — visible to everyone (Share); host-only + // rows (Edit) are gated inside. + Box { + androidx.compose.material3.IconButton(onClick = { showHostMenu = true }) { + Icon( + symbol = MaterialSymbols.MoreVert, + contentDescription = stringRes(R.string.audio_room_overflow_menu), + ) + } + val context = androidx.compose.ui.platform.LocalContext.current + androidx.compose.material3.DropdownMenu( + expanded = showHostMenu, + onDismissRequest = { showHostMenu = false }, + ) { + androidx.compose.material3.DropdownMenuItem( + text = { Text(stringRes(R.string.audio_room_share_action)) }, + onClick = { + showHostMenu = false + shareRoomNaddr(context, event) + }, + ) + if (isHost) { androidx.compose.material3.DropdownMenuItem( text = { Text(stringRes(R.string.audio_room_edit_title)) }, onClick = { @@ -461,3 +472,25 @@ private fun TalkRow( } } } + +/** + * Build an `nostr:naddr1...` URI for the room and hand it to the + * system share sheet. Includes the room title in the share text + * so the receiving app can render a preview without round-tripping + * the relay. + */ +private fun shareRoomNaddr( + context: android.content.Context, + event: MeetingSpaceEvent, +) { + val aTag = ATag(event.kind, event.pubKey, event.dTag(), null) + val naddr = aTag.toNAddr() + val title = event.room().orEmpty() + val text = if (title.isNotBlank()) "$title — nostr:$naddr" else "nostr:$naddr" + val intent = + android.content.Intent(android.content.Intent.ACTION_SEND).apply { + type = "text/plain" + putExtra(android.content.Intent.EXTRA_TEXT, text) + } + context.startActivity(android.content.Intent.createChooser(intent, null)) +} diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index 87cef0dd6..4e5f4d24c 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -544,6 +544,7 @@ <string name="audio_room_participant_unfollow">Unfollow</string> <string name="audio_room_participant_mute">Mute</string> <string name="audio_room_participant_unmute">Unmute</string> + <string name="audio_room_share_action">Share room</string> <string name="audio_room_create_fab">Start space</string> <string name="audio_room_create_title">Start a new audio room</string> <string name="audio_room_create_field_room">Room name</string>