From d1c8a3283b870a1d9edcad2b18b975e1c51e2cd4 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Fri, 10 Jan 2025 13:28:47 +0100 Subject: [PATCH 01/14] Make ModalStatusBarBottomSheetLayout private and avoid its usage if Android API below 15 --- .../ModalStatusBarBottomSheetLayout.kt | 141 ------------------ .../component/WCModalBottomSheetLayout.kt | 127 +++++++++++++--- 2 files changed, 110 insertions(+), 158 deletions(-) delete mode 100644 WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/ModalStatusBarBottomSheetLayout.kt diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/ModalStatusBarBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/ModalStatusBarBottomSheetLayout.kt deleted file mode 100644 index 08877698aaab..000000000000 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/ModalStatusBarBottomSheetLayout.kt +++ /dev/null @@ -1,141 +0,0 @@ -package com.woocommerce.android.ui.compose.component - -import android.R.attr -import android.util.TypedValue -import androidx.compose.foundation.background -import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.ExperimentalLayoutApi -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.imeNestedScroll -import androidx.compose.foundation.layout.imePadding -import androidx.compose.foundation.layout.navigationBarsPadding -import androidx.compose.foundation.layout.statusBarsPadding -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.MaterialTheme -import androidx.compose.material.ModalBottomSheetDefaults -import androidx.compose.material.ModalBottomSheetLayout -import androidx.compose.material.ModalBottomSheetState -import androidx.compose.material.ModalBottomSheetValue.Hidden -import androidx.compose.material.contentColorFor -import androidx.compose.material.rememberModalBottomSheetState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.graphics.toArgb -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.colorResource -import androidx.compose.ui.unit.Dp -import androidx.core.view.WindowCompat -import com.woocommerce.android.R -import com.woocommerce.android.extensions.findActivity - -/* - * This is a custom implementation of the ModalBottomSheetLayout that fixes the scrim color of the status bar - * and the show animation. - * - * Source: https://stackoverflow.com/a/76998328 - * - */ -@OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) -@Composable -fun ModalStatusBarBottomSheetLayout( - sheetContent: @Composable ColumnScope.() -> Unit, - modifier: Modifier = Modifier, - sheetState: ModalBottomSheetState = - rememberModalBottomSheetState(Hidden), - sheetShape: Shape = MaterialTheme.shapes.large, - sheetElevation: Dp = ModalBottomSheetDefaults.Elevation, - sheetBackgroundColor: Color = colorResource(id = R.color.bottom_sheet_background), - sheetContentColor: Color = contentColorFor(sheetBackgroundColor), - content: @Composable () -> Unit -): Unit = ModalBottomSheetLayout( - sheetContent = { - Box( - modifier = Modifier - .fillMaxWidth() - ) { - sheetContent.invoke(this@ModalBottomSheetLayout) - } - }, - modifier = modifier - .imePadding() - .navigationBarsPadding() - .imeNestedScroll(), - sheetState = sheetState, - sheetShape = sheetShape, - sheetElevation = sheetElevation, - sheetBackgroundColor = sheetBackgroundColor, - sheetContentColor = sheetContentColor, - scrimColor = scrimColor(), -) { - val context = LocalContext.current - var statusBarColor by remember { mutableStateOf(Color.Transparent) } - val backgroundColor = remember { - val typedValue = TypedValue() - if (context.findActivity()?.theme?.resolveAttribute(attr.windowBackground, typedValue, true) == true) { - Color(typedValue.data) - } else { - sheetBackgroundColor - } - } - - Box( - modifier = Modifier - .fillMaxWidth() - .background(statusBarColor) - .statusBarsPadding() - ) { - Box( - modifier = Modifier - .background(backgroundColor) - .fillMaxSize() - .navigationBarsPadding() - ) { - content() - } - } - - val window = remember { context.findActivity()?.window } - if (window == null) return@ModalBottomSheetLayout - - val originalNavigationBarColor = remember { window.navigationBarColor } - - LaunchedEffect(sheetState.currentValue) { - if (sheetState.currentValue != Hidden) { - window.navigationBarColor = sheetBackgroundColor.toArgb() - } else { - window.navigationBarColor = originalNavigationBarColor - } - } - - DisposableEffect(Unit) { - val originalStatusBarColor = window.statusBarColor - statusBarColor = Color(originalStatusBarColor) - - window.statusBarColor = android.graphics.Color.TRANSPARENT - WindowCompat.setDecorFitsSystemWindows(window, false) - - onDispose { - window.statusBarColor = originalStatusBarColor - window.navigationBarColor = originalNavigationBarColor - WindowCompat.setDecorFitsSystemWindows(window, true) - } - } -} - -@Composable -private fun scrimColor() = if (isSystemInDarkTheme()) { - colorResource(id = R.color.color_scrim_background) -} else { - ModalBottomSheetDefaults.scrimColor -} diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index 1c35115ae3c0..6137360344cb 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -1,16 +1,13 @@ package com.woocommerce.android.ui.compose.component -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.ModalBottomSheetDefaults import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material.ModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource import com.woocommerce.android.R @@ -29,19 +26,115 @@ fun WCModalBottomSheetLayout( ), content: @Composable () -> Unit ) { - ModalBottomSheetLayout( - sheetContent = sheetContent, - sheetShape = sheetShape, - sheetState = sheetState, - modifier = modifier, - scrimColor = - // Overriding scrim color for dark theme because of the following bug affecting ModalBottomSheetLayout: - // https://issuetracker.google.com/issues/183697056 - if (isSystemInDarkTheme()) { - colorResource(id = R.color.color_scrim_background) + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM) { + ModalBottomSheetLayout( + sheetContent = sheetContent, + sheetShape = sheetShape, + sheetState = sheetState, + modifier = modifier, + content = content, + ) + } else { + ModalStatusBarBottomSheetLayout( + sheetContent = sheetContent, + sheetShape = sheetShape, + sheetState = sheetState, + modifier = modifier, + content = content, + ) + } +} + +/* + * This is a custom implementation of the ModalBottomSheetLayout that fixes the scrim color of the status bar + * and the show animation. + * + * Source: https://stackoverflow.com/a/76998328 + * + */ +@OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) +@Composable +private fun ModalStatusBarBottomSheetLayout( + sheetContent: @Composable ColumnScope.() -> Unit, + modifier: Modifier = Modifier, + sheetState: ModalBottomSheetState = + rememberModalBottomSheetState(Hidden), + sheetShape: Shape = MaterialTheme.shapes.large, + sheetElevation: Dp = ModalBottomSheetDefaults.Elevation, + sheetBackgroundColor: Color = colorResource(id = R.color.bottom_sheet_background), + sheetContentColor: Color = contentColorFor(sheetBackgroundColor), + content: @Composable () -> Unit +): Unit = ModalBottomSheetLayout( + sheetContent = { + Box( + modifier = Modifier + .fillMaxWidth() + ) { + sheetContent.invoke(this@ModalBottomSheetLayout) + } + }, + modifier = modifier + .imePadding() + .navigationBarsPadding() + .imeNestedScroll(), + sheetState = sheetState, + sheetShape = sheetShape, + sheetElevation = sheetElevation, + sheetBackgroundColor = sheetBackgroundColor, + sheetContentColor = sheetContentColor, +) { + val context = LocalContext.current + var statusBarColor by remember { mutableStateOf(Color.Transparent) } + val backgroundColor = remember { + val typedValue = TypedValue() + if (context.findActivity()?.theme?.resolveAttribute(attr.windowBackground, typedValue, true) == true) { + Color(typedValue.data) } else { - ModalBottomSheetDefaults.scrimColor - }, - content = content, - ) + sheetBackgroundColor + } + } + + Box( + modifier = Modifier + .fillMaxWidth() + .background(statusBarColor) + .statusBarsPadding() + ) { + Box( + modifier = Modifier + .background(backgroundColor) + .fillMaxSize() + .navigationBarsPadding() + ) { + content() + } + } + + val window = remember { context.findActivity()?.window } + if (window == null) return@ModalBottomSheetLayout + + val originalNavigationBarColor = remember { window.navigationBarColor } + + LaunchedEffect(sheetState.currentValue) { + if (sheetState.currentValue != Hidden) { + window.navigationBarColor = sheetBackgroundColor.toArgb() + } else { + window.navigationBarColor = originalNavigationBarColor + } + } + + DisposableEffect(Unit) { + val originalStatusBarColor = window.statusBarColor + statusBarColor = Color(originalStatusBarColor) + + window.statusBarColor = android.graphics.Color.TRANSPARENT + WindowCompat.setDecorFitsSystemWindows(window, false) + + onDispose { + window.statusBarColor = originalStatusBarColor + window.navigationBarColor = originalNavigationBarColor + WindowCompat.setDecorFitsSystemWindows(window, true) + } + } } + From 835fb94941d3e327067e7de4be26a5cb4adfa7f6 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Fri, 10 Jan 2025 13:29:06 +0100 Subject: [PATCH 02/14] Migrate any direct usages of ModalStatusBarBottomSheetLayout --- .../BlazeCampaignCreationAdDestinationParametersBottomSheet.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt index dcbf68d7ba57..e377dae4c3e7 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt @@ -56,7 +56,7 @@ fun AdDestinationParametersBottomSheet( } } - ModalStatusBarBottomSheetLayout( + WCModalBottomSheetLayout( sheetState = modalSheetState, sheetShape = RoundedCornerShape(topStart = roundedCornerRadius, topEnd = roundedCornerRadius), sheetContent = { From f013afdef00d40f3ad88b1692ae390c7520213c3 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Fri, 10 Jan 2025 13:29:49 +0100 Subject: [PATCH 03/14] Place bottomsheet wrapping the whole screen --- .../budget/BlazeCampaignBudgetScreen.kt | 66 +++++++++---------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/budget/BlazeCampaignBudgetScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/budget/BlazeCampaignBudgetScreen.kt index b97bc64a5059..5408f788f4b6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/budget/BlazeCampaignBudgetScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/budget/BlazeCampaignBudgetScreen.kt @@ -115,42 +115,42 @@ private fun CampaignBudgetScreen( skipHalfExpanded = true, ) - Scaffold( - topBar = { - Toolbar( - onNavigationButtonClick = onBackPressed, - navigationIcon = Icons.AutoMirrored.Filled.ArrowBack - ) - }, - modifier = Modifier.background(MaterialTheme.colors.surface) - ) { paddingValues -> - WCModalBottomSheetLayout( - sheetState = modalSheetState, - sheetContent = { - Column { - Spacer(modifier = Modifier.height(dimensionResource(id = dimen.minor_100))) - BottomSheetHandle(Modifier.align(Alignment.CenterHorizontally)) - when { - state.showImpressionsBottomSheet -> ImpressionsInfoBottomSheet( - onDoneTapped = { coroutineScope.launch { modalSheetState.hide() } } - ) + WCModalBottomSheetLayout( + sheetState = modalSheetState, + sheetContent = { + Column { + Spacer(modifier = Modifier.height(dimensionResource(id = dimen.minor_100))) + BottomSheetHandle(Modifier.align(Alignment.CenterHorizontally)) + when { + state.showImpressionsBottomSheet -> ImpressionsInfoBottomSheet( + onDoneTapped = { coroutineScope.launch { modalSheetState.hide() } } + ) - state.showCampaignDurationBottomSheet -> EditDurationBottomSheet( - budgetUiState = state, - onStartDateChanged = { onStartDateChanged(it) }, - onApplyTapped = { duration, isEndlessCampaign, startDate -> - onApplyDurationTapped(duration, isEndlessCampaign, startDate) - coroutineScope.launch { modalSheetState.hide() } - }, - onCancelTapped = { coroutineScope.launch { modalSheetState.hide() } }, - onDurationSliderUpdated = { duration, startDate -> - onDurationSliderUpdated(duration, startDate) - } - ) - } + state.showCampaignDurationBottomSheet -> EditDurationBottomSheet( + budgetUiState = state, + onStartDateChanged = { onStartDateChanged(it) }, + onApplyTapped = { duration, isEndlessCampaign, startDate -> + onApplyDurationTapped(duration, isEndlessCampaign, startDate) + coroutineScope.launch { modalSheetState.hide() } + }, + onCancelTapped = { coroutineScope.launch { modalSheetState.hide() } }, + onDurationSliderUpdated = { duration, startDate -> + onDurationSliderUpdated(duration, startDate) + } + ) } } - ) { + } + ) { + Scaffold( + topBar = { + Toolbar( + onNavigationButtonClick = onBackPressed, + navigationIcon = Icons.AutoMirrored.Filled.ArrowBack + ) + }, + modifier = Modifier.background(MaterialTheme.colors.surface) + ) { paddingValues -> Column( modifier = Modifier .padding(paddingValues) From 362f15811d51b5e48c12e528086dbdd69a3c83b8 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Fri, 10 Jan 2025 15:12:18 +0100 Subject: [PATCH 04/14] Cleanup ModalStatusBarBottomSheetLayout and suppress deprecation --- .../component/WCModalBottomSheetLayout.kt | 40 +++++++++++++++++-- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index 6137360344cb..15a177fae2e8 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -1,15 +1,42 @@ package com.woocommerce.android.ui.compose.component +import android.util.TypedValue +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.ExperimentalLayoutApi +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imeNestedScroll +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.navigationBarsPadding +import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.MaterialTheme +import androidx.compose.material.ModalBottomSheetDefaults import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material.ModalBottomSheetState +import androidx.compose.material.ModalBottomSheetValue +import androidx.compose.material.contentColorFor import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.colorResource import androidx.compose.ui.res.dimensionResource +import androidx.compose.ui.unit.Dp +import androidx.core.view.WindowCompat import com.woocommerce.android.R +import com.woocommerce.android.extensions.findActivity /** * A wrapper around [ModalBottomSheetLayout] that provides default values for the sheet shape and scrim color. @@ -52,13 +79,13 @@ fun WCModalBottomSheetLayout( * Source: https://stackoverflow.com/a/76998328 * */ +@Suppress("DEPRECATION") @OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) @Composable private fun ModalStatusBarBottomSheetLayout( sheetContent: @Composable ColumnScope.() -> Unit, modifier: Modifier = Modifier, - sheetState: ModalBottomSheetState = - rememberModalBottomSheetState(Hidden), + sheetState: ModalBottomSheetState, sheetShape: Shape = MaterialTheme.shapes.large, sheetElevation: Dp = ModalBottomSheetDefaults.Elevation, sheetBackgroundColor: Color = colorResource(id = R.color.bottom_sheet_background), @@ -87,7 +114,12 @@ private fun ModalStatusBarBottomSheetLayout( var statusBarColor by remember { mutableStateOf(Color.Transparent) } val backgroundColor = remember { val typedValue = TypedValue() - if (context.findActivity()?.theme?.resolveAttribute(attr.windowBackground, typedValue, true) == true) { + if (context.findActivity()?.theme?.resolveAttribute( + android.R.attr.windowBackground, + typedValue, + true + ) == true + ) { Color(typedValue.data) } else { sheetBackgroundColor @@ -116,7 +148,7 @@ private fun ModalStatusBarBottomSheetLayout( val originalNavigationBarColor = remember { window.navigationBarColor } LaunchedEffect(sheetState.currentValue) { - if (sheetState.currentValue != Hidden) { + if (sheetState.currentValue != ModalBottomSheetValue.Hidden) { window.navigationBarColor = sheetBackgroundColor.toArgb() } else { window.navigationBarColor = originalNavigationBarColor From 3515ec6207f2f34a9bd7fdebcad0d9b090fd8a17 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Fri, 10 Jan 2025 15:20:28 +0100 Subject: [PATCH 05/14] Add missing import --- .../BlazeCampaignCreationAdDestinationParametersBottomSheet.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt index e377dae4c3e7..3fbae44f4987 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt @@ -27,8 +27,8 @@ import com.woocommerce.android.R import com.woocommerce.android.ui.blaze.creation.destination.BlazeCampaignCreationAdDestinationParametersViewModel.ViewState import com.woocommerce.android.ui.blaze.creation.destination.BlazeCampaignCreationAdDestinationParametersViewModel.ViewState.ParameterBottomSheetState.Editing import com.woocommerce.android.ui.compose.component.BottomSheetHandle -import com.woocommerce.android.ui.compose.component.ModalStatusBarBottomSheetLayout import com.woocommerce.android.ui.compose.component.WCColoredButton +import com.woocommerce.android.ui.compose.component.WCModalBottomSheetLayout import com.woocommerce.android.ui.compose.component.WCOutlinedTextField import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground From 01fb0a2dfd6f87cea5cc9a446d8483c2d807ce87 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Fri, 10 Jan 2025 15:21:51 +0100 Subject: [PATCH 06/14] Add clearer name --- .../ui/compose/component/WCModalBottomSheetLayout.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index 15a177fae2e8..903e7b7b2601 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -22,10 +22,10 @@ import androidx.compose.material.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.getValue -import androidx.compose.runtime.setValue +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape @@ -62,7 +62,7 @@ fun WCModalBottomSheetLayout( content = content, ) } else { - ModalStatusBarBottomSheetLayout( + ModalBottomSheetLayoutWithStatusBarWorkAround( sheetContent = sheetContent, sheetShape = sheetShape, sheetState = sheetState, @@ -82,7 +82,7 @@ fun WCModalBottomSheetLayout( @Suppress("DEPRECATION") @OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) @Composable -private fun ModalStatusBarBottomSheetLayout( +private fun ModalBottomSheetLayoutWithStatusBarWorkAround( sheetContent: @Composable ColumnScope.() -> Unit, modifier: Modifier = Modifier, sheetState: ModalBottomSheetState, From 961784e035e335ea1465eec82da565807b0ca6d4 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Fri, 10 Jan 2025 15:24:46 +0100 Subject: [PATCH 07/14] Replace direct usages of ModalBottomSheetLayout --- .../android/ui/blaze/campaigs/BlazeCampaignListScreen.kt | 4 ++-- .../ui/orders/wooshippinglabels/address/AddressSection.kt | 4 ++-- .../ui/products/inventory/ScanToUpdateInventoryScreen.kt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/campaigs/BlazeCampaignListScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/campaigs/BlazeCampaignListScreen.kt index 62ebf6c01566..6d67ff771669 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/campaigs/BlazeCampaignListScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/campaigs/BlazeCampaignListScreen.kt @@ -23,7 +23,6 @@ import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.FloatingActionButton import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme -import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.Text import androidx.compose.material.icons.Icons.Filled @@ -51,6 +50,7 @@ import com.woocommerce.android.ui.blaze.campaigs.BlazeCampaignListViewModel.Clic import com.woocommerce.android.ui.compose.component.BottomSheetHandle import com.woocommerce.android.ui.compose.component.InfiniteListHandler import com.woocommerce.android.ui.compose.component.WCColoredButton +import com.woocommerce.android.ui.compose.component.WCModalBottomSheetLayout @Composable fun BlazeCampaignListScreen(viewModel: BlazeCampaignListViewModel) { @@ -91,7 +91,7 @@ private fun BlazeCampaignListScreen( } } - ModalBottomSheetLayout( + WCModalBottomSheetLayout( sheetState = bottomSheetState, sheetContent = { CampaignCelebrationSheet(onCampaignCelebrationDismissed) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/address/AddressSection.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/address/AddressSection.kt index 5bbd956ecced..fd01a2751aa1 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/address/AddressSection.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/orders/wooshippinglabels/address/AddressSection.kt @@ -15,7 +15,6 @@ import androidx.compose.material.Divider import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme -import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material.ModalBottomSheetState import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.Text @@ -40,6 +39,7 @@ import com.woocommerce.android.model.Address import com.woocommerce.android.model.AmbiguousLocation import com.woocommerce.android.model.Location import com.woocommerce.android.ui.compose.component.BottomSheetHandle +import com.woocommerce.android.ui.compose.component.WCModalBottomSheetLayout import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground import com.woocommerce.android.ui.orders.wooshippinglabels.RoundedCornerBoxWithBorder import com.woocommerce.android.ui.orders.wooshippinglabels.ShipmentDetailsSectionTitle @@ -347,7 +347,7 @@ fun AddressSelection( modifier: Modifier = Modifier, content: @Composable () -> Unit = {} ) { - ModalBottomSheetLayout( + WCModalBottomSheetLayout( modifier = modifier, sheetState = modalBottomSheetState, sheetContent = { diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/inventory/ScanToUpdateInventoryScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/inventory/ScanToUpdateInventoryScreen.kt index 10e8d8f4f9b5..1b8e4747dde2 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/inventory/ScanToUpdateInventoryScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/products/inventory/ScanToUpdateInventoryScreen.kt @@ -3,7 +3,6 @@ package com.woocommerce.android.ui.products.inventory import androidx.camera.core.ImageProxy import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.ModalBottomSheetLayout import androidx.compose.material.ModalBottomSheetValue import androidx.compose.material.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -16,6 +15,7 @@ import com.woocommerce.android.R import com.woocommerce.android.ui.barcodescanner.BarcodeScannerScreen import com.woocommerce.android.ui.barcodescanner.BarcodeScanningViewModel import com.woocommerce.android.ui.compose.component.ProgressIndicator +import com.woocommerce.android.ui.compose.component.WCModalBottomSheetLayout import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground import kotlinx.coroutines.flow.filter @@ -38,7 +38,7 @@ fun ScanToUpdateInventoryScreen( initialValue = ModalBottomSheetValue.Hidden, skipHalfExpanded = true ) - ModalBottomSheetLayout( + WCModalBottomSheetLayout( sheetState = sheetState, content = { BarcodeScannerScreen( From a5225cabd8e02140ebcb9cd6e94539c896504a43 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Fri, 10 Jan 2025 15:25:43 +0100 Subject: [PATCH 08/14] Fix detekt indentation issue --- .../android/ui/compose/component/WCModalBottomSheetLayout.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index 903e7b7b2601..0a669d102104 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -169,4 +169,3 @@ private fun ModalBottomSheetLayoutWithStatusBarWorkAround( } } } - From 0d85128fa6b69e56b93ff8eb879d11f895530e19 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Fri, 10 Jan 2025 15:36:50 +0100 Subject: [PATCH 09/14] Add back scrim color override to show consistent overlay in dark mode --- .../component/WCModalBottomSheetLayout.kt | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index 0a669d102104..eeafab435b2d 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -2,6 +2,7 @@ package com.woocommerce.android.ui.compose.component import android.util.TypedValue import androidx.compose.foundation.background +import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ExperimentalLayoutApi @@ -58,8 +59,9 @@ fun WCModalBottomSheetLayout( sheetContent = sheetContent, sheetShape = sheetShape, sheetState = sheetState, + scrimColor = scrimColor(), modifier = modifier, - content = content, + content = content ) } else { ModalBottomSheetLayoutWithStatusBarWorkAround( @@ -100,15 +102,16 @@ private fun ModalBottomSheetLayoutWithStatusBarWorkAround( sheetContent.invoke(this@ModalBottomSheetLayout) } }, - modifier = modifier - .imePadding() - .navigationBarsPadding() - .imeNestedScroll(), sheetState = sheetState, sheetShape = sheetShape, sheetElevation = sheetElevation, sheetBackgroundColor = sheetBackgroundColor, sheetContentColor = sheetContentColor, + scrimColor = scrimColor(), + modifier = modifier + .imePadding() + .navigationBarsPadding() + .imeNestedScroll(), ) { val context = LocalContext.current var statusBarColor by remember { mutableStateOf(Color.Transparent) } @@ -169,3 +172,12 @@ private fun ModalBottomSheetLayoutWithStatusBarWorkAround( } } } + +// Overriding scrim color for dark theme because of the following bug affecting ModalBottomSheetLayout: +// https://issuetracker.google.com/issues/183697056 +@Composable +private fun scrimColor() = if (isSystemInDarkTheme()) { + colorResource(id = R.color.color_scrim_background) +} else { + ModalBottomSheetDefaults.scrimColor +} From 4b3057562f3192aa7ab7046ab853b470de136f5f Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 18:34:22 +0100 Subject: [PATCH 10/14] Use system utils to check Android version --- .../compose/component/WCModalBottomSheetLayout.kt | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index eeafab435b2d..32fbabd164a6 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.unit.Dp import androidx.core.view.WindowCompat import com.woocommerce.android.R import com.woocommerce.android.extensions.findActivity +import com.woocommerce.android.util.SystemVersionUtils /** * A wrapper around [ModalBottomSheetLayout] that provides default values for the sheet shape and scrim color. @@ -54,22 +55,22 @@ fun WCModalBottomSheetLayout( ), content: @Composable () -> Unit ) { - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.VANILLA_ICE_CREAM) { - ModalBottomSheetLayout( + if (SystemVersionUtils.isAtMostU()) { + ModalBottomSheetLayoutWithStatusBarWorkAround( sheetContent = sheetContent, sheetShape = sheetShape, sheetState = sheetState, - scrimColor = scrimColor(), modifier = modifier, - content = content + content = content, ) } else { - ModalBottomSheetLayoutWithStatusBarWorkAround( + ModalBottomSheetLayout( sheetContent = sheetContent, sheetShape = sheetShape, sheetState = sheetState, + scrimColor = scrimColor(), modifier = modifier, - content = content, + content = content ) } } From d58be6d69d1090b7c025b870c1b87839a24e3c38 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 18:34:50 +0100 Subject: [PATCH 11/14] Fix typo --- .../android/ui/compose/component/WCModalBottomSheetLayout.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index 32fbabd164a6..1670e6ebfa12 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -56,7 +56,7 @@ fun WCModalBottomSheetLayout( content: @Composable () -> Unit ) { if (SystemVersionUtils.isAtMostU()) { - ModalBottomSheetLayoutWithStatusBarWorkAround( + ModalBottomSheetLayoutWithStatusBarWorkaround( sheetContent = sheetContent, sheetShape = sheetShape, sheetState = sheetState, @@ -85,7 +85,7 @@ fun WCModalBottomSheetLayout( @Suppress("DEPRECATION") @OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) @Composable -private fun ModalBottomSheetLayoutWithStatusBarWorkAround( +private fun ModalBottomSheetLayoutWithStatusBarWorkaround( sheetContent: @Composable ColumnScope.() -> Unit, modifier: Modifier = Modifier, sheetState: ModalBottomSheetState, From a3f0637096fdc0a57ddd2e91e4c6a6852d5fb5e1 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 18:43:27 +0100 Subject: [PATCH 12/14] Remove ime nested scroll from bottomsheet modifier --- .../android/ui/compose/component/WCModalBottomSheetLayout.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index 1670e6ebfa12..da58710290d0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -8,7 +8,6 @@ import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.imeNestedScroll import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.statusBarsPadding @@ -112,7 +111,6 @@ private fun ModalBottomSheetLayoutWithStatusBarWorkaround( modifier = modifier .imePadding() .navigationBarsPadding() - .imeNestedScroll(), ) { val context = LocalContext.current var statusBarColor by remember { mutableStateOf(Color.Transparent) } From 76208b377673f1d1f65d33a104c9d41bd997f3c9 Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 18:45:38 +0100 Subject: [PATCH 13/14] Fix bottomsheet for Blaze intro screen to show content edge to edge --- .../intro/BlazeCampaignCreationIntroScreen.kt | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/intro/BlazeCampaignCreationIntroScreen.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/intro/BlazeCampaignCreationIntroScreen.kt index 9193744b89b0..5577ed518757 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/intro/BlazeCampaignCreationIntroScreen.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/intro/BlazeCampaignCreationIntroScreen.kt @@ -56,6 +56,7 @@ import com.woocommerce.android.ui.compose.component.WCColoredButton import com.woocommerce.android.ui.compose.component.WCModalBottomSheetLayout import com.woocommerce.android.ui.compose.component.WCTextButton import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground +import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.launch @Composable @@ -78,41 +79,40 @@ fun BlazeCampaignCreationIntroScreen( onDismissClick: () -> Unit, onLearnMoreClick: () -> Unit, ) { - Scaffold( - topBar = { - Toolbar( - onNavigationButtonClick = onDismissClick, - navigationIcon = Icons.Default.Clear + val coroutineScope = rememberCoroutineScope() + val modalSheetState = rememberModalBottomSheetState( + initialValue = Hidden, + confirmValueChange = { it != HalfExpanded }, + skipHalfExpanded = true + ) + + WCModalBottomSheetLayout( + sheetContent = { + BlazeCampaignBottomSheetContent( + onDismissClick = { + coroutineScope.launch { modalSheetState.hide() } + } ) }, + sheetState = modalSheetState, modifier = Modifier.background(MaterialTheme.colors.surface) - ) { paddingValues -> - val coroutineScope = rememberCoroutineScope() - val modalSheetState = rememberModalBottomSheetState( - initialValue = Hidden, - confirmValueChange = { it != HalfExpanded }, - skipHalfExpanded = true - ) - - WCModalBottomSheetLayout( - sheetContent = { - BlazeCampaignBottomSheetContent( - onDismissClick = { - coroutineScope.launch { modalSheetState.hide() } - } + ) { + Scaffold( + topBar = { + Toolbar( + onNavigationButtonClick = onDismissClick, + navigationIcon = Icons.Default.Clear ) }, - sheetState = modalSheetState, - modifier = Modifier - .background(MaterialTheme.colors.surface) - .padding(paddingValues) - ) { + modifier = Modifier.background(MaterialTheme.colors.surface) + ) { paddingValues -> BlazeCampaignCreationIntroContent( onContinueClick = onContinueClick, onLearnMoreClick = { coroutineScope.launch { modalSheetState.show() } onLearnMoreClick() - } + }, + modifier = Modifier.padding(paddingValues) ) } } From 5c5aed723a758d14ceb232d757475880375f77af Mon Sep 17 00:00:00 2001 From: jorgemucientesfayos Date: Tue, 14 Jan 2025 19:01:17 +0100 Subject: [PATCH 14/14] Moved imeNestedScroll to the specific bottom sheet that requires it --- ...mpaignCreationAdDestinationParametersBottomSheet.kt | 10 +++++++--- .../ui/compose/component/WCModalBottomSheetLayout.kt | 4 ---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt index 3fbae44f4987..5f2894e179a0 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/blaze/creation/destination/BlazeCampaignCreationAdDestinationParametersBottomSheet.kt @@ -3,9 +3,11 @@ package com.woocommerce.android.ui.blaze.creation.destination import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.imeNestedScroll import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape @@ -33,7 +35,7 @@ import com.woocommerce.android.ui.compose.component.WCOutlinedTextField import com.woocommerce.android.ui.compose.preview.LightDarkThemePreviews import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground -@OptIn(ExperimentalMaterialApi::class) +@OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) @Composable fun AdDestinationParametersBottomSheet( viewState: ViewState, @@ -65,10 +67,12 @@ fun AdDestinationParametersBottomSheet( paramsState = viewState.bottomSheetState, onParameterChanged = onParameterChanged, onParameterSaved = onParameterSaved, - modifier = modifier.fillMaxWidth() + modifier = modifier + .fillMaxWidth() ) } - } + }, + modifier = Modifier.imeNestedScroll(), ) { screenContent() } diff --git a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt index da58710290d0..e2cdc3df515e 100644 --- a/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt +++ b/WooCommerce/src/main/kotlin/com/woocommerce/android/ui/compose/component/WCModalBottomSheetLayout.kt @@ -5,14 +5,12 @@ import androidx.compose.foundation.background import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.ColumnScope -import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.navigationBarsPadding import androidx.compose.foundation.layout.statusBarsPadding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.MaterialTheme import androidx.compose.material.ModalBottomSheetDefaults import androidx.compose.material.ModalBottomSheetLayout @@ -42,7 +40,6 @@ import com.woocommerce.android.util.SystemVersionUtils /** * A wrapper around [ModalBottomSheetLayout] that provides default values for the sheet shape and scrim color. */ -@OptIn(ExperimentalMaterialApi::class) @Composable fun WCModalBottomSheetLayout( sheetState: ModalBottomSheetState, @@ -82,7 +79,6 @@ fun WCModalBottomSheetLayout( * */ @Suppress("DEPRECATION") -@OptIn(ExperimentalMaterialApi::class, ExperimentalLayoutApi::class) @Composable private fun ModalBottomSheetLayoutWithStatusBarWorkaround( sheetContent: @Composable ColumnScope.() -> Unit,