Skip to content

Commit 736fe3d

Browse files
PM-27597: Update Yubikey illustration and copy
1 parent 448ba97 commit 736fe3d

File tree

10 files changed

+136
-63
lines changed

10 files changed

+136
-63
lines changed

app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt

Lines changed: 37 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,19 @@ import androidx.compose.foundation.layout.fillMaxSize
77
import androidx.compose.foundation.layout.fillMaxWidth
88
import androidx.compose.foundation.layout.height
99
import androidx.compose.foundation.layout.navigationBarsPadding
10-
import androidx.compose.foundation.layout.padding
1110
import androidx.compose.foundation.layout.size
1211
import androidx.compose.foundation.rememberScrollState
13-
import androidx.compose.foundation.shape.RoundedCornerShape
1412
import androidx.compose.foundation.text.KeyboardActions
1513
import androidx.compose.foundation.verticalScroll
1614
import androidx.compose.material3.ExperimentalMaterial3Api
1715
import androidx.compose.material3.Text
1816
import androidx.compose.material3.TopAppBarDefaults
19-
import androidx.compose.material3.rememberTopAppBarState
2017
import androidx.compose.runtime.Composable
2118
import androidx.compose.runtime.getValue
2219
import androidx.compose.runtime.remember
2320
import androidx.compose.ui.Alignment
2421
import androidx.compose.ui.Modifier
25-
import androidx.compose.ui.draw.clip
2622
import androidx.compose.ui.input.nestedscroll.nestedScroll
27-
import androidx.compose.ui.layout.ContentScale
2823
import androidx.compose.ui.res.painterResource
2924
import androidx.compose.ui.res.stringResource
3025
import androidx.compose.ui.text.input.ImeAction
@@ -58,7 +53,6 @@ import com.bitwarden.ui.platform.manager.IntentManager
5853
import com.bitwarden.ui.platform.resource.BitwardenDrawable
5954
import com.bitwarden.ui.platform.resource.BitwardenString
6055
import com.bitwarden.ui.platform.theme.BitwardenTheme
61-
import com.bitwarden.ui.util.asText
6256
import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.description
6357
import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.title
6458
import com.x8bit.bitwarden.ui.platform.composition.LocalAuthTabLaunchers
@@ -126,19 +120,18 @@ fun TwoFactorLoginScreen(
126120
},
127121
)
128122

