diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestActionBar.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestActionBar.kt index c723c2491..ce8bb9c9b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestActionBar.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestActionBar.kt @@ -154,7 +154,7 @@ internal fun StageControlsBar( modifier = modifier .fillMaxWidth() - .padding(horizontal = 16.dp, vertical = 8.dp), + .padding(top = 8.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp), ) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestFullScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestFullScreen.kt index 32fb19579..ed6f90ea2 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestFullScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/screen/NestFullScreen.kt @@ -246,18 +246,20 @@ internal fun NestFullScreen( onTapSelf = onTapSelf, listenerCount = presences.size, modifier = Modifier.padding(horizontal = 16.dp), - ) - // Speaker controls live attached to the Stage card so they - // only render when the user is actually on stage. This keeps - // the action bar narrow for audience and makes the controls - // appearing/disappearing a deliberate signal that the mic - // is now (or no longer) available. - StageControlsBar( - viewModel = viewModel, - ui = ui, - isOnStage = isOnStageMe, - canBroadcast = viewModel.canBroadcast, - speakerPubkeyHex = myPubkey, + // Speaker controls live inside the Stage card so they + // only render when the user is actually on stage. This + // keeps the action bar narrow for audience and makes + // the controls appearing/disappearing a deliberate + // signal that the mic is now (or no longer) available. + bottomBar = { + StageControlsBar( + viewModel = viewModel, + ui = ui, + isOnStage = isOnStageMe, + canBroadcast = viewModel.canBroadcast, + speakerPubkeyHex = myPubkey, + ) + }, ) NestActionBar( viewModel = viewModel, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/stage/ParticipantsGrid.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/stage/ParticipantsGrid.kt index 01ecb4181..0e8efdefb 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/stage/ParticipantsGrid.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/room/stage/ParticipantsGrid.kt @@ -126,6 +126,10 @@ private val STAGE_MAX_HEIGHT = 320.dp * * When [members] is empty, renders an "Waiting for speakers…" hint * instead so the strip stays visually anchored. + * + * [bottomBar] is rendered inside the same Surface, below the grid — + * used to anchor speaker controls to the stage card so they only + * appear when the local user is on stage. */ @Composable internal fun StageGrid( @@ -140,6 +144,7 @@ internal fun StageGrid( myPubkey: String? = null, onTapSelf: (() -> Unit)? = null, listenerCount: Int = 0, + bottomBar: (@Composable () -> Unit)? = null, ) { // Float currently-speaking members to the top so the listener can // see who they're hearing without scrolling. sortedBy is stable in @@ -193,32 +198,33 @@ internal fun StageGrid( } if (members.isEmpty()) { EmptyStageHint() - return@Column - } - LazyVerticalGrid( - columns = GridCells.Adaptive(STAGE_CELL_MIN), - modifier = Modifier.fillMaxWidth().heightIn(max = STAGE_MAX_HEIGHT), - horizontalArrangement = Arrangement.spacedBy(GRID_SPACING), - verticalArrangement = Arrangement.spacedBy(GRID_SPACING), - ) { - items(items = sortedMembers, key = { it.pubkey }) { member -> - val isSelf = myPubkey != null && member.pubkey == myPubkey - MemberCell( - member = member, - avatarSize = STAGE_AVATAR, - isSpeaking = member.pubkey in speakingNow, - audioLevel = audioLevels[member.pubkey] ?: 0f, - isConnecting = member.pubkey in connectingSpeakers, - showMicBadge = true, - reactions = reactionsByPubkey[member.pubkey].orEmpty(), - accountViewModel = accountViewModel, - onLongPressParticipant = onLongPressParticipant, - isSelf = isSelf, - onTapSelf = if (isSelf) onTapSelf else null, - modifier = Modifier.animateItem(), - ) + } else { + LazyVerticalGrid( + columns = GridCells.Adaptive(STAGE_CELL_MIN), + modifier = Modifier.fillMaxWidth().heightIn(max = STAGE_MAX_HEIGHT), + horizontalArrangement = Arrangement.spacedBy(GRID_SPACING), + verticalArrangement = Arrangement.spacedBy(GRID_SPACING), + ) { + items(items = sortedMembers, key = { it.pubkey }) { member -> + val isSelf = myPubkey != null && member.pubkey == myPubkey + MemberCell( + member = member, + avatarSize = STAGE_AVATAR, + isSpeaking = member.pubkey in speakingNow, + audioLevel = audioLevels[member.pubkey] ?: 0f, + isConnecting = member.pubkey in connectingSpeakers, + showMicBadge = true, + reactions = reactionsByPubkey[member.pubkey].orEmpty(), + accountViewModel = accountViewModel, + onLongPressParticipant = onLongPressParticipant, + isSelf = isSelf, + onTapSelf = if (isSelf) onTapSelf else null, + modifier = Modifier.animateItem(), + ) + } } } + bottomBar?.invoke() } } }