diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/BottomControlsWithOptionalBar.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/BottomControlsWithOptionalBar.kt index 8f865981fb..9626ba3832 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/BottomControlsWithOptionalBar.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/BottomControlsWithOptionalBar.kt @@ -5,8 +5,6 @@ package org.thoughtcrime.securesms.components.webrtc.v2 -import androidx.compose.material3.BottomSheetDefaults -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.layout.Layout @@ -36,7 +34,6 @@ internal enum class BottomControlsLayoutId { * Usage: Apply `Modifier.layoutId(BottomControlsLayoutId.CONTROLS)` to the controls content * and `Modifier.layoutId(BottomControlsLayoutId.BAR)` to the bar content. */ -@OptIn(ExperimentalMaterial3Api::class) @Composable internal fun BottomControlsWithOptionalBar( bottomSheetPadding: Dp, @@ -44,7 +41,7 @@ internal fun BottomControlsWithOptionalBar( controlsRow: @Composable () -> Unit, barSlot: @Composable () -> Unit ) { - val sheetMaxWidthPx = with(LocalDensity.current) { BottomSheetDefaults.SheetMaxWidth.roundToPx() } + val sheetMaxWidthPx = with(LocalDensity.current) { CallScreenMetrics.SheetMaxWidth.roundToPx() } val spacingPx = with(LocalDensity.current) { 16.dp.roundToPx() } val elementBottomPaddingPx = with(LocalDensity.current) { 16.dp.roundToPx() } val bottomSheetPaddingPx = with(LocalDensity.current) { bottomSheetPadding.roundToPx() } @@ -79,7 +76,7 @@ internal fun BottomControlsWithOptionalBar( val controlsPlaceable = controlsMeasurable?.measure(constraints.copy(minWidth = 0, minHeight = 0)) val controlsHeight = controlsPlaceable?.height ?: 0 - if (controlsCanBeAtScreenEdge) { + if (controlsCanBeAtScreenEdge && barHeight > 0) { // Controls at screen edge with 16dp bottom padding, bar above sheet with 16dp bottom padding val controlsTotalHeight = controlsHeight + elementBottomPaddingPx val barTotalHeight = barHeight + elementBottomPaddingPx @@ -92,7 +89,14 @@ internal fun BottomControlsWithOptionalBar( controlsPlaceable?.placeRelative(0, controlsY) barPlaceable?.placeRelative(barX, barY) } - } else if (barPlaceable != null) { + } else if (controlsCanBeAtScreenEdge) { + // Controls at screen edge with 16dp bottom padding, no bar + val totalHeight = max(controlsHeight + elementBottomPaddingPx, bottomSheetPaddingPx) + + layout(constraints.maxWidth, totalHeight) { + controlsPlaceable?.placeRelative(0, totalHeight - controlsHeight - elementBottomPaddingPx) + } + } else if (barHeight > 0) { // Not enough gutter space, controls stacked above bar, both above sheet with 16dp bottom padding val contentHeight = controlsHeight + (if (controlsHeight > 0) spacingPx else 0) + barHeight val totalHeight = contentHeight + elementBottomPaddingPx + bottomSheetPaddingPx @@ -102,7 +106,7 @@ internal fun BottomControlsWithOptionalBar( layout(constraints.maxWidth, totalHeight) { controlsPlaceable?.placeRelative(0, controlsY) - barPlaceable.placeRelative(barX, barY) + barPlaceable?.placeRelative(barX, barY) } } else { // No bar, not enough gutter space - controls above sheet with 16dp bottom padding diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallElementsLayout.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallElementsLayout.kt index 3642466c88..c27951dcaf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallElementsLayout.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallElementsLayout.kt @@ -52,7 +52,7 @@ fun CallElementsLayout( @Composable fun Bars() { - Column { + Column(modifier = Modifier.fillMaxWidth()) { raiseHandSlot() callLinkBarSlot() } @@ -74,6 +74,7 @@ fun CallElementsLayout( isFocused = isFocused, isPortrait = isPortrait, bottomInsetPx = bottomInsetPx, + bottomSheetWidthPx = bottomSheetWidthPx, barsSlot = { Bars() }, callGridSlot = callGridSlot, reactionsSlot = reactionsSlot, @@ -95,6 +96,7 @@ private fun BlurrableContentLayer( isFocused: Boolean, isPortrait: Boolean, bottomInsetPx: Int, + bottomSheetWidthPx: Int, barsSlot: @Composable () -> Unit, callGridSlot: @Composable () -> Unit, reactionsSlot: @Composable () -> Unit, @@ -122,7 +124,11 @@ private fun BlurrableContentLayer( nonOverflowConstraints } - val barsPlaceables = measurables[0].map { it.measure(barConstraints) } + // Cap bars width to sheet max width (bars can be narrower if content doesn't fill) + val barsMaxWidth = minOf(barConstraints.maxWidth, bottomSheetWidthPx) + val barsConstrainedToSheet = barConstraints.copy(maxWidth = barsMaxWidth) + + val barsPlaceables = measurables[0].map { it.measure(barsConstrainedToSheet) } val barsHeightOffset = barsPlaceables.sumOf { it.height } val reactionsConstraints = barConstraints.offset(vertical = -barsHeightOffset) @@ -142,7 +148,8 @@ private fun BlurrableContentLayer( } barsPlaceables.forEach { - it.place(0, barConstraints.maxHeight - it.height) + val barsX = (looseConstraints.maxWidth - it.width) / 2 + it.place(barsX, barConstraints.maxHeight - it.height) } reactionsPlaceables.forEach { @@ -258,7 +265,7 @@ private fun CallElementsLayoutPreview() { ) }, bottomInset = 120.dp, - bottomSheetWidth = 640.dp, + bottomSheetWidth = CallScreenMetrics.SheetMaxWidth, localRenderState = localRenderState ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreen.kt index 491009cfeb..3e14e5561d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreen.kt @@ -24,7 +24,6 @@ import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.layout.width -import androidx.compose.material3.BottomSheetDefaults import androidx.compose.material3.BottomSheetScaffold import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.LocalContentColor @@ -181,7 +180,7 @@ fun CallScreen( sheetPeekHeight = peekHeight.dp, sheetContainerColor = SignalTheme.colors.colorSurface1, containerColor = Color.Black, - sheetMaxWidth = 540.dp, + sheetMaxWidth = CallScreenMetrics.SheetMaxWidth, sheetContent = { BottomSheets.Handle(modifier = Modifier.align(Alignment.CenterHorizontally)) @@ -339,11 +338,14 @@ fun CallScreen( ) }, raiseHandSlot = { - raiseHandSnackbar( - Modifier - .fillMaxWidth() - .padding(bottom = 16.dp) - ) + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.CenterEnd + ) { + raiseHandSnackbar( + Modifier.padding(bottom = 16.dp) + ) + } }, callLinkBarSlot = { PendingParticipantsInternal(modifier = Modifier.padding(horizontal = 16.dp).padding(bottom = 16.dp)) @@ -375,7 +377,7 @@ fun CallScreen( } }, bottomInset = padding, - bottomSheetWidth = BottomSheetDefaults.SheetMaxWidth, + bottomSheetWidth = CallScreenMetrics.SheetMaxWidth, localRenderState = localRenderState, modifier = Modifier.fillMaxSize() ) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreenJoiningOverlay.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreenJoiningOverlay.kt index b058496fcf..2b3c409053 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreenJoiningOverlay.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreenJoiningOverlay.kt @@ -15,9 +15,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.widthIn -import androidx.compose.material3.BottomSheetDefaults import androidx.compose.material3.CircularProgressIndicator -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -112,7 +110,6 @@ fun CallScreenJoiningOverlay( } } -@OptIn(ExperimentalMaterial3Api::class) @Composable private fun WaitingToBeLetInBar( modifier: Modifier = Modifier @@ -121,7 +118,7 @@ private fun WaitingToBeLetInBar( horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically, modifier = modifier - .widthIn(max = BottomSheetDefaults.SheetMaxWidth) + .widthIn(max = CallScreenMetrics.SheetMaxWidth) .fillMaxWidth() .background( color = SignalTheme.colors.colorSurface1, diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreenMetrics.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreenMetrics.kt index 8f25e96fe5..1b045c4f43 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreenMetrics.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/v2/CallScreenMetrics.kt @@ -30,6 +30,11 @@ class CallScreenMetrics @RememberInComposition constructor( * Shape of self renderer when in large group calls. */ val OverflowParticipantRendererShape = RoundedCornerShape(OverflowParticipantRendererCornerSize) + + /** + * Maximum width of the bottom sheet and related UI bars on the call screen. + */ + val SheetMaxWidth = 540.dp } /**