129-
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
130-
val title = if (state.isNewDeviceVerification) {
131-
BitwardenString.verify_your_identity.asText()
132-
} else {
133-
state.authMethod.title
134-
}
123+
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
135124
BitwardenScaffold(
136125
modifier = Modifier
137126
.fillMaxSize()
138127
.nestedScroll(scrollBehavior.nestedScrollConnection),
139128
topBar = {
140129
BitwardenTopAppBar(
141-
title = title(),
130+
title = if (state.isNewDeviceVerification) {
131+
stringResource(id = BitwardenString.verify_your_identity)
132+
} else {
133+
state.authMethod.title()
134+
},
142135
scrollBehavior = scrollBehavior,
143136
navigationIcon = rememberVectorPainter(id = BitwardenDrawable.ic_close),
144137
navigationIconContentDescription = stringResource(id = BitwardenString.close),
@@ -230,55 +223,45 @@ private fun TwoFactorLoginScreenContent(
230223
modifier = modifier
231224
.verticalScroll(rememberScrollState()),
232225
) {
233-
if (state.authMethod != TwoFactorAuthMethod.YUBI_KEY) {
234-
state.imageRes?.let {
235-
Spacer(modifier = Modifier.height(12.dp))
236-
Image(
237-
painter = painterResource(id = it),
238-
contentDescription = null,
239-
modifier = Modifier
240-
.standardHorizontalMargin()
241-
.size(124.dp),
242-
)
243-
Spacer(modifier = Modifier.height(12.dp))
244-
}
226+
state.imageRes?.let {
227+
Spacer(modifier = Modifier.height(12.dp))
228+
Image(
229+
painter = painterResource(id = it),
230+
contentDescription = null,
231+
modifier = Modifier
232+
.standardHorizontalMargin()
233+
.size(124.dp),
234+
)
235+
Spacer(modifier = Modifier.height(12.dp))
245236
}
246-
Spacer(modifier = Modifier.height(height = 12.dp))
247-
Text(
248-
text = if (state.isNewDeviceVerification) {
249-
stringResource(BitwardenString.enter_verification_code_new_device)
250-
} else {
251-
state.authMethod.description(
252-
state.displayEmail,
253-
).invoke()
254-
},
255-
textAlign = TextAlign.Center,
256-
style = BitwardenTheme.typography.bodyMedium,
257-
color = BitwardenTheme.colorScheme.text.primary,
258-
modifier = Modifier
259-
.standardHorizontalMargin()
260-
.fillMaxWidth(),
261-
)
262-
263-
Spacer(modifier = Modifier.height(12.dp))
264237

265-
if (state.authMethod == TwoFactorAuthMethod.YUBI_KEY) {
266-
state.imageRes?.let {
267-
Spacer(modifier = Modifier.height(12.dp))
268-
Image(
269-
painter = painterResource(id = it),
270-
contentDescription = null,
271-
alignment = Alignment.Center,
272-
contentScale = ContentScale.FillWidth,
238+
if (state.isNewDeviceVerification) {
239+
Spacer(modifier = Modifier.height(height = 12.dp))
240+
Text(
241+
text = stringResource(id = BitwardenString.enter_verification_code_new_device),
242+
textAlign = TextAlign.Center,
243+
style = BitwardenTheme.typography.bodyMedium,
244+
color = BitwardenTheme.colorScheme.text.primary,
245+
modifier = Modifier
246+
.standardHorizontalMargin()
247+
.fillMaxWidth(),
248+
)
249+
} else {
250+
state.authMethod.description(email = state.displayEmail)?.let { text ->
251+
Spacer(modifier = Modifier.height(height = 12.dp))
252+
Text(
253+
text = text(),
254+
textAlign = TextAlign.Center,
255+
style = BitwardenTheme.typography.bodyMedium,
256+
color = BitwardenTheme.colorScheme.text.primary,
273257
modifier = Modifier
274-
.padding(horizontal = 24.dp)
275-
.clip(RoundedCornerShape(4.dp))
258+
.standardHorizontalMargin()
276259
.fillMaxWidth(),
277260
)
278-
Spacer(modifier = Modifier.height(24.dp))
279261
}
280262
}
281263

264+
Spacer(modifier = Modifier.height(12.dp))
282265
if (state.shouldShowCodeInput) {
283266
BitwardenPasswordField(
284267
value = state.codeInput,

app/src/main/kotlin/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensions.kt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ val TwoFactorAuthMethod.title: Text
2929
/**
3030
* Get the description for the given auth method.
3131
*/
32-
fun TwoFactorAuthMethod.description(email: String): Text = when (this) {
32+
fun TwoFactorAuthMethod.description(email: String): Text? = when (this) {
3333
TwoFactorAuthMethod.AUTHENTICATOR_APP -> BitwardenString.enter_verification_code_app.asText()
3434
TwoFactorAuthMethod.DUO -> {
3535
BitwardenString.follow_the_steps_from_duo_to_finish_logging_in.asText()
3636
}
37+
3738
TwoFactorAuthMethod.DUO_ORGANIZATION -> {
3839
BitwardenString.duo_two_step_login_is_required_for_your_account
3940
.asText()
@@ -45,8 +46,12 @@ fun TwoFactorAuthMethod.description(email: String): Text = when (this) {
4546
TwoFactorAuthMethod.WEB_AUTH -> {
4647
BitwardenString.continue_to_complete_web_authn_verification.asText()
4748
}
49+
4850
TwoFactorAuthMethod.YUBI_KEY -> BitwardenString.yubi_key_instruction.asText()
49-
else -> "".asText()
51+
TwoFactorAuthMethod.U2F,
52+
TwoFactorAuthMethod.REMEMBER,
53+
TwoFactorAuthMethod.RECOVERY_CODE,
54+
-> null
5055
}
5156

5257
/**
@@ -122,7 +127,7 @@ val TwoFactorAuthMethod.shouldUseNfc: Boolean
122127
@get:DrawableRes
123128
val TwoFactorAuthMethod.imageRes: Int?
124129
get() = when (this) {
125-
TwoFactorAuthMethod.YUBI_KEY -> BitwardenDrawable.img_yubi_key
130+
TwoFactorAuthMethod.YUBI_KEY -> BitwardenDrawable.ill_yubi_key
126131
TwoFactorAuthMethod.EMAIL -> BitwardenDrawable.ill_new_device_verification
127132
TwoFactorAuthMethod.AUTHENTICATOR_APP -> BitwardenDrawable.ill_authenticator
128133
else -> null

app/src/test/kotlin/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensionTest.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ class TwoFactorAuthMethodExtensionTest {
4343
TwoFactorAuthMethod.DUO to
4444
BitwardenString.follow_the_steps_from_duo_to_finish_logging_in.asText(),
4545
TwoFactorAuthMethod.YUBI_KEY to BitwardenString.yubi_key_instruction.asText(),
46-
TwoFactorAuthMethod.U2F to "".asText(),
47-
TwoFactorAuthMethod.REMEMBER to "".asText(),
46+
TwoFactorAuthMethod.U2F to null,
47+
TwoFactorAuthMethod.REMEMBER to null,
4848
TwoFactorAuthMethod.DUO_ORGANIZATION to
4949
BitwardenString.duo_two_step_login_is_required_for_your_account
5050
.asText()
@@ -54,7 +54,7 @@ class TwoFactorAuthMethodExtensionTest {
5454
),
5555
TwoFactorAuthMethod.WEB_AUTH to
5656
BitwardenString.continue_to_complete_web_authn_verification.asText(),
57-
TwoFactorAuthMethod.RECOVERY_CODE to "".asText(),
57+
TwoFactorAuthMethod.RECOVERY_CODE to null,
5858
)
5959
.forEach { (type, title) ->
6060
assertEquals(
@@ -142,7 +142,7 @@ class TwoFactorAuthMethodExtensionTest {
142142
TwoFactorAuthMethod.AUTHENTICATOR_APP to BitwardenDrawable.ill_authenticator,
143143
TwoFactorAuthMethod.EMAIL to BitwardenDrawable.ill_new_device_verification,
144144
TwoFactorAuthMethod.DUO to null,
145-
TwoFactorAuthMethod.YUBI_KEY to BitwardenDrawable.img_yubi_key,
145+
TwoFactorAuthMethod.YUBI_KEY to BitwardenDrawable.ill_yubi_key,
146146
TwoFactorAuthMethod.U2F to null,
147147
TwoFactorAuthMethod.REMEMBER to null,
148148
TwoFactorAuthMethod.DUO_ORGANIZATION to null,
-182 KB
Binary file not shown.
-89.7 KB
Binary file not shown.
-300 KB
Binary file not shown.
-583 KB
Binary file not shown.
-901 KB
Binary file not shown.
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="124dp"
3+
android:height="124dp"
4+
android:viewportWidth="124"
5+
android:viewportHeight="124">
6+
<path
7+
android:name="primary"
8+
android:fillColor="#DBE5F6"
9+
android:pathData="M20.67,23.25C20.67,18.97 24.14,15.5 28.42,15.5H116.25C120.53,15.5 124,18.97 124,23.25V85.25C124,89.53 120.53,93 116.25,93H28.42C24.14,93 20.67,89.53 20.67,85.25V23.25Z" />
10+
<path
11+
android:name="outline"
12+
android:fillColor="#020F66"
13+
android:fillType="evenOdd"
14+
android:pathData="M116.25,18.08H28.42C25.56,18.08 23.25,20.4 23.25,23.25V85.25C23.25,88.1 25.56,90.42 28.42,90.42H116.25C119.1,90.42 121.42,88.1 121.42,85.25V23.25C121.42,20.4 119.1,18.08 116.25,18.08ZM28.42,15.5C24.14,15.5 20.67,18.97 20.67,23.25V85.25C20.67,89.53 24.14,93 28.42,93H116.25C120.53,93 124,89.53 124,85.25V23.25C124,18.97 120.53,15.5 116.25,15.5H28.42Z" />
15+
<path
16+
android:name="secondary"
17+
android:fillColor="#AAC3EF"
18+
android:pathData="M94.29,59.42C94.29,71.54 84.46,81.37 72.33,81.37C60.21,81.37 50.38,71.54 50.38,59.42C50.38,47.29 60.21,37.46 72.33,37.46C84.46,37.46 94.29,47.29 94.29,59.42Z" />
19+
<path
20+
android:name="accent"
21+
android:fillColor="#FFBF00"
22+
android:pathData="M59.42,55.54C59.42,53.4 61.15,51.67 63.29,51.67H81.38C83.52,51.67 85.25,53.4 85.25,55.54V68.46C85.25,70.6 83.52,72.33 81.38,72.33H63.29C61.15,72.33 59.42,70.6 59.42,68.46V55.54Z" />
23+
<path
24+
android:name="outline"
25+
android:fillColor="#020F66"
26+
android:fillType="evenOdd"
27+
android:pathData="M81.38,54.25H63.29C62.58,54.25 62,54.83 62,55.54V68.46C62,69.17 62.58,69.75 63.29,69.75H81.38C82.09,69.75 82.67,69.17 82.67,68.46V55.54C82.67,54.83 82.09,54.25 81.38,54.25ZM63.29,51.67C61.15,51.67 59.42,53.4 59.42,55.54V68.46C59.42,70.6 61.15,72.33 63.29,72.33H81.38C83.52,72.33 85.25,70.6 85.25,68.46V55.54C85.25,53.4 83.52,51.67 81.38,51.67H63.29Z" />
28+
<path
29+
android:name="outline"
30+
android:fillColor="#020F66"
31+
android:pathData="M71.04,59.42C71.04,58.7 71.62,58.13 72.33,58.13C73.05,58.13 73.63,58.7 73.63,59.42V64.58C73.63,65.3 73.05,65.88 72.33,65.88C71.62,65.88 71.04,65.3 71.04,64.58V59.42Z" />
32+
<path
33+
android:name="outline"
34+
android:fillColor="#020F66"
35+
android:fillType="evenOdd"
36+
android:pathData="M65.88,50.38C65.88,46.81 68.77,43.92 72.33,43.92C75.9,43.92 78.79,46.81 78.79,50.38V51.67H76.21V50.38C76.21,48.24 74.47,46.5 72.33,46.5C70.19,46.5 68.46,48.24 68.46,50.38V51.67H65.88V50.38Z" />
37+
<path
38+
android:name="outline"
39+
android:fillColor="#020F66"
40+
android:fillType="evenOdd"
41+
android:pathData="M122.71,31L21.96,31L21.96,28.42L122.71,28.42L122.71,31Z" />
42+
<path
43+
android:name="outline"
44+
android:fillColor="#020F66"
45+
android:pathData="M118.83,23.25C118.83,24.68 117.68,25.83 116.25,25.83C114.82,25.83 113.67,24.68 113.67,23.25C113.67,21.82 114.82,20.67 116.25,20.67C117.68,20.67 118.83,21.82 118.83,23.25Z" />
46+
<path
47+
android:name="outline"
48+
android:fillColor="#020F66"
49+
android:pathData="M111.08,23.25C111.08,24.68 109.93,25.83 108.5,25.83C107.07,25.83 105.92,24.68 105.92,23.25C105.92,21.82 107.07,20.67 108.5,20.67C109.93,20.67 111.08,21.82 111.08,23.25Z" />
50+
<path
51+
android:name="outline"
52+
android:fillColor="#020F66"
53+
android:pathData="M103.33,23.25C103.33,24.68 102.18,25.83 100.75,25.83C99.32,25.83 98.17,24.68 98.17,23.25C98.17,21.82 99.32,20.67 100.75,20.67C102.18,20.67 103.33,21.82 103.33,23.25Z" />
54+
<path
55+
android:name="outline"
56+
android:fillColor="#020F66"
57+
android:pathData="M11.63,40.04C11.63,38.61 12.78,37.46 14.21,37.46H33.58C35.01,37.46 36.17,38.61 36.17,40.04V59.42H11.63V40.04Z" />
58+
<path
59+
android:name="accent"
60+
android:fillColor="#FFBF00"
61+
android:pathData="M15.5,41.33H19.38V55.54H15.5V41.33Z" />
62+
<path
63+
android:name="accent"
64+
android:fillColor="#FFBF00"
65+
android:pathData="M21.96,43.92H25.83V55.54H21.96V43.92Z" />
66+
<path
67+
android:name="accent"
68+
android:fillColor="#FFBF00"
69+
android:pathData="M28.42,41.33H32.29V55.54H28.42V41.33Z" />
70+
<path
71+
android:name="secondary"
72+
android:fillColor="#AAC3EF"
73+
android:fillType="evenOdd"
74+
android:pathData="M10.33,56.83C7.48,56.83 5.17,59.15 5.17,62V113.67C5.17,116.52 7.48,118.83 10.33,118.83H37.46C40.31,118.83 42.63,116.52 42.63,113.67V62C42.63,59.15 40.31,56.83 37.46,56.83H10.33ZM23.9,103.33C25.68,103.33 27.13,104.78 27.13,106.56C27.13,108.35 25.68,109.79 23.9,109.79C22.11,109.79 20.67,108.35 20.67,106.56C20.67,104.78 22.11,103.33 23.9,103.33Z" />
75+
<path
76+
android:name="outline"
77+
android:fillColor="#020F66"
78+
android:fillType="evenOdd"
79+
android:pathData="M10.33,59.42C8.91,59.42 7.75,60.57 7.75,62V113.67C7.75,115.09 8.91,116.25 10.33,116.25H37.46C38.89,116.25 40.04,115.09 40.04,113.67V62C40.04,60.57 38.89,59.42 37.46,59.42H10.33ZM23.9,100.75C27.11,100.75 29.71,103.35 29.71,106.56C29.71,109.77 27.11,112.38 23.9,112.38C20.69,112.38 18.08,109.77 18.08,106.56C18.08,103.35 20.69,100.75 23.9,100.75ZM5.17,62C5.17,59.15 7.48,56.83 10.33,56.83H37.46C40.31,56.83 42.63,59.15 42.63,62V113.67C42.63,116.52 40.31,118.83 37.46,118.83H10.33C7.48,118.83 5.17,116.52 5.17,113.67V62ZM27.13,106.56C27.13,104.78 25.68,103.33 23.9,103.33C22.11,103.33 20.67,104.78 20.67,106.56C20.67,108.35 22.11,109.79 23.9,109.79C25.68,109.79 27.13,108.35 27.13,106.56Z" />
80+
<path
81+
android:name="tertiary"
82+
android:fillColor="#ffffff"
83+
android:fillType="evenOdd"
84+
android:pathData="M23.9,93C29.25,93 33.58,88.66 33.58,83.31C33.58,77.96 29.25,73.63 23.9,73.63C18.55,73.63 14.21,77.96 14.21,83.31C14.21,88.66 18.55,93 23.9,93ZM23.9,95.58C30.67,95.58 36.17,90.09 36.17,83.31C36.17,76.54 30.67,71.04 23.9,71.04C17.12,71.04 11.63,76.54 11.63,83.31C11.63,90.09 17.12,95.58 23.9,95.58Z" />
85+
</vector>

ui/src/main/res/values/strings.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@
179179
<string name="send_verification_code_again">Resend code</string>
180180
<string name="verification_email_not_sent">Could not send verification email. Try again.</string>
181181
<string name="verification_email_sent">Verification email sent</string>
182-
<string name="yubi_key_instruction">To continue, hold your YubiKey NEO against the back of the device or insert your YubiKey into your device’s USB port, then touch its button.</string>
183-
<string name="yubi_key_title">YubiKey security key</string>
182+
<string name="yubi_key_instruction">To continue, hold your Yubico OTP security key against the back of the device or insert it into your device’s USB port, then touch its button.</string>
183+
<string name="yubi_key_title">Yubico security key</string>
184184
<string name="add_new_attachment">Add new attachment</string>
185185
<string name="attachments">Attachments</string>
186186
<string name="unable_to_download_file">Unable to download file.</string>

0 commit comments

Comments
 (0)