improvement: Move more text phrases to translatable resources #626

This commit is contained in:
Artem Chepurnoy 2024-11-07 10:35:36 +02:00
parent 1402aa2245
commit 77be8e5e0d
No known key found for this signature in database
GPG Key ID: FAC37D0CF674043E
7 changed files with 63 additions and 12 deletions

View File

@ -489,6 +489,7 @@
<string name="error_invalid_uri">Invalid URI</string> <string name="error_invalid_uri">Invalid URI</string>
<string name="error_invalid_card_number">Invalid card number</string> <string name="error_invalid_card_number">Invalid card number</string>
<string name="error_incorrect_password">Incorrect password</string> <string name="error_incorrect_password">Incorrect password</string>
<string name="error_otp_key_must_not_be_empty">One time password's secret key must not be empty</string>
<string name="error_failed_generate_kdf_hash_oom">Failed to create a key, not enough memory. Please check your KDF server settings.</string> <string name="error_failed_generate_kdf_hash_oom">Failed to create a key, not enough memory. Please check your KDF server settings.</string>
<string name="error_failed_generate_otp_code">Failed to generate OTP code</string> <string name="error_failed_generate_otp_code">Failed to generate OTP code</string>
<string name="error_failed_create_passkey">Failed to create a passkey</string> <string name="error_failed_create_passkey">Failed to create a passkey</string>
@ -497,11 +498,16 @@
<string name="error_failed_format_placeholder">Failed to format the placeholder</string> <string name="error_failed_format_placeholder">Failed to format the placeholder</string>
<string name="error_failed_open_app_for">No installed app can handle this request</string> <string name="error_failed_open_app_for">No installed app can handle this request</string>
<string name="error_failed_unknown">Something went wrong</string> <string name="error_failed_unknown">Something went wrong</string>
<string name="error_failed_encrypt_biometric_key">Failed to encrypt the biometric key</string>
<string name="error_failed_decrypt_biometric_key">Failed to decrypt the biometric key</string>
<string name="scanqr_title">Scan QR code</string> <string name="scanqr_title">Scan QR code</string>
<string name="scanqr_load_from_image_note">Load and parse a QR code from an image file.</string> <string name="scanqr_load_from_image_note">Load and parse a QR code from an image file.</string>
<string name="scanqr_camera_permission_required_text">Camera permission is required to scan the QR codes.</string> <string name="scanqr_camera_permission_required_text">Camera permission is required to scan the QR codes.</string>
<string name="post_notifications_permission_banner_title">Notifications are disabled</string>
<string name="post_notifications_permission_banner_text">Grant the notification permission to allow Keyguard to show one-time passwords when autofilling &amp; more.</string>
<!-- Title of the 'Show as Barcode' dialog --> <!-- Title of the 'Show as Barcode' dialog -->
<string name="barcodetype_title">Barcode</string> <string name="barcodetype_title">Barcode</string>
<string name="barcodetype_action_show_in_barcode_title">Show as Barcode</string> <string name="barcodetype_action_show_in_barcode_title">Show as Barcode</string>

View File

@ -0,0 +1,12 @@
package com.artemchep.keyguard.common.exception
import com.artemchep.keyguard.feature.localization.TextHolder
import com.artemchep.keyguard.res.Res
import com.artemchep.keyguard.res.*
class OtpEmptySecretKeyException(
e: Throwable? = null,
) : IllegalArgumentException("One time password's secret key must not be empty", e), Readable {
override val title: TextHolder
get() = TextHolder.Res(Res.string.error_otp_key_must_not_be_empty)
}

View File

@ -0,0 +1,16 @@
package com.artemchep.keyguard.common.exception.crypto
import com.artemchep.keyguard.common.exception.Readable
import com.artemchep.keyguard.feature.localization.TextHolder
import com.artemchep.keyguard.res.Res
import com.artemchep.keyguard.res.*
class BiometricKeyDecryptException(
e: Throwable,
) : RuntimeException("Failed to decrypt the biometric key", e), Readable {
override val title: TextHolder
get() = TextHolder.Res(Res.string.error_failed_decrypt_biometric_key)
override val text: TextHolder?
get() = cause?.message?.let(TextHolder::Value)
}

View File

@ -0,0 +1,16 @@
package com.artemchep.keyguard.common.exception.crypto
import com.artemchep.keyguard.common.exception.Readable
import com.artemchep.keyguard.feature.localization.TextHolder
import com.artemchep.keyguard.res.Res
import com.artemchep.keyguard.res.*
class BiometricKeyEncryptException(
e: Throwable,
) : RuntimeException("Failed to encrypt the biometric key", e), Readable {
override val title: TextHolder
get() = TextHolder.Res(Res.string.error_failed_encrypt_biometric_key)
override val text: TextHolder?
get() = cause?.message?.let(TextHolder::Value)
}

