improvement: Move more text phrases to translatable resources #626
This commit is contained in:
parent
1402aa2245
commit
77be8e5e0d
|
@ -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 & 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>
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
|
@ -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(
|
||||||
|
|
|
@ -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 ->
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue