mirror of
https://github.com/bitwarden/android.git
synced 2024-10-31 07:05:35 +03:00
PM-13382 show contextual message for the level of Biometrics available (#4099)
This commit is contained in:
parent
1446e43c46
commit
62cfd5e746
8 changed files with 57 additions and 11 deletions
|
@ -161,7 +161,7 @@ private fun SetupUnlockScreenContent(
|
|||
|
||||
Spacer(modifier = Modifier.height(height = 24.dp))
|
||||
BitwardenUnlockWithBiometricsSwitch(
|
||||
isBiometricsSupported = biometricsManager.isBiometricsSupported,
|
||||
biometricSupportStatus = biometricsManager.biometricSupportStatus,
|
||||
isChecked = state.isUnlockWithBiometricsEnabled || showBiometricsPrompt,
|
||||
onDisableBiometrics = handler.onDisableBiometrics,
|
||||
onEnableBiometrics = handler.onEnableBiometrics,
|
||||
|
|
|
@ -4,29 +4,41 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.x8bit.bitwarden.R
|
||||
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricSupportStatus
|
||||
|
||||
/**
|
||||
* Displays a switch for enabling or disabling unlock with biometrics functionality.
|
||||
*
|
||||
* @param isChecked Indicates that the switch should be checked or not.
|
||||
* @param isBiometricsSupported Indicates if biometrics is supported and we should display the
|
||||
* switch.
|
||||
* @param biometricSupportStatus Indicates what type of biometrics are supported on device.
|
||||
* @param onDisableBiometrics Callback invoked when the toggle has be turned off.
|
||||
* @param onEnableBiometrics Callback invoked when the toggle has be turned on.
|
||||
* @param modifier The [Modifier] to be applied to the switch.
|
||||
*/
|
||||
@Composable
|
||||
fun BitwardenUnlockWithBiometricsSwitch(
|
||||
isBiometricsSupported: Boolean,
|
||||
biometricSupportStatus: BiometricSupportStatus,
|
||||
isChecked: Boolean,
|
||||
onDisableBiometrics: () -> Unit,
|
||||
onEnableBiometrics: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
if (!isBiometricsSupported) return
|
||||
val biometricsDescription: String = when (biometricSupportStatus) {
|
||||
BiometricSupportStatus.CLASS_3_SUPPORTED -> {
|
||||
stringResource(R.string.class_3_biometrics_description)
|
||||
}
|
||||
BiometricSupportStatus.CLASS_2_SUPPORTED -> {
|
||||
stringResource(R.string.class_2_biometrics_description)
|
||||
}
|
||||
|
||||
BiometricSupportStatus.NOT_SUPPORTED -> return
|
||||
}
|
||||
BitwardenWideSwitch(
|
||||
modifier = modifier,
|
||||
label = stringResource(id = R.string.unlock_with, stringResource(id = R.string.biometrics)),
|
||||
label = stringResource(
|
||||
id = R.string.unlock_with,
|
||||
stringResource(id = R.string.biometrics),
|
||||
),
|
||||
isChecked = isChecked,
|
||||
onCheckedChange = { toggled ->
|
||||
if (toggled) {
|
||||
|
@ -35,5 +47,7 @@ fun BitwardenUnlockWithBiometricsSwitch(
|
|||
onDisableBiometrics()
|
||||
}
|
||||
},
|
||||
enabled = biometricSupportStatus == BiometricSupportStatus.CLASS_3_SUPPORTED,
|
||||
description = biometricsDescription,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ fun AccountSecurityScreen(
|
|||
.padding(horizontal = 16.dp),
|
||||
)
|
||||
BitwardenUnlockWithBiometricsSwitch(
|
||||
isBiometricsSupported = biometricsManager.isBiometricsSupported,
|
||||
biometricSupportStatus = biometricsManager.biometricSupportStatus,
|
||||
isChecked = state.isUnlockWithBiometricsEnabled || showBiometricsPrompt,
|
||||
onDisableBiometrics = remember(viewModel) {
|
||||
{
|
||||
|
|
|
@ -9,7 +9,8 @@ import javax.crypto.Cipher
|
|||
@Immutable
|
||||
interface BiometricsManager {
|
||||
/**
|
||||
* Returns `true` if the device supports string biometric authentication, `false` otherwise.
|
||||
* Returns `true` if the device supports Class 3 (STRONG) biometric authentication, `false`
|
||||
* otherwise.
|
||||
*/
|
||||
val isBiometricsSupported: Boolean
|
||||
|
||||
|
@ -19,6 +20,11 @@ interface BiometricsManager {
|
|||
*/
|
||||
val isUserVerificationSupported: Boolean
|
||||
|
||||
/**
|
||||
* Returns the status of biometric support available on the device.
|
||||
*/
|
||||
val biometricSupportStatus: BiometricSupportStatus
|
||||
|
||||
/**
|
||||
* Display a prompt for setting up or verifying biometrics.
|
||||
*/
|
||||
|
@ -49,3 +55,12 @@ interface BiometricsManager {
|
|||
onNotSupported: () -> Unit,
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Status of biometric support available on the device.
|
||||
*/
|
||||
enum class BiometricSupportStatus {
|
||||
CLASS_3_SUPPORTED,
|
||||
CLASS_2_SUPPORTED,
|
||||
NOT_SUPPORTED,
|
||||
}
|
||||
|
|
|
@ -22,13 +22,26 @@ class BiometricsManagerImpl(
|
|||
private val fragmentActivity: FragmentActivity get() = activity as FragmentActivity
|
||||
|
||||
override val isBiometricsSupported: Boolean
|
||||
get() = canAuthenticate(Authenticators.BIOMETRIC_STRONG)
|
||||
get() = biometricSupportStatus == BiometricSupportStatus.CLASS_3_SUPPORTED
|
||||
|
||||
override val isUserVerificationSupported: Boolean
|
||||
get() = canAuthenticate(
|
||||
authenticators = Authenticators.BIOMETRIC_STRONG or Authenticators.DEVICE_CREDENTIAL,
|
||||
)
|
||||
|
||||
override val biometricSupportStatus: BiometricSupportStatus
|
||||
get() = when {
|
||||
canAuthenticate(Authenticators.BIOMETRIC_STRONG) -> {
|
||||
BiometricSupportStatus.CLASS_3_SUPPORTED
|
||||
}
|
||||
|
||||
canAuthenticate(Authenticators.BIOMETRIC_WEAK) -> {
|
||||
BiometricSupportStatus.CLASS_2_SUPPORTED
|
||||
}
|
||||
|
||||
else -> BiometricSupportStatus.NOT_SUPPORTED
|
||||
}
|
||||
|
||||
override fun promptBiometrics(
|
||||
onSuccess: (cipher: Cipher?) -> Unit,
|
||||
onCancel: () -> Unit,
|
||||
|
|
|
@ -1028,4 +1028,6 @@ Do you want to switch to this account?</string>
|
|||
<string name="import_logins">Import Logins</string>
|
||||
<string name="from_your_computer_follow_these_instructions_to_export_saved_passwords">From your computer, follow these instructions to export saved passwords from your browser or other password manager. Then, safely import them to Bitwarden.</string>
|
||||
<string name="give_your_vault_a_head_start">Give your vault a head start</string>
|
||||
<string name="class_3_biometrics_description">Unlock with biometrics requires strong biometric authentication and may not be compatible with all biometric options on this device.</string>
|
||||
<string name="class_2_biometrics_description">Unlock with biometrics requires strong biometric authentication and is not compatible with the biometrics options available on this device.</string>
|
||||
</resources>
|
||||
|
|
|
@ -17,6 +17,7 @@ import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFl
|
|||
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import com.x8bit.bitwarden.ui.platform.components.toggle.UnlockWithPinState
|
||||
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricSupportStatus
|
||||
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManager
|
||||
import com.x8bit.bitwarden.ui.util.assertNoDialogExists
|
||||
import io.mockk.every
|
||||
|
@ -40,7 +41,7 @@ class SetupUnlockScreenTest : BaseComposeTest() {
|
|||
private val captureBiometricsLockOut = slot<() -> Unit>()
|
||||
private val captureBiometricsError = slot<() -> Unit>()
|
||||
private val biometricsManager: BiometricsManager = mockk {
|
||||
every { isBiometricsSupported } returns true
|
||||
every { biometricSupportStatus } returns BiometricSupportStatus.CLASS_3_SUPPORTED
|
||||
every {
|
||||
promptBiometrics(
|
||||
onSuccess = capture(captureBiometricsSuccess),
|
||||
|
|
|
@ -26,6 +26,7 @@ import com.x8bit.bitwarden.data.platform.repository.util.bufferedMutableSharedFl
|
|||
import com.x8bit.bitwarden.ui.platform.base.BaseComposeTest
|
||||
import com.x8bit.bitwarden.ui.platform.base.util.asText
|
||||
import com.x8bit.bitwarden.ui.platform.components.toggle.UnlockWithPinState
|
||||
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricSupportStatus
|
||||
import com.x8bit.bitwarden.ui.platform.manager.biometrics.BiometricsManager
|
||||
import com.x8bit.bitwarden.ui.platform.manager.intent.IntentManager
|
||||
import com.x8bit.bitwarden.ui.util.assertNoDialogExists
|
||||
|
@ -60,7 +61,7 @@ class AccountSecurityScreenTest : BaseComposeTest() {
|
|||
private val captureBiometricsLockOut = slot<() -> Unit>()
|
||||
private val captureBiometricsError = slot<() -> Unit>()
|
||||
private val biometricsManager: BiometricsManager = mockk {
|
||||
every { isBiometricsSupported } returns true
|
||||
every { biometricSupportStatus } returns BiometricSupportStatus.CLASS_3_SUPPORTED
|
||||
every {
|
||||
promptBiometrics(
|
||||
onSuccess = capture(captureBiometricsSuccess),
|
||||
|
|
Loading…
Reference in a new issue