From 1e86e15291a9c5775f6134462392b1bb7bfceb82 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 27 Apr 2026 17:54:16 -0400 Subject: [PATCH] Adjustments to the loading and updating of the nest event in a PiPActivity --- .../home/live/RenderLiveActivityBubble.kt | 5 -- .../screen/loggedIn/nests/NestsFeedLoaded.kt | 5 -- .../loggedIn/nests/create/CreateNestSheet.kt | 5 -- .../loggedIn/nests/room/NestActivity.kt | 36 +----------- .../nests/room/NestActivityContent.kt | 56 +++++++++++++------ .../loggedIn/nests/room/NestFullScreen.kt | 33 +++-------- .../loggedIn/nests/room/NestJoinCard.kt | 11 +--- .../loggedIn/nests/room/ParticipantsGrid.kt | 11 ++-- 8 files changed, 55 insertions(+), 107 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/live/RenderLiveActivityBubble.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/live/RenderLiveActivityBubble.kt index 045df9371..d573c8516 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/live/RenderLiveActivityBubble.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/live/RenderLiveActivityBubble.kt @@ -77,11 +77,6 @@ fun RenderLiveActivityBubble( NestActivity.launch( context = context, addressValue = meetingEvent.address().toValue(), - authBaseUrl = service, - endpoint = endpoint, - hostPubkey = meetingEvent.pubKey, - roomId = dTag, - kind = meetingEvent.kind, ) } else { // Fall back to the channel route so the user diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsFeedLoaded.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsFeedLoaded.kt index 4d3d2639b..436fbf0cf 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsFeedLoaded.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/NestsFeedLoaded.kt @@ -149,11 +149,6 @@ private fun NestFeedCard( NestActivity.launch( context = context, addressValue = meetingEvent.address().toValue(), - authBaseUrl = service, - endpoint = endpoint, - hostPubkey = meetingEvent.pubKey, - roomId = dTag, - kind = meetingEvent.kind, ) } else { nav.nav { routeFor(baseNote, accountViewModel.account) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestSheet.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestSheet.kt index 604df59e0..bdad98bae 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestSheet.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/create/CreateNestSheet.kt @@ -195,11 +195,6 @@ fun CreateNestSheet( NestActivity.launch( context = context, addressValue = launchInfo.addressValue, - authBaseUrl = launchInfo.authBaseUrl, - endpoint = launchInfo.endpoint, - hostPubkey = launchInfo.hostPubkey, - roomId = launchInfo.roomId, - kind = launchInfo.kind, ) onDismiss() } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivity.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivity.kt index 08e42af7e..045b07863 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivity.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivity.kt @@ -98,18 +98,7 @@ class NestActivity : AppCompatActivity() { val accountViewModel = NestBridge.accountViewModel val addressValue = intent.getStringExtra(EXTRA_ADDRESS) - val authBaseUrl = intent.getStringExtra(EXTRA_AUTH_BASE_URL) - val endpoint = intent.getStringExtra(EXTRA_ENDPOINT) - val hostPubkey = intent.getStringExtra(EXTRA_HOST_PUBKEY) - val roomId = intent.getStringExtra(EXTRA_ROOM_ID) - val kind = intent.getIntExtra(EXTRA_KIND, com.vitorpamplona.nestsclient.NestsRoomConfig.MEETING_SPACE_KIND) - if (accountViewModel == null || - addressValue == null || - authBaseUrl == null || - endpoint == null || - hostPubkey == null || - roomId == null - ) { + if (accountViewModel == null || addressValue == null) { // After process death the bridge is empty (the previous // process's AccountViewModel is gone). Bounce the user back to // MainActivity so they land on the lobby instead of a black @@ -147,14 +136,6 @@ class NestActivity : AppCompatActivity() { AmethystTheme { NestActivityContent( addressValue = addressValue, - room = - com.vitorpamplona.nestsclient.NestsRoomConfig( - authBaseUrl = authBaseUrl, - endpoint = endpoint, - hostPubkey = hostPubkey, - roomId = roomId, - kind = kind, - ), accountViewModel = accountViewModel, isInPipMode = isInPipMode.value, onMuteState = { muted -> @@ -252,11 +233,6 @@ class NestActivity : AppCompatActivity() { companion object { const val EXTRA_ADDRESS = "com.vitorpamplona.amethyst.NEST_ADDRESS" - const val EXTRA_AUTH_BASE_URL = "com.vitorpamplona.amethyst.NEST_AUTH_BASE_URL" - const val EXTRA_ENDPOINT = "com.vitorpamplona.amethyst.NEST_ENDPOINT" - const val EXTRA_HOST_PUBKEY = "com.vitorpamplona.amethyst.NEST_HOST_PUBKEY" - const val EXTRA_ROOM_ID = "com.vitorpamplona.amethyst.NEST_ROOM_ID" - const val EXTRA_KIND = "com.vitorpamplona.amethyst.NEST_KIND" private const val ACTION_PIP_TOGGLE_MUTE = "com.vitorpamplona.amethyst.NEST_PIP_MUTE" private const val ACTION_PIP_LEAVE = "com.vitorpamplona.amethyst.NEST_PIP_LEAVE" private const val PIP_MUTE_REQ = 0x6A001 @@ -265,21 +241,11 @@ class NestActivity : AppCompatActivity() { fun launch( context: Context, addressValue: String, - authBaseUrl: String, - endpoint: String, - hostPubkey: String, - roomId: String, - kind: Int, ) { context.startActivity( Intent(context, NestActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) putExtra(EXTRA_ADDRESS, addressValue) - putExtra(EXTRA_AUTH_BASE_URL, authBaseUrl) - putExtra(EXTRA_ENDPOINT, endpoint) - putExtra(EXTRA_HOST_PUBKEY, hostPubkey) - putExtra(EXTRA_ROOM_ID, roomId) - putExtra(EXTRA_KIND, kind) }, ) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivityContent.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivityContent.kt index 542aea65e..807eeb542 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivityContent.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestActivityContent.kt @@ -27,9 +27,14 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.lifecycle.viewmodel.compose.viewModel +import com.vitorpamplona.amethyst.commons.model.AddressableNote +import com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel +import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteEvent import com.vitorpamplona.amethyst.ui.note.LoadAddressableNote import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.NestRoomFilterAssemblerSubscription +import com.vitorpamplona.nestsclient.NestsRoomConfig import com.vitorpamplona.quartz.nip01Core.core.Address import com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.MeetingSpaceEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.tags.ROLE @@ -43,7 +48,6 @@ import kotlinx.coroutines.flow.SharedFlow @Composable internal fun NestActivityContent( addressValue: String, - room: com.vitorpamplona.nestsclient.NestsRoomConfig, accountViewModel: AccountViewModel, isInPipMode: Boolean, onMuteState: (Boolean) -> Unit, @@ -61,18 +65,37 @@ internal fun NestActivityContent( LoadAddressableNote(parsedAddress, accountViewModel) { addressableNote -> addressableNote ?: return@LoadAddressableNote - val event = addressableNote.event as? MeetingSpaceEvent ?: return@LoadAddressableNote - NestActivityBody( - event = event, - roomNote = addressableNote, - room = room, - accountViewModel = accountViewModel, - isInPipMode = isInPipMode, - onMuteState = onMuteState, - onConnectedChange = onConnectedChange, - pipMuteSignal = pipMuteSignal, - onLeave = onLeave, - ) + val event by observeNoteEvent(addressableNote, accountViewModel) + + event?.let { + val service = it.service() + val endPoint = it.endpoint() + if (service != null && endPoint != null) { + val viewModel = + rememberNestViewModel( + NestsRoomConfig( + authBaseUrl = service, + endpoint = endPoint, + hostPubkey = it.pubKey, + roomId = it.dTag(), + kind = it.kind, + ), + accountViewModel.account.signer, + ) + + NestActivityBody( + event = it, + roomNote = addressableNote, + viewModel = viewModel, + accountViewModel = accountViewModel, + isInPipMode = isInPipMode, + onMuteState = onMuteState, + onConnectedChange = onConnectedChange, + pipMuteSignal = pipMuteSignal, + onLeave = onLeave, + ) + } + } } } @@ -90,8 +113,8 @@ internal fun NestActivityContent( @Composable private fun NestActivityBody( event: MeetingSpaceEvent, - roomNote: com.vitorpamplona.amethyst.model.AddressableNote, - room: com.vitorpamplona.nestsclient.NestsRoomConfig, + roomNote: AddressableNote, + viewModel: NestViewModel, accountViewModel: AccountViewModel, isInPipMode: Boolean, onMuteState: (Boolean) -> Unit, @@ -101,7 +124,7 @@ private fun NestActivityBody( ) { val account = accountViewModel.account val localPubkey = account.signer.pubKey - val roomATag = remember(event) { event.address().toValue() } + val roomATag = roomNote.idHex // Static room layout: hosts + speakers from the kind-30312 `p`-tags. // The grid renderer derives audience from the kind-10312 presence @@ -116,7 +139,6 @@ private fun NestActivityBody( } val onStageKeys = remember(onStage) { onStage.map { it.pubKey }.toSet() } - val viewModel = rememberNestViewModel(room, account.signer) AutoConnectAndTrackSpeakers(viewModel, onStageKeys) // Single REQ per relay covering chat, presence, reactions, admin diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestFullScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestFullScreen.kt index cec828be3..c5356a2c7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestFullScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestFullScreen.kt @@ -48,7 +48,6 @@ import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TextButton -import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -72,6 +71,8 @@ import com.vitorpamplona.amethyst.commons.viewmodels.ConnectionUiState import com.vitorpamplona.amethyst.commons.viewmodels.NestUiState import com.vitorpamplona.amethyst.commons.viewmodels.NestViewModel import com.vitorpamplona.amethyst.commons.viewmodels.RoomTheme +import com.vitorpamplona.amethyst.commons.viewmodels.buildParticipantGrid +import com.vitorpamplona.amethyst.ui.navigation.topbars.ShorterTopAppBar import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.quartz.nip01Core.tags.aTag.ATag @@ -151,17 +152,15 @@ internal fun NestFullScreen( Column( modifier = Modifier - .weight(1f, fill = false) + .weight(1f) .verticalScroll(rememberScrollState()) - .padding(horizontal = 16.dp) - .padding(top = 8.dp), + .padding(horizontal = 16.dp), ) { event.summary()?.let { Text( text = it, style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.padding(top = 4.dp), ) } @@ -169,20 +168,6 @@ internal fun NestFullScreen( // in the room. Hidden until the aggregator has at least one // entry so the placeholder doesn't flash on entry. val presences by viewModel.presences.collectAsState() - val listenerCount = presences.size - if (listenerCount > 0) { - Text( - text = - androidx.compose.ui.res.pluralStringResource( - R.plurals.nest_listener_count, - listenerCount, - listenerCount, - ), - style = MaterialTheme.typography.bodySmall, - color = MaterialTheme.colorScheme.onSurfaceVariant, - modifier = Modifier.padding(top = 4.dp), - ) - } val reactionsByPubkey by viewModel.recentReactions.collectAsState() var hostMenuTarget by rememberSaveable { mutableStateOf(null) } @@ -198,7 +183,7 @@ internal fun NestFullScreen( // greys out at 50 % alpha, matching nostrnests' web client. val participantGrid = androidx.compose.runtime.remember(event, presences) { - com.vitorpamplona.amethyst.commons.viewmodels.buildParticipantGrid( + buildParticipantGrid( participants = event.participants(), presences = presences, ) @@ -324,11 +309,7 @@ internal fun NestFullScreen( event = event, viewModel = viewModel, accountViewModel = accountViewModel, - modifier = - Modifier - .weight(1f, fill = true) - .padding(horizontal = 16.dp) - .padding(top = 12.dp, bottom = 16.dp), + modifier = Modifier.weight(1f), ) } } @@ -367,7 +348,7 @@ private fun NestTopAppBar( onShare: () -> Unit, onEdit: () -> Unit, ) { - TopAppBar( + ShorterTopAppBar( title = { Text( text = title, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestJoinCard.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestJoinCard.kt index e5afd5b9f..da3651c9d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestJoinCard.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/NestJoinCard.kt @@ -296,10 +296,6 @@ fun JoinNestButton( 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 - val colors = if (primaryColorOverride != null) { androidx.compose.material3.ButtonDefaults @@ -314,12 +310,7 @@ fun JoinNestButton( NestBridge.set(accountViewModel) NestActivity.launch( context = context, - addressValue = addressValue, - authBaseUrl = serviceBase, - endpoint = endpoint, - hostPubkey = hostPubkey, - roomId = roomId, - kind = kind, + addressValue = event.address().toValue(), ) }, colors = colors, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantsGrid.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantsGrid.kt index e1b27c80f..e789d798c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantsGrid.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/ParticipantsGrid.kt @@ -28,7 +28,6 @@ import androidx.compose.animation.core.rememberInfiniteTransition import androidx.compose.animation.core.tween import androidx.compose.foundation.background import androidx.compose.foundation.border -import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer @@ -60,10 +59,13 @@ import com.vitorpamplona.amethyst.commons.viewmodels.ParticipantGrid import com.vitorpamplona.amethyst.commons.viewmodels.RoomMember import com.vitorpamplona.amethyst.commons.viewmodels.RoomReaction 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.amethyst.ui.theme.Size35dp import com.vitorpamplona.amethyst.ui.theme.Size40dp +import com.vitorpamplona.amethyst.ui.theme.SpacedBy10dp +import com.vitorpamplona.amethyst.ui.theme.SpacedBy5dp import kotlinx.collections.immutable.ImmutableSet /** @@ -155,7 +157,7 @@ private fun ParticipantsSection( val absentAlphaModifier = remember { Modifier.alpha(0.5f) } val speakingBorderModifier = remember(ringColor) { Modifier.border(2.dp, ringColor, CircleShape) } val spinnerModifier = remember(avatarSize) { Modifier.size(avatarSize - 8.dp) } - Column(modifier = Modifier.padding(top = 8.dp)) { + Column(modifier = Modifier.padding(top = 8.dp), verticalArrangement = SpacedBy5dp) { Text( text = title, style = MaterialTheme.typography.labelMedium, @@ -168,7 +170,7 @@ private fun ParticipantsSection( LazyHorizontalGrid( rows = GridCells.Fixed(1), modifier = gridModifier, - horizontalArrangement = Arrangement.spacedBy(6.dp), + horizontalArrangement = SpacedBy5dp, ) { items(items = members, key = { it.pubkey }) { member -> val isSpeaking = member.pubkey in speakingNow @@ -196,6 +198,7 @@ private fun ParticipantsSection( val isConnecting = member.pubkey in connectingSpeakers Column( horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = SpacedBy10dp, modifier = cellWidthModifier, ) { Box(contentAlignment = Alignment.Center) { @@ -234,7 +237,7 @@ private fun ParticipantsSection( ) } } - com.vitorpamplona.amethyst.ui.note.UsernameDisplay( + UsernameDisplay( baseUser = user, weight = Modifier.fillMaxWidth(), accountViewModel = accountViewModel,