feat: Add biometric authentication toggle in ProfileScreen with state management

This commit is contained in:
2026-01-22 15:00:33 +05:00
parent 1f6fc01a54
commit c7443a7ed7
2 changed files with 103 additions and 150 deletions

View File

@@ -735,7 +735,7 @@ fun UnlockScreen(
onUnlocking = { isUnlocking = it },
onError = { error = it },
onSuccess = { decryptedAccount ->
// Если биометрия доступна и включена, сохраняем пароль
// If biometric is enabled, save password
if (biometricAvailable is BiometricAvailability.Available &&
isBiometricEnabled && activity != null) {
scope.launch {
@@ -750,8 +750,8 @@ fun UnlockScreen(
)
}
},
onError = { /* Игнорируем ошибки при сохранении */ },
onCancel = { /* Пользователь отменил */ }
onError = { /* Ignore save errors */ },
onCancel = { /* User cancelled */ }
)
}
}
@@ -792,149 +792,6 @@ fun UnlockScreen(
Spacer(modifier = Modifier.height(16.dp))
// Кнопка для включения/отключения биометрии (вне AnimatedVisibility)
if (biometricAvailable is BiometricAvailability.Available && activity != null && !isDropdownExpanded) {
// Кнопка входа по биометрии (если биометрия включена и пароль сохранен)
var hasSavedPassword by remember { mutableStateOf(false) }
LaunchedEffect(selectedAccount, isBiometricEnabled) {
hasSavedPassword = if (selectedAccount != null && isBiometricEnabled) {
biometricPrefs.hasEncryptedPassword(selectedAccount!!.publicKey)
} else false
}
if (isBiometricEnabled && hasSavedPassword) {
// Кнопка для входа по биометрии
OutlinedButton(
onClick = {
selectedAccount?.let { account ->
scope.launch {
val encryptedPassword = biometricPrefs.getEncryptedPassword(account.publicKey)
if (encryptedPassword != null) {
biometricManager.decryptPassword(
activity = activity,
encryptedData = encryptedPassword,
onSuccess = { decryptedPassword ->
password = decryptedPassword
scope.launch {
performUnlock(
selectedAccount = selectedAccount,
password = decryptedPassword,
accountManager = accountManager,
onUnlocking = { isUnlocking = it },
onError = { error = it },
onSuccess = { decryptedAccount ->
onUnlocked(decryptedAccount)
}
)
}
},
onError = { errorMessage ->
error = "Ошибка биометрии: $errorMessage"
},
onCancel = { }
)
}
}
}
},
modifier = Modifier.fillMaxWidth().height(56.dp),
shape = RoundedCornerShape(12.dp),
border = BorderStroke(1.dp, PrimaryBlue)
) {
Icon(
imageVector = Icons.Default.Fingerprint,
contentDescription = null,
tint = PrimaryBlue,
modifier = Modifier.size(24.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = "Войти по отпечатку",
color = PrimaryBlue,
fontSize = 16.sp,
fontWeight = FontWeight.SemiBold
)
}
Spacer(modifier = Modifier.height(12.dp))
}
// Переключатель биометрии
Row(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(8.dp))
.clickable {
scope.launch {
if (isBiometricEnabled) {
// Отключаем биометрию
biometricPrefs.disableBiometric()
selectedAccount?.let {
biometricPrefs.removeEncryptedPassword(it.publicKey)
}
isBiometricEnabled = false
} else {
// Включаем биометрию - нужно сохранить пароль
if (password.isNotEmpty()) {
// Сначала проверим пароль
val account = selectedAccount?.encryptedAccount
if (account != null) {
val decryptedPrivateKey = CryptoManager.decryptWithPassword(
account.encryptedPrivateKey,
password
)
if (decryptedPrivateKey != null) {
// Пароль верный, сохраняем через биометрию
biometricManager.encryptPassword(
activity = activity,
password = password,
onSuccess = { encryptedPassword ->
scope.launch {
biometricPrefs.enableBiometric()
biometricPrefs.saveEncryptedPassword(
account.publicKey,
encryptedPassword
)
isBiometricEnabled = true
}
},
onError = { errorMsg ->
error = "Ошибка сохранения: $errorMsg"
},
onCancel = { }
)
} else {
error = "Неверный пароль"
}
}
} else {
error = "Сначала введите пароль"
}
}
}
}
.padding(12.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
Icon(
imageVector = Icons.Default.Fingerprint,
contentDescription = null,
tint = if (isBiometricEnabled) PrimaryBlue else secondaryTextColor,
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = if (isBiometricEnabled) "Биометрия включена" else "Включить биометрию",
color = if (isBiometricEnabled) PrimaryBlue else secondaryTextColor,
fontSize = 14.sp
)
}
Spacer(modifier = Modifier.height(16.dp))
}
// Create New Account button
AnimatedVisibility(
visible = visible && !isDropdownExpanded,