diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt index f678598bd7..eae46e8aa7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt @@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.ui.note.types import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -158,6 +159,24 @@ fun RenderMeetingSpaceEventInner( } RenderParticipants(participants, accountViewModel, nav) + + // In-feed Join button — closes the deep-link loop. A + // `nostr:naddr1...` for a kind-30312 lands here through + // MainActivity's URI handler → Route.Note(addressTag) → this + // renderer; without a button the user has no path into the + // audio room. JoinAudioRoomButton hides itself when the + // event lacks service / endpoint / d-tag. + if (status != MeetingSpaceStatusTag.STATUS.CLOSED) { + Row( + modifier = Modifier.fillMaxWidth().padding(top = 8.dp), + horizontalArrangement = Arrangement.End, + ) { + com.vitorpamplona.amethyst.ui.screen.loggedIn.audiorooms.room.JoinAudioRoomButton( + event = noteEvent, + accountViewModel = accountViewModel, + ) + } + } } @Composable diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomJoinCard.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomJoinCard.kt index 9ea42ac8ad..f84fc64c74 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomJoinCard.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/audiorooms/room/AudioRoomJoinCard.kt @@ -107,21 +107,48 @@ private fun AudioRoomJoinCardContent( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, ) { - Button(onClick = { - AudioRoomBridge.set(accountViewModel) - AudioRoomActivity.launch( - context = context, - addressValue = addressValue, - authBaseUrl = serviceBase, - endpoint = endpoint, - hostPubkey = hostPubkey, - roomId = roomId, - kind = kind, - ) - }) { - Text(stringRes(R.string.audio_room_join)) - } + JoinAudioRoomButton(event = event, accountViewModel = accountViewModel) } } } } + +/** + * Standalone "Join audio room" button. Reusable from any composable + * that has a [MeetingSpaceEvent] in hand — the lobby card, the + * in-feed note renderer (so a `nostr:naddr1...` deep-link to a + * kind-30312 lands one tap away from the room), and any future + * room-list surface. Renders nothing for events without a + * service / endpoint / d-tag — those rooms can't be joined on + * the audio plane. + */ +@Composable +fun JoinAudioRoomButton( + event: MeetingSpaceEvent, + accountViewModel: AccountViewModel, +) { + val serviceBase = event.service() + val endpoint = event.endpoint() + val roomId = event.address().dTag + if (serviceBase.isNullOrBlank() || endpoint.isNullOrBlank() || roomId.isBlank()) return + + val context = LocalContext.current + val addressValue = remember(event) { event.address().toValue() } + val hostPubkey = event.pubKey + val kind = event.kind + + Button(onClick = { + AudioRoomBridge.set(accountViewModel) + AudioRoomActivity.launch( + context = context, + addressValue = addressValue, + authBaseUrl = serviceBase, + endpoint = endpoint, + hostPubkey = hostPubkey, + roomId = roomId, + kind = kind, + ) + }) { + Text(stringRes(R.string.audio_room_join)) + } +}