View File

@ -4,6 +4,7 @@ import arrow.core.Either
import arrow.core.Either.Companion.catch import arrow.core.Either.Companion.catch
import arrow.core.flatten import arrow.core.flatten
import arrow.core.right import arrow.core.right
import com.artemchep.keyguard.common.exception.OtpEmptySecretKeyException
import io.ktor.http.Url import io.ktor.http.Url
private const val PREFIX_OTP_AUTH = "otpauth://" private const val PREFIX_OTP_AUTH = "otpauth://"
@ -163,7 +164,7 @@ private fun parseTotpAuth(
} }
if (keyBase32.isBlank()) { if (keyBase32.isBlank()) {
throw IllegalArgumentException("One time password key must not be empty.") throw OtpEmptySecretKeyException()
} }
builder.build( builder.build(
@ -203,7 +204,7 @@ private fun parseHotpAuth(
} }
if (keyBase32.isBlank()) { if (keyBase32.isBlank()) {
throw IllegalArgumentException("One time password key must not be empty.") throw OtpEmptySecretKeyException()
} }
builder.build( builder.build(
@ -266,8 +267,9 @@ private fun parseOtpMobile(
) )
} }
val secret = requireNotNull(params["secret"]) { val secret = params["secret"]
"URI must include the mOTP secret" if (secret.isNullOrBlank()) {
throw OtpEmptySecretKeyException()
} }
val pin = params["pin"] val pin = params["pin"]
TotpToken.MobileAuth( TotpToken.MobileAuth(

View File

@ -5,6 +5,8 @@ import arrow.core.compose
import arrow.core.getOrElse import arrow.core.getOrElse
import arrow.core.memoize import arrow.core.memoize
import arrow.core.partially1 import arrow.core.partially1
import com.artemchep.keyguard.common.exception.crypto.BiometricKeyDecryptException
import com.artemchep.keyguard.common.exception.crypto.BiometricKeyEncryptException
import com.artemchep.keyguard.common.io.IO import com.artemchep.keyguard.common.io.IO
import com.artemchep.keyguard.common.io.attempt import com.artemchep.keyguard.common.io.attempt
import com.artemchep.keyguard.common.io.dispatchOn import com.artemchep.keyguard.common.io.dispatchOn
@ -214,8 +216,7 @@ class UnlockUseCaseImpl(
} }
biometricKeyEncryptUseCase(cipherIo, masterKey) biometricKeyEncryptUseCase(cipherIo, masterKey)
.handleErrorWith { e -> .handleErrorWith { e ->
val newMessage = "Failed to encrypt the biometric key!" val newException = BiometricKeyEncryptException(e)
val newException = IllegalStateException(newMessage, e)
ioRaise(newException) ioRaise(newException)
} }
.flatMap { encryptedMasterKey -> .flatMap { encryptedMasterKey ->
@ -296,8 +297,7 @@ class UnlockUseCaseImpl(
} }
decryptBiometricKeyUseCase(cipherIo, encryptedMasterKey) decryptBiometricKeyUseCase(cipherIo, encryptedMasterKey)
.handleErrorWith { e -> .handleErrorWith { e ->
val newMessage = "Failed to decrypt the biometric key!" val newException = BiometricKeyDecryptException(e)
val newException = IllegalStateException(newMessage, e)
ioRaise(newException) ioRaise(newException)
} }
// Try to unlock the vault using decrypted // Try to unlock the vault using decrypted
@ -396,8 +396,7 @@ class UnlockUseCaseImpl(
} }
biometricKeyEncryptUseCase(cipherIo, newMasterKey) biometricKeyEncryptUseCase(cipherIo, newMasterKey)
.handleErrorWith { e -> .handleErrorWith { e ->
val newMessage = "Failed to encrypt the biometric key!" val newException = BiometricKeyEncryptException(e)
val newException = IllegalStateException(newMessage, e)
ioRaise(newException) ioRaise(newException)
} }
.flatMap { encryptedNewMasterKey -> .flatMap { encryptedNewMasterKey ->

View File

@ -509,8 +509,8 @@ private fun BannerStatusBadge(
.isNotEmpty() -> { .isNotEmpty() -> {
BannerStatusBadgeContentModel( BannerStatusBadgeContentModel(
count = 0, count = 0,
title = TextHolder.Value("Notifications are disabled"), title = TextHolder.Res(Res.string.post_notifications_permission_banner_title),
text = TextHolder.Value("Grant the notification permission to allow Keyguard to show one-time passwords when autofilling & more."), text = TextHolder.Res(Res.string.post_notifications_permission_banner_text),
error = false, error = false,
onClick = { onClick = {
val permission = statusState.value.pendingPermissions val permission = statusState.value.pendingPermissions