diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt index 2b9e5d99e3..ba2f6e3659 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginScreen.kt @@ -1,6 +1,7 @@ package com.x8bit.bitwarden.ui.auth.feature.twofactorlogin import android.widget.Toast +import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -9,6 +10,7 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding 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.MaterialTheme @@ -20,7 +22,9 @@ import androidx.compose.runtime.getValue 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.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -223,6 +227,21 @@ private fun TwoFactorLoginScreenContent( Spacer(modifier = Modifier.height(12.dp)) + state.imageRes?.let { + Spacer(modifier = Modifier.height(12.dp)) + Image( + painter = painterResource(id = it), + contentDescription = null, + alignment = Alignment.Center, + contentScale = ContentScale.FillWidth, + modifier = Modifier + .padding(horizontal = 24.dp) + .clip(RoundedCornerShape(4.dp)) + .fillMaxWidth(), + ) + Spacer(modifier = Modifier.height(24.dp)) + } + if (state.shouldShowCodeInput) { BitwardenPasswordField( value = state.codeInput, diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginViewModel.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginViewModel.kt index 6ffbcfd9da..134d27071d 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginViewModel.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/TwoFactorLoginViewModel.kt @@ -2,6 +2,7 @@ package com.x8bit.bitwarden.ui.auth.feature.twofactorlogin import android.net.Uri import android.os.Parcelable +import androidx.annotation.DrawableRes import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.viewModelScope import com.x8bit.bitwarden.R @@ -18,6 +19,7 @@ import com.x8bit.bitwarden.data.auth.repository.util.CaptchaCallbackTokenResult import com.x8bit.bitwarden.data.auth.repository.util.DuoCallbackTokenResult import com.x8bit.bitwarden.data.auth.repository.util.generateUriForCaptcha import com.x8bit.bitwarden.data.auth.util.YubiKeyResult +import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.imageRes import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.isDuo import com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util.shouldUseNfc import com.x8bit.bitwarden.ui.platform.base.BaseViewModel @@ -447,6 +449,12 @@ data class TwoFactorLoginState( */ val shouldShowCodeInput: Boolean get() = !authMethod.isDuo + /** + * The image to display for the given the [authMethod]. + */ + @get:DrawableRes + val imageRes: Int? get() = authMethod.imageRes + /** * Represents the current state of any dialogs on the screen. */ diff --git a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensions.kt b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensions.kt index c27e3adb67..b7e6d3aa3b 100644 --- a/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensions.kt +++ b/app/src/main/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensions.kt @@ -1,5 +1,6 @@ package com.x8bit.bitwarden.ui.auth.feature.twofactorlogin.util +import androidx.annotation.DrawableRes import com.x8bit.bitwarden.R import com.x8bit.bitwarden.data.auth.datasource.network.model.TwoFactorAuthMethod import com.x8bit.bitwarden.ui.platform.base.util.Text @@ -56,3 +57,13 @@ val TwoFactorAuthMethod.shouldUseNfc: Boolean TwoFactorAuthMethod.YUBI_KEY -> true else -> false } + +/** + * Gets a drawable resource for the image to be displayed or `null` if nothing should be displayed. + */ +@get:DrawableRes +val TwoFactorAuthMethod.imageRes: Int? + get() = when (this) { + TwoFactorAuthMethod.YUBI_KEY -> R.drawable.yubi_key + else -> null + } diff --git a/app/src/main/res/drawable-hdpi/yubi_key.png b/app/src/main/res/drawable-hdpi/yubi_key.png new file mode 100644 index 0000000000..ca8936de15 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/yubi_key.png differ diff --git a/app/src/main/res/drawable-mdpi/yubi_key.png b/app/src/main/res/drawable-mdpi/yubi_key.png new file mode 100644 index 0000000000..ec44159a70 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/yubi_key.png differ diff --git a/app/src/main/res/drawable-xhdpi/yubi_key.png b/app/src/main/res/drawable-xhdpi/yubi_key.png new file mode 100644 index 0000000000..a69444039e Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/yubi_key.png differ diff --git a/app/src/main/res/drawable-xxhdpi/yubi_key.png b/app/src/main/res/drawable-xxhdpi/yubi_key.png new file mode 100644 index 0000000000..fa02ce2c9b Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/yubi_key.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/yubi_key.png b/app/src/main/res/drawable-xxxhdpi/yubi_key.png new file mode 100644 index 0000000000..cb1776b3a5 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/yubi_key.png differ diff --git a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensionTest.kt b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensionTest.kt index f8e24ca81c..16b8b4e4fb 100644 --- a/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensionTest.kt +++ b/app/src/test/java/com/x8bit/bitwarden/ui/auth/feature/twofactorlogin/util/TwoFactorAuthMethodExtensionTest.kt @@ -93,4 +93,22 @@ class TwoFactorAuthMethodExtensionTest { assertEquals(shouldUseNfc, type.shouldUseNfc) } } + + @Test + fun `imageRes returns the expected value`() { + mapOf( + TwoFactorAuthMethod.AUTHENTICATOR_APP to null, + TwoFactorAuthMethod.EMAIL to null, + TwoFactorAuthMethod.DUO to null, + TwoFactorAuthMethod.YUBI_KEY to R.drawable.yubi_key, + TwoFactorAuthMethod.U2F to null, + TwoFactorAuthMethod.REMEMBER to null, + TwoFactorAuthMethod.DUO_ORGANIZATION to null, + TwoFactorAuthMethod.FIDO_2_WEB_APP to null, + TwoFactorAuthMethod.RECOVERY_CODE to null, + ) + .forEach { (type, imageRes) -> + assertEquals(imageRes, type.imageRes) + } + } }