PM-25006: Migrate row components to the UI module (#5753)

This commit is contained in:
David Perez
2025-08-19 17:07:26 -05:00
committed by GitHub
parent b010c9a29d
commit 5f42c9bb39
10 changed files with 14 additions and 14 deletions

View File

@@ -1,96 +0,0 @@
package com.x8bit.bitwarden.ui.platform.components.row
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
import com.bitwarden.ui.platform.base.util.mirrorIfRtl
import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.platform.theme.BitwardenTheme
/**
* Represents a row of text that can be clicked on and contains an external link.
* A confirmation dialog will always be displayed before [onConfirmClick] is invoked.
*
* @param text The label for the row as a [String].
* @param onConfirmClick The callback when the confirm button of the dialog is clicked.
* @param cardStyle Indicates the type of card style to be applied.
* @param modifier The modifier to be applied to the layout.
* @param description An optional description label to be displayed below the [text].
* @param withDivider Indicates if a divider should be drawn on the bottom of the row, defaults
* to `true`.
* @param dialogTitle The title of the dialog displayed when the user clicks this item.
* @param dialogMessage The message of the dialog displayed when the user clicks this item.
* @param dialogConfirmButtonText The text on the confirm button of the dialog displayed when the
* user clicks this item.
* @param dialogDismissButtonText The text on the dismiss button of the dialog displayed when the
* user clicks this item.
*/
@Composable
fun BitwardenExternalLinkRow(
text: String,
onConfirmClick: () -> Unit,
cardStyle: CardStyle,
modifier: Modifier = Modifier,
description: String? = null,
withDivider: Boolean = true,
dialogTitle: String,
dialogMessage: String,
dialogConfirmButtonText: String = stringResource(id = BitwardenString.continue_text),
dialogDismissButtonText: String = stringResource(id = BitwardenString.cancel),
) {
var shouldShowDialog by rememberSaveable { mutableStateOf(false) }
BitwardenTextRow(
text = text,
description = description,
onClick = { shouldShowDialog = true },
modifier = modifier,
withDivider = withDivider,
cardStyle = cardStyle,
) {
Icon(
modifier = Modifier.mirrorIfRtl(),
painter = rememberVectorPainter(id = BitwardenDrawable.ic_external_link),
contentDescription = null,
tint = BitwardenTheme.colorScheme.icon.primary,
)
}
if (shouldShowDialog) {
BitwardenTwoButtonDialog(
title = dialogTitle,
message = dialogMessage,
confirmButtonText = dialogConfirmButtonText,
dismissButtonText = dialogDismissButtonText,
onConfirmClick = {
shouldShowDialog = false
onConfirmClick()
},
onDismissClick = { shouldShowDialog = false },
onDismissRequest = { shouldShowDialog = false },
)
}
}
@Preview
@Composable
private fun BitwardenExternalLinkRow_preview() {
BitwardenTheme {
BitwardenExternalLinkRow(
text = "Linked Text",
onConfirmClick = { },
dialogTitle = "",
dialogMessage = "",
cardStyle = CardStyle.Full,
)
}
}

View File

@@ -1,139 +0,0 @@
package com.x8bit.bitwarden.ui.platform.components.row
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.bitwarden.ui.platform.base.util.cardStyle
import com.bitwarden.ui.platform.base.util.mirrorIfRtl
import com.bitwarden.ui.platform.components.badge.NotificationBadge
import com.bitwarden.ui.platform.components.icon.BitwardenIcon
import com.bitwarden.ui.platform.components.icon.model.IconData
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.theme.BitwardenTheme
/**
* Reusable row with push icon built in.
*
* @param text The displayable text.
* @param onClick The callback when the row is clicked.
* @param cardStyle The [CardStyle] to be applied to this row.
* @param modifier The modifier for this composable.
* @param leadingIcon An optional leading icon.
* @param notificationCount The optional notification count to be displayed.
*/
@Composable
fun BitwardenPushRow(
text: String,
onClick: () -> Unit,
cardStyle: CardStyle,
modifier: Modifier = Modifier,
leadingIcon: IconData? = null,
notificationCount: Int = 0,
) {
Row(
modifier = modifier
.fillMaxWidth()
.defaultMinSize(minHeight = 60.dp)
.cardStyle(
cardStyle = cardStyle,
onClick = onClick,
paddingStart = leadingIcon?.let { 12.dp } ?: 16.dp,
paddingEnd = 20.dp,
paddingTop = 6.dp,
paddingBottom = 6.dp,
),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.defaultMinSize(minHeight = 48.dp)
.weight(weight = 1f),
) {
leadingIcon?.let {
BitwardenIcon(
iconData = it,
tint = BitwardenTheme.colorScheme.icon.primary,
modifier = Modifier.size(size = 24.dp),
)
Spacer(modifier = Modifier.width(width = 12.dp))
}
Text(
text = text,
style = BitwardenTheme.typography.bodyLarge,
color = BitwardenTheme.colorScheme.text.primary,
modifier = Modifier.fillMaxWidth(),
)
}
TrailingContent(notificationCount = notificationCount)
}
}
@Composable
private fun TrailingContent(
notificationCount: Int,
modifier: Modifier = Modifier,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = modifier.defaultMinSize(minHeight = 48.dp),
) {
val notificationBadgeVisible = notificationCount > 0
NotificationBadge(
notificationCount = notificationCount,
isVisible = notificationBadgeVisible,
)
if (notificationBadgeVisible) {
Spacer(modifier = Modifier.width(12.dp))
}
Icon(
painter = rememberVectorPainter(id = BitwardenDrawable.ic_chevron_right),
contentDescription = null,
tint = BitwardenTheme.colorScheme.icon.primary,
modifier = Modifier
.mirrorIfRtl()
.size(size = 16.dp),
)
}
}
@Preview
@Composable
private fun BitwardenPushRow_preview() {
BitwardenTheme {
Column {
BitwardenPushRow(
text = "Plain Row",
onClick = { },
cardStyle = CardStyle.Top(),
)
BitwardenPushRow(
text = "Icon Row",
onClick = { },
cardStyle = CardStyle.Middle(),
leadingIcon = IconData.Local(iconRes = BitwardenDrawable.ic_vault),
)
BitwardenPushRow(
text = "Notification Row",
onClick = { },
cardStyle = CardStyle.Bottom,
notificationCount = 3,
)
}
}
}

