feat: Add biometric authentication toggle in ProfileScreen with state management
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user