PM-38479: Feat: Update the RemovePasswordScreen UI (#7010)

This commit is contained in:
David Perez
2026-06-02 15:02:04 -05:00
committed by GitHub
parent 051b8b53d1
commit bd45d5f56a
4 changed files with 74 additions and 38 deletions

View File

@@ -1,11 +1,14 @@
package com.x8bit.bitwarden.ui.auth.feature.removepassword
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.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
@@ -14,14 +17,17 @@ import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.bitwarden.ui.platform.base.util.cardStyle
import com.bitwarden.ui.platform.base.util.standardHorizontalMargin
import com.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar
import com.bitwarden.ui.platform.components.button.BitwardenFilledButton
@@ -30,8 +36,11 @@ import com.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog
import com.bitwarden.ui.platform.components.dialog.BitwardenLoadingDialog
import com.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog
import com.bitwarden.ui.platform.components.field.BitwardenPasswordField
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.scaffold.BitwardenScaffold
import com.bitwarden.ui.platform.resource.BitwardenDrawable
import com.bitwarden.ui.platform.resource.BitwardenString
import com.bitwarden.ui.platform.theme.BitwardenTheme
import com.bitwarden.ui.util.asText
@@ -91,53 +100,41 @@ private fun RemovePasswordScreenContent(
modifier = modifier
.verticalScroll(rememberScrollState()),
) {
Spacer(modifier = Modifier.height(height = 12.dp))
Spacer(modifier = Modifier.height(height = 24.dp))
Text(
text = state.description(),
style = BitwardenTheme.typography.bodyMedium,
color = BitwardenTheme.colorScheme.text.primary,
textAlign = TextAlign.Center,
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
)
Spacer(modifier = Modifier.height(height = 12.dp))
Text(
text = state.labelOrg(),
style = BitwardenTheme.typography.bodyMedium,
color = BitwardenTheme.colorScheme.text.primary,
Spacer(modifier = Modifier.height(height = 24.dp))
RemovePasswordInfoColumn(
label = state.labelOrg(),
value = state.orgName?.invoke().orEmpty(),
icon = IconData.Local(iconRes = BitwardenDrawable.ic_organization),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.fillMaxWidth(),
.cardStyle(
cardStyle = CardStyle.Top(dividerPadding = 56.dp),
paddingBottom = 4.dp,
),
)
Text(
text = state.orgName?.invoke().orEmpty(),
style = BitwardenTheme.typography.bodyMedium,
color = BitwardenTheme.colorScheme.text.secondary,
RemovePasswordInfoColumn(
label = state.labelDomain(),
value = state.domainName?.invoke().orEmpty(),
icon = IconData.Local(iconRes = BitwardenDrawable.ic_globe),
modifier = Modifier
.fillMaxWidth()
.standardHorizontalMargin()
.fillMaxWidth(),
.cardStyle(cardStyle = CardStyle.Bottom),
)
Spacer(modifier = Modifier.height(height = 12.dp))
Text(
text = state.labelDomain(),
style = BitwardenTheme.typography.bodyMedium,
color = BitwardenTheme.colorScheme.text.primary,
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
)
Text(
text = state.domainName?.invoke().orEmpty(),
style = BitwardenTheme.typography.bodyMedium,
color = BitwardenTheme.colorScheme.text.secondary,
modifier = Modifier
.standardHorizontalMargin()
.fillMaxWidth(),
)
Spacer(modifier = Modifier.height(16.dp))
Spacer(modifier = Modifier.height(height = 24.dp))
BitwardenPasswordField(
label = stringResource(id = BitwardenString.master_password),
@@ -179,6 +176,43 @@ private fun RemovePasswordScreenContent(
}
}
@Composable
private fun RemovePasswordInfoColumn(
label: String,
value: String,
icon: IconData,
modifier: Modifier = Modifier,
) {
Row(
modifier = modifier.defaultMinSize(minHeight = 60.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Spacer(modifier = Modifier.width(width = 12.dp))
BitwardenIcon(
iconData = icon,
tint = BitwardenTheme.colorScheme.icon.secondary,
)
Spacer(modifier = Modifier.width(width = 12.dp))
Column(modifier = Modifier.fillMaxWidth()) {
Text(
text = label,
style = BitwardenTheme.typography.titleSmall,
color = BitwardenTheme.colorScheme.text.primary,
modifier = Modifier.fillMaxWidth(),
)
Spacer(modifier = Modifier.height(height = 4.dp))
Text(
text = value,
style = BitwardenTheme.typography.bodyMedium,
color = BitwardenTheme.colorScheme.text.secondary,
modifier = Modifier.fillMaxWidth(),
)
}
}
}
@Composable
private fun RemovePasswordDialogs(
dialogState: RemovePasswordState.DialogState?,

View File

@@ -36,8 +36,10 @@ class RemovePasswordViewModel @Inject constructor(
RemovePasswordState(
input = "",
description = BitwardenString.password_no_longer_required_confirm_domain.asText(),
labelOrg = BitwardenString.key_connector_organization.asText(),
description = BitwardenString
.your_organization_no_longer_requires_a_master_password
.asText(),
labelOrg = BitwardenString.organization.asText(),
orgName = org?.name?.asText(),
labelDomain = BitwardenString.key_connector_domain.asText(),
domainName = org?.keyConnectorUrl?.asText(),

View File

@@ -268,8 +268,9 @@ private val DEFAULT_STATE = RemovePasswordState(
input = "",
dialogState = null,
description = BitwardenString
.password_no_longer_required_confirm_domain.asText(),
labelOrg = BitwardenString.key_connector_organization.asText(),
.your_organization_no_longer_requires_a_master_password
.asText(),
labelOrg = BitwardenString.organization.asText(),
orgName = ORGANIZATION_NAME.asText(),
labelDomain = BitwardenString.key_connector_domain.asText(),
domainName = KEY_CONNECTOR_URL.asText(),

View File

@@ -991,9 +991,8 @@ Do you want to switch to this account?</string>
<string name="delete_logs">Delete logs</string>
<string name="do_you_really_want_to_delete_all_recorded_logs">Do you really want to delete all recorded logs?</string>
<string name="confirm_key_connector_domain">Confirm Key Connector domain</string>
<string name="key_connector_domain">Key Connector domain:</string>
<string name="key_connector_organization">Organization:</string>
<string name="password_no_longer_required_confirm_domain">A master password is no longer required for members of the following organization. Please confirm the domain below with your organization administrator.</string>
<string name="key_connector_domain">Key Connector domain</string>
<string name="your_organization_no_longer_requires_a_master_password">Your organization no longer requires a master password for its members. Please verify the domain below with your admin and enter your master password to continue.</string>
<string name="please_confirm_domain_with_admin">Please confirm the domain below with your organization administrator.\n\nKey Connector domain:\n%1$s</string>
<string name="flight_recorder_banner_title">Flight recorder on</string>
<string name="flight_recorder_banner_message">Flight recorder will be active until %1$s at %2$s. Return to settings to deactivate now.</string>