From 7f5271a86bb6ef001ee8a783f639575cc1c67ca6 Mon Sep 17 00:00:00 2001 From: Pavel Baksy Date: Fri, 6 Mar 2026 19:00:03 +0100 Subject: [PATCH] Generator: add Settings button; vault: lowercase service name; tweak rotate label --- .../deterministic/DeterministicViewModel.kt | 4 +- .../ui/screens/WordGeneratorScreen.kt | 50 +++++++++++++++++-- app/src/main/res/values-cs/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 4 files changed, 50 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/cz/bugsy/passwordzebra/deterministic/DeterministicViewModel.kt b/app/src/main/java/cz/bugsy/passwordzebra/deterministic/DeterministicViewModel.kt index cd03b42..c2031a6 100644 --- a/app/src/main/java/cz/bugsy/passwordzebra/deterministic/DeterministicViewModel.kt +++ b/app/src/main/java/cz/bugsy/passwordzebra/deterministic/DeterministicViewModel.kt @@ -80,14 +80,14 @@ class DeterministicViewModel(app: Application) : AndroidViewModel(app) { } } - fun updateServiceName(name: String) = _state.update { it.copy(serviceName = name) } + fun updateServiceName(name: String) = _state.update { it.copy(serviceName = name.lowercase()) } fun updateMasterPassword(pw: CharArray) = _state.update { it.copy(masterPassword = pw) } fun toggleMasterPasswordVisible() = _state.update { it.copy(masterPasswordVisible = !it.masterPasswordVisible) } - fun selectService(name: String) = _state.update { it.copy(serviceName = name) } + fun selectService(name: String) = _state.update { it.copy(serviceName = name.lowercase()) } fun generate() { val s = _state.value diff --git a/app/src/main/java/cz/bugsy/passwordzebra/ui/screens/WordGeneratorScreen.kt b/app/src/main/java/cz/bugsy/passwordzebra/ui/screens/WordGeneratorScreen.kt index 998b4b3..b3afbc4 100644 --- a/app/src/main/java/cz/bugsy/passwordzebra/ui/screens/WordGeneratorScreen.kt +++ b/app/src/main/java/cz/bugsy/passwordzebra/ui/screens/WordGeneratorScreen.kt @@ -20,7 +20,10 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.FilledIconButton +import androidx.compose.material3.FilledTonalIconButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold @@ -47,7 +50,7 @@ import cz.bugsy.passwordzebra.R import cz.bugsy.passwordzebra.ui.components.NumberPickerView @Composable -fun WordGeneratorScreen() { +fun WordGeneratorScreen(onNavigateToSettings: () -> Unit) { var password by rememberSaveable { mutableStateOf("") } var wordCount by rememberSaveable { mutableIntStateOf(4) } var withoutSpaces by rememberSaveable { mutableStateOf(false) } @@ -104,7 +107,26 @@ fun WordGeneratorScreen() { .weight(1f), ) Spacer(modifier = Modifier.height(12.dp)) - GenerateButton(onClick = onGenerate) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + Spacer(modifier = Modifier.size(48.dp)) + Spacer(modifier = Modifier.width(20.dp)) + GenerateButton(onClick = onGenerate) + Spacer(modifier = Modifier.width(20.dp)) + FilledTonalIconButton( + onClick = onNavigateToSettings, + modifier = Modifier.size(48.dp), + shape = RoundedCornerShape(16.dp), + ) { + Icon( + imageVector = Icons.Default.Settings, + contentDescription = stringResource(R.string.det_settings), + ) + } + } } } } else { @@ -134,8 +156,28 @@ fun WordGeneratorScreen() { modifier = Modifier.fillMaxWidth(), ) Spacer(modifier = Modifier.weight(3f)) - GenerateButton(onClick = onGenerate) - Spacer(modifier = Modifier.height(16.dp)) + Row( + modifier = Modifier + .fillMaxWidth() + .padding(start = 16.dp, top = 14.dp, end = 16.dp, bottom = 16.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically, + ) { + Spacer(modifier = Modifier.size(48.dp)) + Spacer(modifier = Modifier.width(20.dp)) + GenerateButton(onClick = onGenerate) + Spacer(modifier = Modifier.width(20.dp)) + FilledTonalIconButton( + onClick = onNavigateToSettings, + modifier = Modifier.size(48.dp), + shape = RoundedCornerShape(16.dp), + ) { + Icon( + imageVector = Icons.Default.Settings, + contentDescription = stringResource(R.string.det_settings), + ) + } + } } } } diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index a4e808d..c55725d 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -32,7 +32,7 @@ Pro tuto službu bylo vygenerováno nové heslo.\n\nVáš záložní QR kód tuto rotaci nezachycuje. Pokud ztratíte zařízení bez aktualizace QR kódu, TOTO HESLO BUDE TRVALE ZTRACENO — žádným jiným způsobem ho nelze obnovit.\n\nOstatní hesla nejsou dotčena. Aktualizovat QR zálohu nyní Udělám to později (riskantní) - Bylo heslo kompromitováno? Rotovat! + Bylo heslo kompromitováno? Rotovat heslo? Tato akce zvýší čítač pro tuto službu. Předchozí heslo již nebude generováno. Rotovat diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index aef3fe7..5f9b9dc 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -31,7 +31,7 @@ A new password has been generated for this service.\n\nYour QR backup no longer reflects this rotation. If you lose this device without updating the QR code, THIS PASSWORD WILL BE PERMANENTLY LOST — it cannot be recovered any other way.\n\nYour other passwords are not affected. Update QR Backup Now I\'ll do it later (risky) - Password compromised? Rotate! + Password compromised? Rotate password? This will increment the counter for this service. The previous password will no longer be generated. Rotate