From 11c87116330a15fbfa82e44415a3eac0a4c81134 Mon Sep 17 00:00:00 2001 From: Philip Cappelli Date: Mon, 25 Nov 2024 10:25:48 -0500 Subject: [PATCH 1/3] PM-15147 - Design Audit - Master Password Guidance Screen --- .../CompleteRegistrationScreen.kt | 3 + .../MasterPasswordGuidanceScreen.kt | 202 ++++++++---------- .../components/card/BitwardenActionCard.kt | 29 ++- .../card/BitwardenActionCardSmall.kt | 8 +- .../card/color/BitwardenCardColors.kt | 20 +- app/src/main/res/values/strings.xml | 11 + 6 files changed, 147 insertions(+), 126 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt index f96a9b6333e..132cb167462 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt @@ -46,6 +46,7 @@ import com.x8bit.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar import com.x8bit.bitwarden.ui.platform.components.button.BitwardenFilledButton import com.x8bit.bitwarden.ui.platform.components.button.BitwardenTextButton import com.x8bit.bitwarden.ui.platform.components.card.BitwardenActionCardSmall +import com.x8bit.bitwarden.ui.platform.components.card.color.bitwardenCardColors import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenBasicDialog import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenLoadingDialog import com.x8bit.bitwarden.ui.platform.components.dialog.BitwardenTwoButtonDialog @@ -211,6 +212,8 @@ private fun CompleteRegistrationContent( actionIcon = rememberVectorPainter(id = R.drawable.ic_question_circle), actionText = stringResource(id = R.string.what_makes_a_password_strong), callToActionText = stringResource(id = R.string.learn_more), + callToActionTextColor = BitwardenTheme.colorScheme.text.interaction, + colors = bitwardenCardColors(containerColor = BitwardenTheme.colorScheme.background.primary), onCardClicked = handler.onMakeStrongPassword, modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt index 6b2befc447f..c3dd80fa878 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt @@ -1,44 +1,41 @@ package com.x8bit.bitwarden.ui.auth.feature.masterpasswordguidance -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer 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.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.rememberTopAppBarState import androidx.compose.runtime.Composable import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.clearAndSetSemantics import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.x8bit.bitwarden.R import com.x8bit.bitwarden.ui.platform.base.util.EventsEffect +import com.x8bit.bitwarden.ui.platform.base.util.bitwardenBoldSpanStyle +import com.x8bit.bitwarden.ui.platform.base.util.createAnnotatedString import com.x8bit.bitwarden.ui.platform.base.util.standardHorizontalMargin +import com.x8bit.bitwarden.ui.platform.base.util.toAnnotatedString import com.x8bit.bitwarden.ui.platform.components.appbar.BitwardenTopAppBar -import com.x8bit.bitwarden.ui.platform.components.card.BitwardenActionCardSmall -import com.x8bit.bitwarden.ui.platform.components.divider.BitwardenHorizontalDivider +import com.x8bit.bitwarden.ui.platform.components.card.BitwardenActionCard +import com.x8bit.bitwarden.ui.platform.components.card.BitwardenContentCard +import com.x8bit.bitwarden.ui.platform.components.model.ContentBlockData import com.x8bit.bitwarden.ui.platform.components.scaffold.BitwardenScaffold import com.x8bit.bitwarden.ui.platform.components.util.rememberVectorPainter import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme +import kotlinx.collections.immutable.persistentListOf private const val BULLET_TWO_TAB = "\u2022\t\t" @@ -81,128 +78,111 @@ fun MasterPasswordGuidanceScreen( ) }, ) { - Column( + MasterPasswordGuidanceContent( modifier = Modifier .fillMaxSize() .verticalScroll(rememberScrollState()) .standardHorizontalMargin(), - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .clip(RoundedCornerShape(size = 4.dp)) - .background(BitwardenTheme.colorScheme.background.tertiary), - ) { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(all = 24.dp), - ) { - - Text( - text = stringResource(R.string.what_makes_a_password_strong), - style = BitwardenTheme.typography.titleMedium, - color = BitwardenTheme.colorScheme.text.primary, - ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - style = BitwardenTheme.typography.bodyMedium, - color = BitwardenTheme.colorScheme.text.primary, - text = stringResource( - R.string.the_longer_your_password_the_more_difficult_to_hack, - ), - ) - } - BitwardenHorizontalDivider() - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 24.dp, vertical = 16.dp), - ) { - Text( - text = stringResource(R.string.the_strongest_passwords_are_usually), - style = BitwardenTheme.typography.titleSmall, - color = BitwardenTheme.colorScheme.text.primary, - ) - Spacer(modifier = Modifier.height(8.dp)) - BulletTextRow(text = stringResource(R.string.twelve_or_more_characters)) - BulletTextRow( - text = stringResource( - R.string.random_and_complex_using_numbers_and_special_characters, - ), - ) - BulletTextRow( - text = stringResource(R.string.totally_different_from_your_other_passwords), - ) - } - } - Spacer(modifier = Modifier.height(16.dp)) - TryGeneratorCard( - onCardClicked = remember(viewModel) { - { - viewModel.trySendAction( - MasterPasswordGuidanceAction.TryPasswordGeneratorAction, - ) - } - }, - ) - Spacer(modifier = Modifier.navigationBarsPadding()) - } + viewModel = viewModel, + ) } } @Composable -private fun TryGeneratorCard( - onCardClicked: () -> Unit, +private fun MasterPasswordGuidanceContent( modifier: Modifier = Modifier, + viewModel: MasterPasswordGuidanceViewModel, ) { - BitwardenActionCardSmall( - actionIcon = rememberVectorPainter(id = R.drawable.ic_generate), - actionText = stringResource( - R.string.use_the_generator_to_create_a_strong_unique_password, - ), - callToActionText = stringResource(R.string.try_it_out), - onCardClicked = onCardClicked, - modifier = modifier - .fillMaxWidth(), - trailingContent = { - Icon( - painter = rememberVectorPainter(id = R.drawable.ic_chevron_right), - contentDescription = null, - tint = BitwardenTheme.colorScheme.icon.primary, - modifier = Modifier - .align(Alignment.Center) - .size(16.dp), - ) - }, - ) -} - -@Composable -private fun BulletTextRow( - text: String, - modifier: Modifier = Modifier, -) { - Row( - modifier = modifier - .fillMaxWidth() - .padding(horizontal = 8.dp), - ) { + Column(modifier = modifier) { + Spacer(modifier = Modifier.height(24.dp)) Text( - text = BULLET_TWO_TAB, + text = stringResource(R.string.a_secure_memorable_password), textAlign = TextAlign.Center, - style = BitwardenTheme.typography.bodyMedium, + style = BitwardenTheme.typography.titleMedium, color = BitwardenTheme.colorScheme.text.primary, - modifier = Modifier.clearAndSetSemantics { }, + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), ) + Spacer(modifier = Modifier.height(8.dp)) Text( - text = text, + text = stringResource( + R.string.one_of_the_best_ways_to_create_a_secure_and_memorable_password_is_to_use_a_passphrase, + ), + textAlign = TextAlign.Center, style = BitwardenTheme.typography.bodyMedium, color = BitwardenTheme.colorScheme.text.primary, + modifier = Modifier.padding(horizontal = 16.dp), ) + Spacer(modifier = Modifier.height(24.dp)) + + BitwardenContentCard( + contentItems = persistentListOf( + ContentBlockData( + headerText = stringResource(R.string.choose_three_or_four_random_words) + .toAnnotatedString(), + subtitleText = createAnnotatedString( + mainString = stringResource( + R.string.pick_three_or_four_random_unrelated_words_that_you_can_easily_remember, + ), + highlights = listOf( + stringResource(R.string.pick_three_or_four_random_unrelated_words_highlight), + ), + highlightStyle = bitwardenBoldSpanStyle, + ), + iconVectorResource = R.drawable.ic_number1, + ), + ContentBlockData( + headerText = stringResource(R.string.combine_those_words_together) + .toAnnotatedString(), + subtitleText = createAnnotatedString( + mainString = stringResource( + R.string.put_the_words_together_in_any_order_to_form_your_passphrase_use_hyphens_spaces_or_leave_them_as_one_long_word_your_choice, + ), + highlights = listOf(stringResource(R.string.use_hyphens_spaces_or_leave_them_as_one_long_word_choice_highlight)), + highlightStyle = bitwardenBoldSpanStyle, + ), + iconVectorResource = R.drawable.ic_number2, + ), + ContentBlockData( + headerText = stringResource(R.string.make_it_yours) + .toAnnotatedString(), + subtitleText = createAnnotatedString( + mainString = stringResource(R.string.add_a_number_or_symbol_to_make_it_even_stronger_now_you_have_a_unique_secure_and_memorable_passphrase), + highlights = listOf(stringResource(R.string.add_a_number_or_symbol_highlight)), + highlightStyle = bitwardenBoldSpanStyle, + ), + iconVectorResource = R.drawable.ic_number3, + ), + ), + ) + Spacer(modifier = Modifier.height(24.dp)) + NeedSomeInspirationCard( + onActionClicked = remember(viewModel) { + { + viewModel.trySendAction( + MasterPasswordGuidanceAction.TryPasswordGeneratorAction, + ) + } + }, + ) + Spacer(modifier = Modifier.navigationBarsPadding()) } } +@Composable +private fun NeedSomeInspirationCard( + onActionClicked: () -> Unit, + modifier: Modifier = Modifier, +) { + BitwardenActionCard( + cardTitle = "Need some inspiration?", + actionText = "Check out the passphrase generator", + onActionClick = onActionClicked, + modifier = modifier.fillMaxWidth(), + ) +} + @Preview @Composable private fun MasterPasswordGuidanceScreenPreview() { diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/BitwardenActionCard.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/BitwardenActionCard.kt index abeaf0c3647..9ce164e9747 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/BitwardenActionCard.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/BitwardenActionCard.kt @@ -35,7 +35,7 @@ import kotlin.let * @param cardTitle The title of the card. * @param actionText The text content on the CTA button. * @param onActionClick The action to perform when the CTA button is clicked. - * @param onDismissClick The action to perform when the dismiss button is clicked. + * @param onDismissClick Optional action to perform when the dismiss button is clicked. * @param leadingContent Optional content to display on the leading side of the * [cardTitle] [Text]. */ @@ -44,7 +44,7 @@ fun BitwardenActionCard( cardTitle: String, actionText: String, onActionClick: () -> Unit, - onDismissClick: () -> Unit, + onDismissClick: (() -> Unit)? = null, modifier: Modifier = Modifier, cardSubtitle: String? = null, leadingContent: @Composable (() -> Unit)? = null, @@ -69,11 +69,13 @@ fun BitwardenActionCard( ) } Spacer(Modifier.weight(1f)) - BitwardenStandardIconButton( - painter = rememberVectorPainter(id = R.drawable.ic_close), - contentDescription = stringResource(id = R.string.close), - onClick = onDismissClick, - ) + onDismissClick?.let { + BitwardenStandardIconButton( + painter = rememberVectorPainter(id = R.drawable.ic_close), + contentDescription = stringResource(id = R.string.close), + onClick = it, + ) + } } cardSubtitle?.let { Spacer(Modifier.height(4.dp)) @@ -103,6 +105,19 @@ fun BitwardenActionCard( */ fun actionCardExitAnimation() = fadeOut() + shrinkVertically(shrinkTowards = Alignment.Top) +@Preview +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +private fun BitwardenActionCardWithSubtitleNoDismiss_preview() { + BitwardenTheme { + BitwardenActionCard( + cardTitle = "Title", + actionText = "Action", + onActionClick = {}, + ) + } +} + @Preview @Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) @Composable diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/BitwardenActionCardSmall.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/BitwardenActionCardSmall.kt index df23460901e..d8611c95654 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/BitwardenActionCardSmall.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/BitwardenActionCardSmall.kt @@ -12,12 +12,14 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material3.Card +import androidx.compose.material3.CardColors import androidx.compose.material3.CardDefaults 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.graphics.Color import androidx.compose.ui.graphics.vector.VectorPainter import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp @@ -34,6 +36,8 @@ fun BitwardenActionCardSmall( actionIcon: VectorPainter, actionText: String, callToActionText: String, + callToActionTextColor: Color = BitwardenTheme.colorScheme.text.primary, + colors: CardColors = bitwardenCardColors(), onCardClicked: () -> Unit, modifier: Modifier = Modifier, trailingContent: (@Composable BoxScope.() -> Unit)? = null, @@ -42,7 +46,7 @@ fun BitwardenActionCardSmall( onClick = onCardClicked, shape = BitwardenTheme.shapes.actionCard, modifier = modifier, - colors = bitwardenCardColors(), + colors = colors, elevation = CardDefaults.elevatedCardElevation(), border = BorderStroke(width = 1.dp, color = BitwardenTheme.colorScheme.stroke.border), ) { @@ -70,7 +74,7 @@ fun BitwardenActionCardSmall( Text( text = callToActionText, style = BitwardenTheme.typography.labelLarge, - color = BitwardenTheme.colorScheme.text.primary, + color = callToActionTextColor, ) } Spacer(modifier = Modifier.width(16.dp)) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/color/BitwardenCardColors.kt b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/color/BitwardenCardColors.kt index 05e99959958..60ce38dea85 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/color/BitwardenCardColors.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/platform/components/card/color/BitwardenCardColors.kt @@ -2,15 +2,23 @@ package com.x8bit.bitwarden.ui.platform.components.card.color import androidx.compose.material3.CardColors import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color import com.x8bit.bitwarden.ui.platform.theme.BitwardenTheme /** * Provides a default set of Bitwarden-styled colors for a card. */ @Composable -fun bitwardenCardColors(): CardColors = CardColors( - containerColor = BitwardenTheme.colorScheme.background.tertiary, - contentColor = BitwardenTheme.colorScheme.text.primary, - disabledContainerColor = BitwardenTheme.colorScheme.filledButton.backgroundDisabled, - disabledContentColor = BitwardenTheme.colorScheme.filledButton.foregroundDisabled, -) +fun bitwardenCardColors( + containerColor: Color = BitwardenTheme.colorScheme.background.tertiary, + contentColor: Color = BitwardenTheme.colorScheme.text.primary, + disabledContainerColor: Color = BitwardenTheme.colorScheme.filledButton.backgroundDisabled, + disabledContentColor: Color = BitwardenTheme.colorScheme.filledButton.foregroundDisabled, +): CardColors { + return CardColors( + containerColor = containerColor, + contentColor = contentColor, + disabledContainerColor = disabledContainerColor, + disabledContentColor = disabledContentColor, + ) +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 22540f6b0b9..d11317f16b6 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -962,6 +962,7 @@ Do you want to switch to this account? Remove passkey Passkey removed What makes a password strong? + A secure, memorable password The longer your password, the more difficult it is to hack. The minimum for account creation is 12 characters but if you do 14 characters, the time to crack your password would be centuries! The strongest passwords are usually: 12 or more characters @@ -978,6 +979,7 @@ Do you want to switch to this account? Set up biometrics or choose a PIN code to quickly access your vault and AutoFill your logins. Never lose access to your vault The best way to make sure you can always access your account is to set up safeguards from the start. + One of the best ways to create a secure and memorable password is to use a passphrase. \nHere’s how: Create a hint Your hint will be sent to you via email when you request it. Write your password down @@ -1099,4 +1101,13 @@ Do you want to switch to this account? You’ve been logged out because your device’s biometrics don’t meet the latest security requirements. To update settings, log in once again or contact your administrator for access. CXP Import CXP Export + Choose three or four random words + Pick three or four random, unrelated words that you can easily remember. Think of objects, places, or things you like. + objects, places, or things + Combine those words together + Put the words together in any order to form your passphrase. Use hyphens, spaces, or leave them as one long word—your choice! + Use hyphens, spaces, or leave them as one long word + Make it yours + Add a number or symbol to make it even stronger. Now you have a unique, secure, and memorable passphrase! + Add a number or symbol From 63ce644749c7900502be3dbc0dcd0845c228a8e4 Mon Sep 17 00:00:00 2001 From: Philip Cappelli Date: Mon, 25 Nov 2024 11:37:44 -0500 Subject: [PATCH 2/3] fix linter errors --- .../CompleteRegistrationScreen.kt | 4 +- .../MasterPasswordGuidanceScreen.kt | 66 +++++++++++++------ app/src/main/res/values/strings.xml | 10 +-- 3 files changed, 53 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt index 132cb167462..05e87495e7d 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/completeregistration/CompleteRegistrationScreen.kt @@ -213,7 +213,9 @@ private fun CompleteRegistrationContent( actionText = stringResource(id = R.string.what_makes_a_password_strong), callToActionText = stringResource(id = R.string.learn_more), callToActionTextColor = BitwardenTheme.colorScheme.text.interaction, - colors = bitwardenCardColors(containerColor = BitwardenTheme.colorScheme.background.primary), + colors = bitwardenCardColors( + containerColor = BitwardenTheme.colorScheme.background.primary, + ), onCardClicked = handler.onMakeStrongPassword, modifier = Modifier .fillMaxWidth() diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt index c3dd80fa878..e3fc4170e50 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt @@ -93,6 +93,24 @@ private fun MasterPasswordGuidanceContent( modifier: Modifier = Modifier, viewModel: MasterPasswordGuidanceViewModel, ) { + Column(modifier = modifier) { + MasterPasswordGuidanceHeader() + MasterPasswordGuidanceContentBlocks() + NeedSomeInspirationCard( + onActionClicked = remember(viewModel) { + { + viewModel.trySendAction( + MasterPasswordGuidanceAction.TryPasswordGeneratorAction, + ) + } + }, + ) + Spacer(modifier = Modifier.navigationBarsPadding()) + } +} + +@Composable +private fun MasterPasswordGuidanceHeader(modifier: Modifier = Modifier) { Column(modifier = modifier) { Spacer(modifier = Modifier.height(24.dp)) Text( @@ -107,15 +125,22 @@ private fun MasterPasswordGuidanceContent( Spacer(modifier = Modifier.height(8.dp)) Text( text = stringResource( - R.string.one_of_the_best_ways_to_create_a_secure_and_memorable_password_is_to_use_a_passphrase, + R.string.one_of_the_best_ways_to_create_a_secure_and_memorable_password, ), textAlign = TextAlign.Center, style = BitwardenTheme.typography.bodyMedium, color = BitwardenTheme.colorScheme.text.primary, - modifier = Modifier.padding(horizontal = 16.dp), + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp), ) Spacer(modifier = Modifier.height(24.dp)) + } +} +@Composable +private fun MasterPasswordGuidanceContentBlocks(modifier: Modifier = Modifier) { + Column(modifier = modifier) { BitwardenContentCard( contentItems = persistentListOf( ContentBlockData( @@ -123,10 +148,12 @@ private fun MasterPasswordGuidanceContent( .toAnnotatedString(), subtitleText = createAnnotatedString( mainString = stringResource( - R.string.pick_three_or_four_random_unrelated_words_that_you_can_easily_remember, + R.string.pick_three_or_four_random_unrelated_words, ), highlights = listOf( - stringResource(R.string.pick_three_or_four_random_unrelated_words_highlight), + stringResource( + R.string.pick_three_or_four_random_unrelated_words_highlight, + ), ), highlightStyle = bitwardenBoldSpanStyle, ), @@ -137,37 +164,34 @@ private fun MasterPasswordGuidanceContent( .toAnnotatedString(), subtitleText = createAnnotatedString( mainString = stringResource( - R.string.put_the_words_together_in_any_order_to_form_your_passphrase_use_hyphens_spaces_or_leave_them_as_one_long_word_your_choice, + R.string.put_the_words_together_in_any_order_to_form_your_passphrase, + ), + highlights = listOf( + stringResource( + R.string.use_hyphens_spaces_or_leave_them_as_long_word_highlight, + ), ), - highlights = listOf(stringResource(R.string.use_hyphens_spaces_or_leave_them_as_one_long_word_choice_highlight)), highlightStyle = bitwardenBoldSpanStyle, ), iconVectorResource = R.drawable.ic_number2, ), ContentBlockData( - headerText = stringResource(R.string.make_it_yours) - .toAnnotatedString(), + headerText = stringResource(R.string.make_it_yours).toAnnotatedString(), subtitleText = createAnnotatedString( - mainString = stringResource(R.string.add_a_number_or_symbol_to_make_it_even_stronger_now_you_have_a_unique_secure_and_memorable_passphrase), - highlights = listOf(stringResource(R.string.add_a_number_or_symbol_highlight)), + mainString = stringResource( + R.string.add_a_number_or_symbol_to_make_it_even_stronger, + ), + highlights = listOf( + stringResource(R.string.add_a_number_or_symbol_highlight), + ), highlightStyle = bitwardenBoldSpanStyle, ), iconVectorResource = R.drawable.ic_number3, ), ), ) - Spacer(modifier = Modifier.height(24.dp)) - NeedSomeInspirationCard( - onActionClicked = remember(viewModel) { - { - viewModel.trySendAction( - MasterPasswordGuidanceAction.TryPasswordGeneratorAction, - ) - } - }, - ) - Spacer(modifier = Modifier.navigationBarsPadding()) } + Spacer(modifier = Modifier.height(24.dp)) } @Composable diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d11317f16b6..e17e35c35f1 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -979,7 +979,7 @@ Do you want to switch to this account? Set up biometrics or choose a PIN code to quickly access your vault and AutoFill your logins. Never lose access to your vault The best way to make sure you can always access your account is to set up safeguards from the start. - One of the best ways to create a secure and memorable password is to use a passphrase. \nHere’s how: + One of the best ways to create a secure and memorable password is to use a passphrase. \nHere’s how: Create a hint Your hint will be sent to you via email when you request it. Write your password down @@ -1102,12 +1102,12 @@ Do you want to switch to this account? CXP Import CXP Export Choose three or four random words - Pick three or four random, unrelated words that you can easily remember. Think of objects, places, or things you like. + Pick three or four random, unrelated words that you can easily remember. Think of objects, places, or things you like. objects, places, or things Combine those words together - Put the words together in any order to form your passphrase. Use hyphens, spaces, or leave them as one long word—your choice! - Use hyphens, spaces, or leave them as one long word + Put the words together in any order to form your passphrase. Use hyphens, spaces, or leave them as one long word—your choice! + Use hyphens, spaces, or leave them as one long word Make it yours - Add a number or symbol to make it even stronger. Now you have a unique, secure, and memorable passphrase! + Add a number or symbol to make it even stronger. Now you have a unique, secure, and memorable passphrase! Add a number or symbol From 47c5e8609a1ca1b3dc9a7033c1d4e01c46112252 Mon Sep 17 00:00:00 2001 From: Philip Cappelli Date: Mon, 25 Nov 2024 12:17:43 -0500 Subject: [PATCH 3/3] fix texts and abstract missed strings to resource --- .../masterpasswordguidance/MasterPasswordGuidanceScreen.kt | 7 ++++--- app/src/main/res/values/strings.xml | 2 ++ .../MasterPasswordGuidanceScreenTest.kt | 4 +++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt index e3fc4170e50..09048a270bb 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreen.kt @@ -200,10 +200,11 @@ private fun NeedSomeInspirationCard( modifier: Modifier = Modifier, ) { BitwardenActionCard( - cardTitle = "Need some inspiration?", - actionText = "Check out the passphrase generator", + cardTitle = stringResource(R.string.need_some_inspiration), + actionText = stringResource(R.string.check_out_the_passphrase_generator), onActionClick = onActionClicked, - modifier = modifier.fillMaxWidth(), + modifier = modifier + .fillMaxWidth(), ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e17e35c35f1..a4ab85954c8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1110,4 +1110,6 @@ Do you want to switch to this account? Make it yours Add a number or symbol to make it even stronger. Now you have a unique, secure, and memorable passphrase! Add a number or symbol + "Need some inspiration?" + "Check out the passphrase generator" diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreenTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreenTest.kt index 26ff59f0b5f..66a1913ee1f 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreenTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/masterpasswordguidance/MasterPasswordGuidanceScreenTest.kt @@ -3,6 +3,7 @@ package com.x8bit.bitwarden.ui.auth.feature.masterpasswordguidance import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.performClick +import androidx.compose.ui.test.performScrollTo import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFlow import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest import io.mockk.every @@ -45,7 +46,8 @@ class MasterPasswordGuidanceScreenTest : BaseComposeTest() { @Test fun `Generator card click should invoke send of TryPasswordGeneratorAction`() { composeTestRule - .onNodeWithText("Use the generator to create a strong, unique password") + .onNodeWithText("Check out the passphrase generator") + .performScrollTo() .performClick() verify { viewModel.trySendAction(MasterPasswordGuidanceAction.TryPasswordGeneratorAction) }