View File

@@ -1,165 +0,0 @@
package com.x8bit.bitwarden.ui.platform.components.row
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.bitwarden.ui.platform.base.util.cardStyle
import com.bitwarden.ui.platform.base.util.nullableTestTag
import com.bitwarden.ui.platform.components.button.BitwardenStandardIconButton
import com.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.components.model.TooltipData
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.theme.BitwardenTheme
/**
* Represents a clickable row of text and can contains an optional [content] that appears to the
* right of the [text].
*
* @param text The label for the row as a [String].
* @param onClick The callback when the row is clicked.
* @param cardStyle Indicates the type of card style to be applied.
* @param modifier The modifier to be applied to the layout.
* @param description An optional description label to be displayed below the [text].
* @param textTestTag The optional test tag for the inner text component.
* @param isEnabled Indicates if the row is enabled or not, a disabled row will not be clickable
* and it's contents will be dimmed.
* @param clickable An optional override for whether the row is clickable or not. Defaults to
* [isEnabled].
* @param withDivider Indicates if a divider should be drawn on the bottom of the row, defaults
* to `false`.
* @param tooltip The data required to display a tooltip.
* @param content The content of the [BitwardenTextRow].
*/
@Suppress("LongMethod")
@Composable
fun BitwardenTextRow(
text: String,
onClick: () -> Unit,
cardStyle: CardStyle,
modifier: Modifier = Modifier,
description: String? = null,
textTestTag: String? = null,
isEnabled: Boolean = true,
clickable: Boolean = isEnabled,
withDivider: Boolean = false,
tooltip: TooltipData? = null,
content: (@Composable () -> Unit)? = null,
) {
Box(
contentAlignment = Alignment.CenterStart,
modifier = modifier
.defaultMinSize(minHeight = 60.dp)
.cardStyle(
cardStyle = cardStyle,
onClick = onClick,
clickEnabled = clickable,
paddingHorizontal = 16.dp,
)
.semantics(mergeDescendants = true) { },
) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
) {
Column(
modifier = Modifier
.padding(end = 16.dp)
.weight(1f),
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = text,
style = BitwardenTheme.typography.bodyLarge,
color = if (isEnabled) {
BitwardenTheme.colorScheme.text.primary
} else {
BitwardenTheme.colorScheme.filledButton.foregroundDisabled
},
modifier = Modifier.nullableTestTag(tag = textTestTag),
)
tooltip?.let { ToolTip(tooltip = it) }
}
description?.let {
Text(
text = it,
style = BitwardenTheme.typography.bodyMedium,
color = if (isEnabled) {
BitwardenTheme.colorScheme.text.secondary
} else {
BitwardenTheme.colorScheme.filledButton.foregroundDisabled
},
)
}
}
content?.invoke()
}
if (withDivider) {
BitwardenHorizontalDivider(modifier = Modifier.padding(start = 16.dp))
}
}
}
@Composable
private fun RowScope.ToolTip(
tooltip: TooltipData,
) {
Spacer(modifier = Modifier.width(width = 8.dp))
BitwardenStandardIconButton(
vectorIconRes = BitwardenDrawable.ic_question_circle_small,
contentDescription = tooltip.contentDescription,
onClick = tooltip.onClick,
contentColor = BitwardenTheme.colorScheme.icon.secondary,
modifier = Modifier
.testTag(tag = "TextRowTooltip"),
)
}
@Preview
@Composable
private fun BitwardenTextRowWithTooltipAndContent_Preview() {
BitwardenTextRow(
text = "Sample Text",
onClick = {},
cardStyle = CardStyle.Full,
description = "This is a sample description.",
textTestTag = "sampleTestTag",
isEnabled = true,
withDivider = false,
tooltip = TooltipData(
contentDescription = "Tooltip Description",
onClick = {},
),
)
}
@Preview
@Composable
private fun BitwardenTextRowWithDividerDisabled_Preview() {
BitwardenTextRow(
text = "Sample Text Disabled",
onClick = {},
cardStyle = CardStyle.Top(),
description = "This is a sample disabled description.",
textTestTag = "sampleDisabledTestTag",
isEnabled = false,
withDivider = true,
tooltip = null,
)
}

