Add fix for call screen bar sizing and position.

This commit is contained in:
Alex Hart
2026-01-08 12:45:31 -04:00
committed by GitHub
parent e014779b32
commit d2c6698824
5 changed files with 38 additions and 23 deletions

View File

@@ -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

View File

@@ -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
)
}

View File

@@ -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()
)

View File

@@ -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,

View File

@@ -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
}
/**