From eafba156ba2e78f1136625af5f446815bbebde01 Mon Sep 17 00:00:00 2001 From: jeffrey-signal Date: Fri, 15 May 2026 11:52:30 -0400 Subject: [PATCH] RegistrationScaffold will automatically add top padding when there is no header. --- .../screens/RegistrationScaffold.kt | 75 ++++++++++++------- .../countrycode/CountryCodePickerScreen.kt | 12 +-- .../screens/permissions/PermissionsScreen.kt | 8 +- .../phonenumber/PhoneNumberEntryScreen.kt | 6 +- 4 files changed, 62 insertions(+), 39 deletions(-) diff --git a/feature/registration/src/main/java/org/signal/registration/screens/RegistrationScaffold.kt b/feature/registration/src/main/java/org/signal/registration/screens/RegistrationScaffold.kt index 7cb51d73da..aea4b01642 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/RegistrationScaffold.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/RegistrationScaffold.kt @@ -33,7 +33,7 @@ import org.signal.core.ui.rememberWindowBreakpoint object RegistrationScaffold { private val smallLayoutParams = Params.OnePane( - topInset = 24.dp, + headerSlotHeight = 24.dp, bottomInset = 24.dp, paneVerticalInset = 24.dp, paneHorizontalInset = 24.dp, @@ -41,7 +41,7 @@ object RegistrationScaffold { ) private val mediumLayoutParams = Params.TwoPane( - topInset = 64.dp, + headerSlotHeight = 64.dp, bottomInset = 24.dp, paneTopInset = 16.dp, paneBottomInset = 24.dp, @@ -51,7 +51,7 @@ object RegistrationScaffold { ) private val largeWidthLayoutParams = Params.TwoPane( - topInset = 64.dp, + headerSlotHeight = 64.dp, bottomInset = 32.dp, paneTopInset = 64.dp, paneBottomInset = 64.dp, @@ -61,7 +61,7 @@ object RegistrationScaffold { ) private val largeHeightLayoutParams = Params.OnePane( - topInset = 64.dp, + headerSlotHeight = 64.dp, bottomInset = 32.dp, paneVerticalInset = 64.dp, paneHorizontalInset = 128.dp, @@ -69,19 +69,19 @@ object RegistrationScaffold { ) sealed interface Params { - val topInset: Dp + val headerSlotHeight: Dp val bottomInset: Dp val maxButtonWidth: Dp data class OnePane( - override val topInset: Dp, + override val headerSlotHeight: Dp, private val paneVerticalInset: Dp, private val paneHorizontalInset: Dp, override val bottomInset: Dp, override val maxButtonWidth: Dp ) : Params { - val panePadding = PaddingValues( - top = topInset + paneVerticalInset, + fun panePadding(hasHeader: Boolean) = PaddingValues( + top = if (hasHeader) paneVerticalInset else headerSlotHeight + paneVerticalInset, bottom = paneVerticalInset, start = paneHorizontalInset, end = paneHorizontalInset @@ -89,7 +89,7 @@ object RegistrationScaffold { } data class TwoPane( - override val topInset: Dp, + override val headerSlotHeight: Dp, private val paneTopInset: Dp, private val paneBottomInset: Dp, private val paneOuterInset: Dp, @@ -97,15 +97,16 @@ object RegistrationScaffold { override val bottomInset: Dp, override val maxButtonWidth: Dp ) : Params { - val firstPanePadding: PaddingValues = PaddingValues( - top = topInset + paneTopInset, + + fun firstPanePadding(hasHeader: Boolean): PaddingValues = PaddingValues( + top = if (hasHeader) paneTopInset else headerSlotHeight + paneTopInset, bottom = paneBottomInset, start = paneOuterInset, end = paneInnerInset ) - val secondPanePadding: PaddingValues = PaddingValues( - top = topInset + paneTopInset, + fun secondPanePadding(hasHeader: Boolean): PaddingValues = PaddingValues( + top = if (hasHeader) paneTopInset else headerSlotHeight + paneTopInset, bottom = paneBottomInset, start = paneInnerInset, end = paneOuterInset @@ -129,9 +130,9 @@ object RegistrationScaffold { */ @Composable fun RegistrationScaffold( - content: @Composable () -> Unit, modifier: Modifier = Modifier, - header: (@Composable () -> Unit)? = null, + content: @Composable () -> Unit, + topBar: (@Composable () -> Unit)? = null, footer: (@Composable () -> Unit)? = null ) { SubcomposeLayout(modifier = modifier.imePadding()) { constraints -> @@ -140,7 +141,7 @@ fun RegistrationScaffold( } ?: emptyList() val footerHeight = footerPlaceables.maxOfOrNull { it.height } ?: 0 - val headerPlaceables = header?.let { + val headerPlaceables = topBar?.let { subcompose("header", it).map { m -> m.measure(constraints.copy(minWidth = 0, minHeight = 0)) } } ?: emptyList() val headerHeight = headerPlaceables.maxOfOrNull { it.height } ?: 0 @@ -158,6 +159,25 @@ fun RegistrationScaffold( } } +/** + * One-pane variant of [RegistrationScaffold] for windows with limited width. + */ +@Composable +fun OnePaneRegistrationScaffold( + modifier: Modifier = Modifier, + params: RegistrationScaffold.Params.OnePane, + topBar: (@Composable () -> Unit)? = null, + footer: (@Composable () -> Unit)? = null, + content: @Composable (PaddingValues) -> Unit +) { + RegistrationScaffold( + modifier = modifier.fillMaxSize(), + topBar = topBar, + footer = footer, + content = { content(params.panePadding(hasHeader = topBar != null)) } + ) +} + /** * Two-pane variant of [RegistrationScaffold] for medium and large-width breakpoints. */ @@ -165,22 +185,22 @@ fun RegistrationScaffold( fun TwoPaneRegistrationScaffold( modifier: Modifier = Modifier, params: RegistrationScaffold.Params.TwoPane, - header: (@Composable () -> Unit)? = null, + topBar: (@Composable () -> Unit)? = null, footer: (@Composable () -> Unit)? = null, firstPane: @Composable RowScope.(PaddingValues) -> Unit, secondPane: @Composable RowScope.(PaddingValues) -> Unit ) { RegistrationScaffold( modifier = modifier.fillMaxSize(), - header = header, + topBar = topBar, footer = footer, content = { Row( horizontalArrangement = Arrangement.SpaceAround, modifier = Modifier.fillMaxSize() ) { - firstPane(params.firstPanePadding) - secondPane(params.secondPanePadding) + firstPane(params.firstPanePadding(hasHeader = topBar != null)) + secondPane(params.secondPanePadding(hasHeader = topBar != null)) } } ) @@ -213,23 +233,24 @@ private fun PreviewPane( private fun RegistrationScaffoldPreview() = Previews.Preview { when (val params = RegistrationScaffold.rememberLayoutParams()) { is RegistrationScaffold.Params.OnePane -> { - RegistrationScaffold( - header = { + OnePaneRegistrationScaffold( + params = params, + topBar = { Text( modifier = Modifier .fillMaxWidth() .background(Color.Green) .padding(16.dp), - text = "header", + text = "topBar", textAlign = TextAlign.Center, fontSize = 24.sp, color = Color.Black ) }, - content = { + content = { paddingValues -> PreviewPane( label = "content", - paddingValues = params.panePadding, + paddingValues = paddingValues, outerColor = Color.Red, innerColor = Color.Yellow, modifier = Modifier.fillMaxWidth() @@ -254,13 +275,13 @@ private fun RegistrationScaffoldPreview() = Previews.Preview { TwoPaneRegistrationScaffold( modifier = Modifier.fillMaxSize(), params = params, - header = { + topBar = { Text( modifier = Modifier .fillMaxWidth() .background(Color.Green) .padding(16.dp), - text = "header", + text = "topBar", textAlign = TextAlign.Center, fontSize = 24.sp, color = Color.Black diff --git a/feature/registration/src/main/java/org/signal/registration/screens/countrycode/CountryCodePickerScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/countrycode/CountryCodePickerScreen.kt index 0a1f690c3a..3d60681e9d 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/countrycode/CountryCodePickerScreen.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/countrycode/CountryCodePickerScreen.kt @@ -92,7 +92,7 @@ fun CountryCodePickerScreen( private fun CompactLayout(state: CountryCodeState, onEvent: (CountryCodePickerScreenEvents) -> Unit) { RegistrationScaffold( modifier = Modifier.fillMaxSize(), - header = { + topBar = { Row( modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 8.dp), verticalAlignment = Alignment.CenterVertically @@ -121,8 +121,8 @@ private fun CompactLayout(state: CountryCodeState, onEvent: (CountryCodePickerSc private fun MediumLayout(state: CountryCodeState, onEvent: (CountryCodePickerScreenEvents) -> Unit) { RegistrationScaffold( modifier = Modifier.fillMaxSize(), - header = { - Header(onEvent) + topBar = { + TopBar(onEvent) }, content = { Row( @@ -150,8 +150,8 @@ private fun MediumLayout(state: CountryCodeState, onEvent: (CountryCodePickerScr private fun LargeLayout(state: CountryCodeState, onEvent: (CountryCodePickerScreenEvents) -> Unit) { RegistrationScaffold( modifier = Modifier.fillMaxSize(), - header = { - Header(onEvent) + topBar = { + TopBar(onEvent) }, content = { Row( @@ -176,7 +176,7 @@ private fun LargeLayout(state: CountryCodeState, onEvent: (CountryCodePickerScre } @Composable -private fun Header(onEvent: (CountryCodePickerScreenEvents) -> Unit) { +private fun TopBar(onEvent: (CountryCodePickerScreenEvents) -> Unit) { Row( modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp, vertical = 8.dp), verticalAlignment = Alignment.CenterVertically diff --git a/feature/registration/src/main/java/org/signal/registration/screens/permissions/PermissionsScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/permissions/PermissionsScreen.kt index 6efceedffe..e09d315e94 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/permissions/PermissionsScreen.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/permissions/PermissionsScreen.kt @@ -38,6 +38,7 @@ import org.signal.core.ui.compose.AllDevicePreviews import org.signal.core.ui.compose.Buttons import org.signal.core.ui.compose.Previews import org.signal.registration.R +import org.signal.registration.screens.OnePaneRegistrationScaffold import org.signal.registration.screens.RegistrationScaffold import org.signal.registration.screens.TwoPaneRegistrationScaffold import org.signal.registration.screens.util.MockMultiplePermissionsState @@ -92,9 +93,10 @@ private fun OnePaneLayout( ) { val scrollState = rememberScrollState() - RegistrationScaffold( + OnePaneRegistrationScaffold( modifier = modifier.fillMaxSize(), - content = { + params = params, + content = { paddingValues -> Box( modifier = Modifier .fillMaxWidth() @@ -104,7 +106,7 @@ private fun OnePaneLayout( modifier = Modifier .fillMaxHeight() .verticalScroll(scrollState) - .padding(params.panePadding) + .padding(paddingValues) ) { Text( text = stringResource(id = R.string.GrantPermissionsFragment__allow_permissions), diff --git a/feature/registration/src/main/java/org/signal/registration/screens/phonenumber/PhoneNumberEntryScreen.kt b/feature/registration/src/main/java/org/signal/registration/screens/phonenumber/PhoneNumberEntryScreen.kt index ddb837934c..37d29e2509 100644 --- a/feature/registration/src/main/java/org/signal/registration/screens/phonenumber/PhoneNumberEntryScreen.kt +++ b/feature/registration/src/main/java/org/signal/registration/screens/phonenumber/PhoneNumberEntryScreen.kt @@ -183,7 +183,7 @@ private fun CompactLayout(state: PhoneNumberEntryState, onEvent: (PhoneNumberEnt RegistrationScaffold( modifier = Modifier, - header = { + topBar = { TopbarMenu() }, content = { @@ -236,7 +236,7 @@ private fun MediumLayout(state: PhoneNumberEntryState, onEvent: (PhoneNumberEntr RegistrationScaffold( modifier = Modifier, - header = { + topBar = { TopbarMenu() }, content = { @@ -299,7 +299,7 @@ private fun LargeLayout(state: PhoneNumberEntryState, onEvent: (PhoneNumberEntry RegistrationScaffold( modifier = Modifier, - header = { + topBar = { TopbarMenu() }, content = {