View File

@@ -27,11 +27,11 @@ import com.bitwarden.ui.platform.base.util.toListItemCardStyle
import com.bitwarden.ui.platform.components.appbar.BitwardenMediumTopAppBar
import com.bitwarden.ui.platform.components.appbar.NavigationIcon
import com.bitwarden.ui.platform.components.icon.model.IconData
import com.bitwarden.ui.platform.components.row.BitwardenPushRow
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenPushRow
/**
* Displays the settings screen.

View File

@@ -36,6 +36,9 @@ import com.bitwarden.ui.platform.base.util.standardHorizontalMargin
import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.components.model.TooltipData
import com.bitwarden.ui.platform.components.row.BitwardenExternalLinkRow
import com.bitwarden.ui.platform.components.row.BitwardenPushRow
import com.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
@@ -46,9 +49,6 @@ import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.bitwarden.ui.util.Text
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenExternalLinkRow
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenPushRow
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenTextRow
/**
* Displays the about screen.

View File

@@ -49,6 +49,8 @@ import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
import com.bitwarden.ui.platform.components.dropdown.BitwardenMultiSelectButton
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.components.row.BitwardenExternalLinkRow
import com.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
@@ -61,8 +63,6 @@ import com.bitwarden.ui.util.Text
import com.bitwarden.ui.util.asText
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenExternalLinkRow
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenUnlockWithBiometricsSwitch
import com.x8bit.bitwarden.ui.platform.components.toggle.BitwardenUnlockWithPinSwitch
import com.x8bit.bitwarden.ui.platform.composition.LocalBiometricsManager

View File

@@ -46,6 +46,8 @@ import com.bitwarden.ui.platform.components.dropdown.model.MultiSelectOption
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.components.model.TooltipData
import com.bitwarden.ui.platform.components.row.BitwardenExternalLinkRow
import com.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.toggle.BitwardenSwitch
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
@@ -55,8 +57,6 @@ import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.data.platform.repository.model.UriMatchType
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenExternalLinkRow
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.browser.BrowserAutofillSettingsCard
import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.handlers.AutoFillHandlers
import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.util.displayLabel

View File

@@ -34,11 +34,11 @@ import com.bitwarden.ui.platform.components.dialog.BitwardenLoadingDialog
import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
import com.bitwarden.ui.platform.components.header.BitwardenExpandingHeader
import com.bitwarden.ui.platform.components.header.BitwardenListHeaderText
import com.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.x8bit.bitwarden.ui.platform.feature.settings.autofill.privilegedapps.list.model.PrivilegedAppListItem
import kotlinx.collections.immutable.persistentListOf

View File

@@ -31,12 +31,12 @@ import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
import com.bitwarden.ui.platform.components.content.BitwardenErrorContent
import com.bitwarden.ui.platform.components.content.BitwardenLoadingContent
import com.bitwarden.ui.platform.components.fab.BitwardenFloatingActionButton
import com.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.x8bit.bitwarden.ui.platform.feature.settings.folders.model.FolderDisplayItem
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList

View File

@@ -30,13 +30,13 @@ import com.bitwarden.ui.platform.components.badge.NotificationBadge
import com.bitwarden.ui.platform.components.card.BitwardenActionCard
import com.bitwarden.ui.platform.components.card.actionCardExitAnimation
import com.bitwarden.ui.platform.components.model.CardStyle
import com.bitwarden.ui.platform.components.row.BitwardenTextRow
import com.bitwarden.ui.platform.components.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.components.snackbar.BitwardenSnackbarHost
import com.bitwarden.ui.platform.components.snackbar.rememberBitwardenSnackbarHostState
import com.bitwarden.ui.platform.components.util.rememberVectorPainter
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.x8bit.bitwarden.ui.platform.components.row.BitwardenTextRow
/**
* Displays the vault settings screen.