From 0cdcfab32a2bed9493e0a3870d981eb01fc04c0c Mon Sep 17 00:00:00 2001 From: Dave Severns <dseverns@livefront.com> Date: Thu, 2 Jan 2025 11:54:46 -0500 Subject: [PATCH] WIP --- .../content/BitwardenContentBlock.kt | 96 ++++++++++++++++++- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/content/BitwardenContentBlock.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/content/BitwardenContentBlock.kt index 391ed9ea8..38e3447b8 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/content/BitwardenContentBlock.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/content/BitwardenContentBlock.kt @@ -2,14 +2,18 @@ package com.x8bit.bitwarden.ui.platform.components.content import androidx.annotation.DrawableRes import androidx.compose.foundation.background +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon +import androidx.compose.material3.Switch import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -19,8 +23,11 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.RectangleShape +import androidx.compose.ui.graphics.Shape import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview @@ -28,6 +35,7 @@ import androidx.compose.ui.unit.dp import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.bottomDivider import com.x8bit.bitwarden.ui.platform.components.model.ContentBlockData +import com.x8bit.bitwarden.ui.platform.components.toggle.color.bitwardenSwitchColors import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme @@ -43,6 +51,9 @@ fun BitwardenContentBlock( subtitleTextStyle: TextStyle = BitwardenTheme.typography.bodyMedium, backgroundColor: Color = BitwardenTheme.colorScheme.background.secondary, showDivider: Boolean = true, + shape: ContentBlockShape = ContentBlockShape.Default, + onContentClick: (() -> Unit)? = null, + trailingContent: (@Composable () -> Unit)? = null, ) { BitwardenContentBlock( headerText = data.headerText, @@ -53,6 +64,9 @@ fun BitwardenContentBlock( iconVectorResource = data.iconVectorResource, backgroundColor = backgroundColor, showDivider = showDivider, + shape = shape, + onContentClick = onContentClick, + trailingContent = trailingContent, ) } @@ -70,6 +84,9 @@ private fun BitwardenContentBlock( showDivider: Boolean = true, @DrawableRes iconVectorResource: Int? = null, backgroundColor: Color = BitwardenTheme.colorScheme.background.secondary, + shape: ContentBlockShape = ContentBlockShape.Default, + onContentClick: (() -> Unit)? = null, + trailingContent: (@Composable () -> Unit)? = null, ) { var dividerStartPadding by remember { mutableStateOf(0.dp) } val localDensity = LocalDensity.current @@ -77,9 +94,15 @@ private fun BitwardenContentBlock( Row( modifier = Modifier .fillMaxWidth() - .background(backgroundColor) + .background( + color = backgroundColor, + shape = shape(), + ) + .clickable(enabled = onContentClick != null) { + onContentClick?.invoke() + } .bottomDivider( - enabled = showDivider, + enabled = showDivider && (shape !is ContentBlockShape.Bottom), paddingStart = dividerStartPadding, ) .then(modifier), @@ -107,7 +130,7 @@ private fun BitwardenContentBlock( ?: Spacer(Modifier.width(16.dp)) } - Column(modifier = Modifier.weight(weight = 1f, fill = false)) { + Column(modifier = Modifier.weight(weight = 1f, fill = true)) { Spacer(Modifier.height(12.dp)) Text( text = headerText, @@ -123,16 +146,68 @@ private fun BitwardenContentBlock( } Spacer(Modifier.height(12.dp)) } + trailingContent?.let { + Spacer(Modifier.width(16.dp)) + it() + } Spacer(Modifier.width(16.dp)) } } +/** + * Sealed interface representing the shape of a [BitwardenContentBlock] background. + */ +sealed interface ContentBlockShape { + /** + * Returns the [Shape] defined by this [ContentBlockShape]. + */ + operator fun invoke(): Shape + + /** + * The default [ContentBlockShape] implementation. A rectangle shape. + */ + data object Default : ContentBlockShape { + override fun invoke(): Shape = RectangleShape + } + + /** + * The shape of a [BitwardenContentBlock] with rounded corners at the top. + */ + data object Top : ContentBlockShape { + override fun invoke(): Shape = RoundedCornerShape( + topStart = 8.dp, + topEnd = 8.dp, + ) + } + + /** + * The shape of a [BitwardenContentBlock] with rounded corners at the bottom. + */ + data object Bottom : ContentBlockShape { + override fun invoke(): Shape = RoundedCornerShape( + bottomStart = 8.dp, + bottomEnd = 8.dp, + ) + } + + /** + * The shape of a [BitwardenContentBlock] with rounded corners on all sides. + */ + data object Rounded : ContentBlockShape { + override fun invoke(): Shape = RoundedCornerShape( + size = 8.dp, + ) + } +} + @Preview @Composable private fun BitwardenContentBlock_preview() { BitwardenTheme { Column( - modifier = Modifier.background(color = BitwardenTheme.colorScheme.background.primary), + modifier = Modifier + .background(color = BitwardenTheme.colorScheme.background.primary) + .padding(16.dp), ) { BitwardenContentBlock( data = ContentBlockData( @@ -140,6 +215,7 @@ private fun BitwardenContentBlock_preview() { subtitleText = "Subtitle", iconVectorResource = null, ), + shape = ContentBlockShape.Top, ) BitwardenContentBlock( data = ContentBlockData( @@ -155,6 +231,17 @@ private fun BitwardenContentBlock_preview() { iconVectorResource = null, ), showDivider = false, + trailingContent = { + Switch( + modifier = Modifier + .height(height = 56.dp) + .testTag(tag = "SwitchToggle"), + enabled = false, + checked = false, + onCheckedChange = null, + colors = bitwardenSwitchColors(), + ) + }, ) BitwardenContentBlock( data = ContentBlockData( @@ -162,6 +249,7 @@ private fun BitwardenContentBlock_preview() { subtitleText = "Subtitle", iconVectorResource = null, ), + shape = ContentBlockShape.Bottom, ) } }