diff --git a/core/designsystem/src/main/java/com/twofasapp/designsystem/dialog/PasswordDialog.kt b/core/designsystem/src/main/java/com/twofasapp/designsystem/dialog/PasswordDialog.kt index 24e6773e..1fe0aaeb 100644 --- a/core/designsystem/src/main/java/com/twofasapp/designsystem/dialog/PasswordDialog.kt +++ b/core/designsystem/src/main/java/com/twofasapp/designsystem/dialog/PasswordDialog.kt @@ -22,6 +22,13 @@ import com.twofasapp.designsystem.common.TwOutlinedTextFieldPassword import com.twofasapp.locale.TwLocale import kotlinx.coroutines.android.awaitFrame +sealed class ValidationState { + object Valid : ValidationState() + data class LengthError(val message: String) : ValidationState() + data class ConfirmError(val message: String) : ValidationState() + data class ValidationError(val message: String) : ValidationState() +} + @Composable fun PasswordDialog( onDismissRequest: () -> Unit, @@ -36,6 +43,7 @@ fun PasswordDialog( onPositive: ((String) -> Unit)? = null, onNegative: (() -> Unit)? = null, validation: ((String) -> Boolean)? = null, + validationHint: String? = null, keyboardOptions: KeyboardOptions = KeyboardOptions.Default, minLength: Int = 3, maxLength: Int = Int.MAX_VALUE, @@ -45,6 +53,24 @@ fun PasswordDialog( var password by remember { mutableStateOf("") } var passwordConfirm by remember { mutableStateOf("") } + val validationState by remember { + derivedStateOf { + when { + password.trim().length !in minLength..maxLength -> + ValidationState.LengthError( + TwLocale.strings.backupPasswordLengthError.format(minLength, maxLength) + ) + confirmRequired && password != passwordConfirm -> + ValidationState.ConfirmError(TwLocale.strings.backupPasswordConfirmError) + validation != null && !validation.invoke(password) -> + ValidationState.ValidationError( + validationHint ?: TwLocale.strings.backupPasswordValidationError + ) + else -> ValidationState.Valid + } + } + } + val positiveEnabledState by remember { derivedStateOf { when { @@ -79,11 +105,16 @@ fun PasswordDialog( .padding(horizontal = DialogPadding) .focusRequester(focusRequester), labelText = TwLocale.strings.password, - isError = error.isNullOrBlank().not(), + isError = validationState !is ValidationState.Valid, keyboardOptions = keyboardOptions, maxLines = 1, enabled = enabled, - supportingText = if (error.isNullOrBlank()) null else error, + supportingText = when (validationState) { + is ValidationState.LengthError -> validationState.message + is ValidationState.ValidationError -> validationState.message + ValidationState.Valid -> null + else -> null + }, ) if (confirmRequired) { @@ -94,10 +125,14 @@ fun PasswordDialog( modifier = Modifier .padding(horizontal = DialogPadding), labelText = TwLocale.strings.passwordConfirm, - isError = error.isNullOrBlank().not(), + isError = validationState is ValidationState.ConfirmError, keyboardOptions = keyboardOptions, maxLines = 1, enabled = enabled, + supportingText = when (validationState) { + is ValidationState.ConfirmError -> validationState.message + else -> null + }, ) } @@ -119,4 +154,4 @@ private fun Preview() { title = "Password", body = TwLocale.strings.placeholderMedium, ) -} \ No newline at end of file +} diff --git a/core/locale/src/main/java/com/twofasapp/locale/Strings.kt b/core/locale/src/main/java/com/twofasapp/locale/Strings.kt index 82203495..49519917 100644 --- a/core/locale/src/main/java/com/twofasapp/locale/Strings.kt +++ b/core/locale/src/main/java/com/twofasapp/locale/Strings.kt @@ -291,6 +291,10 @@ class Strings(c: Context) { val backupSetPasswordDescription = c.getString(R.string.backup__set_password_title) val backupEnterPassword = c.getString(R.string.backup__enter_password_dialog_title) val backupEnterPasswordDescription = c.getString(R.string.backup__enter_password_title) + val backupPasswordLengthError = c.getString(R.string.backup__password_length_error) + val backupPasswordConfirmError = c.getString(R.string.backup__password_confirm_error) + val backupPasswordValidationError = c.getString(R.string.backup__password_validation_error) + val backupPasswordValidationHint = c.getString(R.string.backup__password_validation_hint) val backupShareError = c.getString(R.string.backup__share_result_failure) val backupDownloadError = c.getString(R.string.commons__unknown_error) val backupDownloadSuccess = c.getString(R.string.backup__export_result_success) @@ -354,4 +358,4 @@ class Strings(c: Context) { val widgetSelectMsg = c.getString(R.string.widgets_select_msg) val widgetNoServices = c.getString(R.string.widgets_empty_msg) -} \ No newline at end of file +} diff --git a/core/locale/src/main/res/values-de-rDE/strings.xml b/core/locale/src/main/res/values-de-rDE/strings.xml index 22c0c1c4..d087b122 100644 --- a/core/locale/src/main/res/values-de-rDE/strings.xml +++ b/core/locale/src/main/res/values-de-rDE/strings.xml @@ -361,6 +361,11 @@ Um den Schutz deiner Sicherungsdatei zu erhöhen, lege bitte das Passwort fest Gib ein Passwort für diese Sicherungsdatei ein, um mit dem Importvorgang fortzufahren Ein Passwort für diese Sicherungsdatei festlegen + + Das Passwort muss zwischen %1$d und %2$d Zeichen lang sein + Die Passwörter stimmen nicht überein + Das Passwort enthält ungültige Zeichen + Das Passwort darf nur Buchstaben, Zahlen und diese Symbole enthalten: _/!#$%&+*~@?=^.,(){}[]<>|- Falsches Passwort %d neue Dienste diff --git a/core/locale/src/main/res/values-es-rES/strings.xml b/core/locale/src/main/res/values-es-rES/strings.xml index aa0e9bab..ca448213 100644 --- a/core/locale/src/main/res/values-es-rES/strings.xml +++ b/core/locale/src/main/res/values-es-rES/strings.xml @@ -361,6 +361,11 @@ Para aumentar la protección de su archivo de copia de seguridad, establezca una contraseña. Escriba una contraseña para este archivo de copia de seguridad para continuar con el proceso de importación Establecer una contraseña para este archivo de copia de seguridad + + La contraseña debe tener entre %1$d y %2$d caracteres + Las contraseñas no coinciden + La contraseña contiene caracteres no válidos + La contraseña solo puede contener letras, números y estos símbolos: _/!#$%&+*~@?=^.,(){}[]<>|- Contraseña incorrecta %d nuevos servicios diff --git a/core/locale/src/main/res/values-fr-rFR/strings.xml b/core/locale/src/main/res/values-fr-rFR/strings.xml index 9a23c053..b43f39fb 100644 --- a/core/locale/src/main/res/values-fr-rFR/strings.xml +++ b/core/locale/src/main/res/values-fr-rFR/strings.xml @@ -361,6 +361,11 @@ Pour renforcer la protection de votre fichier de sauvegarde, veuillez définir un mot de passe. Saisissez un mot de passe pour ce fichier de sauvegarde afin de poursuivre le processus d\'importation Définir un mot de passe pour le fichier de sauvegarde + + Le mot de passe doit contenir entre %1$d et %2$d caractères + Les mots de passe ne correspondent pas + Le mot de passe contient des caractères non valides + Le mot de passe ne peut contenir que des lettres, des chiffres et ces symboles : _/!#$%&+*~@?=^.,(){}[]<>|- Mot de passe incorrect %d nouveaux services diff --git a/core/locale/src/main/res/values-it-rIT/strings.xml b/core/locale/src/main/res/values-it-rIT/strings.xml index 260105d8..3ef70904 100644 --- a/core/locale/src/main/res/values-it-rIT/strings.xml +++ b/core/locale/src/main/res/values-it-rIT/strings.xml @@ -361,6 +361,11 @@ Per aumentare la protezione del tuo file di backup imposta la password Digita la password per questo file di backup per procedere con il processo di importazione Imposta una password per questo file di backup + + La password deve essere compresa tra %1$d e %2$d caratteri + Le password non corrispondono + La password contiene caratteri non validi + La password può contenere solo lettere, numeri e i simboli: _/!#$%&+*~@?=^.,(){}[]<>|- Password errata %d nuovi servizi diff --git a/core/locale/src/main/res/values/strings.xml b/core/locale/src/main/res/values/strings.xml index b9d61c32..55cacb8f 100644 --- a/core/locale/src/main/res/values/strings.xml +++ b/core/locale/src/main/res/values/strings.xml @@ -361,6 +361,11 @@ To increase the protection of your backup file, please set the password Type in a password for this backup file to proceed with the import process Set a password for this backup file + + Password must be between %1$d and %2$d characters + Passwords don\'t match + Password contains invalid characters + Password can only contain letters, numbers, and these symbols: _/!#$%&+*~@?=^.,(){}[]<>|- Incorrect Password %d new services diff --git a/feature/backup/src/main/java/com/twofasapp/feature/backup/ui/export/BackupExportScreen.kt b/feature/backup/src/main/java/com/twofasapp/feature/backup/ui/export/BackupExportScreen.kt index 113951a0..2976e59a 100644 --- a/feature/backup/src/main/java/com/twofasapp/feature/backup/ui/export/BackupExportScreen.kt +++ b/feature/backup/src/main/java/com/twofasapp/feature/backup/ui/export/BackupExportScreen.kt @@ -204,6 +204,7 @@ private fun ScreenContent( title = TwLocale.strings.backupSetPassword, body = TwLocale.strings.backupSetPasswordDescription, validation = { text -> ExportPasswordRegex.matches(text) }, + validationHint = TwLocale.strings.backupPasswordValidationHint, onPositive = { onPasswordConfirm(it) @@ -263,4 +264,4 @@ private fun Preview() { ScreenContent( uiState = BackupExportUiState(), ) -} \ No newline at end of file +}