Remove biometric lock screen
This commit is contained in:
parent
cd65777fec
commit
5e5d178046
@ -19,10 +19,7 @@ data class DeterministicState(
|
||||
val masterPassword: CharArray = CharArray(0),
|
||||
val masterPasswordVisible: Boolean = false,
|
||||
val generatedPassword: String = "",
|
||||
val isLocked: Boolean = false,
|
||||
val clipboardTimerSeconds: Int = 0,
|
||||
val biometricEnabled: Boolean = false,
|
||||
val lockTimeoutMinutes: Int = 5,
|
||||
val showRotateWarning: Boolean = false,
|
||||
val serviceHistory: List<String> = emptyList(),
|
||||
) {
|
||||
@ -34,10 +31,7 @@ data class DeterministicState(
|
||||
masterPassword.contentEquals(other.masterPassword) &&
|
||||
masterPasswordVisible == other.masterPasswordVisible &&
|
||||
generatedPassword == other.generatedPassword &&
|
||||
isLocked == other.isLocked &&
|
||||
clipboardTimerSeconds == other.clipboardTimerSeconds &&
|
||||
biometricEnabled == other.biometricEnabled &&
|
||||
lockTimeoutMinutes == other.lockTimeoutMinutes &&
|
||||
showRotateWarning == other.showRotateWarning &&
|
||||
serviceHistory == other.serviceHistory
|
||||
}
|
||||
@ -47,10 +41,7 @@ data class DeterministicState(
|
||||
result = 31 * result + masterPassword.contentHashCode()
|
||||
result = 31 * result + masterPasswordVisible.hashCode()
|
||||
result = 31 * result + generatedPassword.hashCode()
|
||||
result = 31 * result + isLocked.hashCode()
|
||||
result = 31 * result + clipboardTimerSeconds
|
||||
result = 31 * result + biometricEnabled.hashCode()
|
||||
result = 31 * result + lockTimeoutMinutes
|
||||
result = 31 * result + showRotateWarning.hashCode()
|
||||
result = 31 * result + serviceHistory.hashCode()
|
||||
return result
|
||||
@ -66,18 +57,10 @@ class DeterministicViewModel(app: Application) : AndroidViewModel(app) {
|
||||
private val _state = MutableStateFlow(DeterministicState())
|
||||
val state: StateFlow<DeterministicState> = _state.asStateFlow()
|
||||
|
||||
private val settingsPrefs = app.getSharedPreferences("det_settings", Context.MODE_PRIVATE)
|
||||
|
||||
private var clipboardClearJob: Job? = null
|
||||
|
||||
init {
|
||||
_state.update {
|
||||
it.copy(
|
||||
biometricEnabled = settingsPrefs.getBoolean("biometric_enabled", false),
|
||||
lockTimeoutMinutes = settingsPrefs.getInt("lock_timeout_minutes", 5),
|
||||
serviceHistory = historyRepository.getNames(),
|
||||
)
|
||||
}
|
||||
_state.update { it.copy(serviceHistory = historyRepository.getNames()) }
|
||||
}
|
||||
|
||||
fun updateServiceName(name: String) = _state.update { it.copy(serviceName = name.lowercase()) }
|
||||
@ -143,27 +126,6 @@ class DeterministicViewModel(app: Application) : AndroidViewModel(app) {
|
||||
}
|
||||
}
|
||||
|
||||
fun lock() = _state.update { it.copy(isLocked = true) }
|
||||
|
||||
fun unlock() = _state.update { it.copy(isLocked = false) }
|
||||
|
||||
fun onAppForeground(lastBackgroundTimeMs: Long) {
|
||||
val timeoutMs = _state.value.lockTimeoutMinutes * 60 * 1000L
|
||||
if (timeoutMs > 0 && System.currentTimeMillis() - lastBackgroundTimeMs >= timeoutMs) {
|
||||
lock()
|
||||
}
|
||||
}
|
||||
|
||||
fun setBiometricEnabled(enabled: Boolean) {
|
||||
settingsPrefs.edit().putBoolean("biometric_enabled", enabled).apply()
|
||||
_state.update { it.copy(biometricEnabled = enabled) }
|
||||
}
|
||||
|
||||
fun setLockTimeoutMinutes(minutes: Int) {
|
||||
settingsPrefs.edit().putInt("lock_timeout_minutes", minutes).apply()
|
||||
_state.update { it.copy(lockTimeoutMinutes = minutes) }
|
||||
}
|
||||
|
||||
fun getDeviceSecret(): ByteArray = deviceSecretManager.exportSecret()
|
||||
|
||||
fun importDeviceSecret(secret: ByteArray) = deviceSecretManager.importSecret(secret)
|
||||
|
||||
@ -180,7 +180,6 @@ fun AppNavigation() {
|
||||
popExitTransition = { slideOutHorizontally(tween(300)) { it } },
|
||||
) {
|
||||
SettingsScreen(
|
||||
viewModel = detViewModel,
|
||||
onNavigateBack = { navController.popBackStack() },
|
||||
onNavigateToExportImport = { navController.navigate(ROUTE_EXPORT_IMPORT) },
|
||||
)
|
||||
|
||||
@ -81,10 +81,6 @@ fun DeterministicScreen(
|
||||
val state by viewModel.state.collectAsState()
|
||||
val context = LocalContext.current
|
||||
BackHandler { (context as? android.app.Activity)?.finish() }
|
||||
if (state.isLocked) {
|
||||
LockScreen(viewModel = viewModel)
|
||||
return
|
||||
}
|
||||
|
||||
var showRotateConfirmDialog by remember { mutableStateOf(false) }
|
||||
val masterPasswordFocus = remember { FocusRequester() }
|
||||
|
||||
@ -1,97 +0,0 @@
|
||||
package cz.bugsy.passwordzebra.ui.screens
|
||||
|
||||
import androidx.biometric.BiometricManager
|
||||
import androidx.biometric.BiometricPrompt
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import cz.bugsy.passwordzebra.R
|
||||
import cz.bugsy.passwordzebra.deterministic.DeterministicViewModel
|
||||
|
||||
@Composable
|
||||
fun LockScreen(viewModel: DeterministicViewModel) {
|
||||
val state by viewModel.state.collectAsState()
|
||||
val context = LocalContext.current
|
||||
|
||||
fun launchBiometric() {
|
||||
val activity = context as? FragmentActivity ?: return
|
||||
val executor = ContextCompat.getMainExecutor(context)
|
||||
val prompt = BiometricPrompt(
|
||||
activity,
|
||||
executor,
|
||||
object : BiometricPrompt.AuthenticationCallback() {
|
||||
override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
|
||||
viewModel.unlock()
|
||||
}
|
||||
},
|
||||
)
|
||||
val promptInfo = BiometricPrompt.PromptInfo.Builder()
|
||||
.setTitle(context.getString(R.string.det_biometric_prompt_title))
|
||||
.setSubtitle(context.getString(R.string.det_biometric_prompt_subtitle))
|
||||
.setNegativeButtonText(context.getString(R.string.cancel))
|
||||
.build()
|
||||
prompt.authenticate(promptInfo)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
if (state.biometricEnabled) {
|
||||
launchBiometric()
|
||||
}
|
||||
}
|
||||
|
||||
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(32.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Lock,
|
||||
contentDescription = null,
|
||||
modifier = Modifier.size(64.dp),
|
||||
tint = MaterialTheme.colorScheme.primary,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(24.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.det_locked_title),
|
||||
style = MaterialTheme.typography.headlineMedium,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.det_locked_body),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||
)
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
if (state.biometricEnabled) {
|
||||
Button(onClick = { launchBiometric() }) {
|
||||
Text(stringResource(R.string.det_unlock_biometric))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user