From 75e24ff7d51e1d45283d22a91370243a5a1ff387 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Tue, 25 Mar 2025 10:54:18 -0400 Subject: [PATCH] Add and use special monospace typeface for AEP. --- .../main/assets/fonts/MonoSpecial-Regular.otf | Bin 0 -> 7168 bytes .../MessageBackupsKeyRecordScreen.kt | 8 +++--- .../MessageBackupsKeyVerifyScreen.kt | 5 ++-- .../securesms/fonts/MonoTypeface.kt | 24 ++++++++++++++++++ .../ui/restore/EnterBackupKeyScreen.kt | 9 +++---- 5 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 app/src/main/assets/fonts/MonoSpecial-Regular.otf create mode 100644 app/src/main/java/org/thoughtcrime/securesms/fonts/MonoTypeface.kt diff --git a/app/src/main/assets/fonts/MonoSpecial-Regular.otf b/app/src/main/assets/fonts/MonoSpecial-Regular.otf new file mode 100644 index 0000000000000000000000000000000000000000..314b20f5a80e257d2ef578ea14cc6afb539725ba GIT binary patch literal 7168 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 D=kkos literal 0 HcmV?d00001 diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt index 5a2a66b174..ba17c38ec3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt @@ -25,7 +25,6 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp @@ -36,8 +35,7 @@ import org.signal.core.ui.compose.Scaffolds import org.signal.core.ui.compose.SignalPreview import org.signal.core.ui.compose.theme.SignalTheme import org.thoughtcrime.securesms.R -import kotlin.random.Random -import kotlin.random.nextInt +import org.thoughtcrime.securesms.fonts.MonoTypeface import org.signal.core.ui.R as CoreUiR /** @@ -120,7 +118,7 @@ fun MessageBackupsKeyRecordScreen( letterSpacing = 1.44.sp, lineHeight = 36.sp, textAlign = TextAlign.Center, - fontFamily = FontFamily.Monospace + fontFamily = MonoTypeface.fontFamily() ) ) } @@ -160,7 +158,7 @@ fun MessageBackupsKeyRecordScreen( private fun MessageBackupsKeyRecordScreenPreview() { Previews.Preview { MessageBackupsKeyRecordScreen( - backupKey = (0 until 64).map { Random.nextInt(97..122).toChar() }.joinToString("") + backupKey = (0 until 63).map { (('A'..'Z') + ('0'..'9')).random() }.joinToString("") + "0" ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyVerifyScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyVerifyScreen.kt index c3ad84f053..fff4f4d8cd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyVerifyScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyVerifyScreen.kt @@ -5,7 +5,6 @@ package org.thoughtcrime.securesms.backup.v2.ui.subscription -import android.graphics.Typeface import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column @@ -48,7 +47,6 @@ import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.dimensionResource import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardType @@ -63,6 +61,7 @@ import org.signal.core.ui.compose.Scaffolds import org.signal.core.ui.compose.SignalPreview import org.signal.core.ui.compose.horizontalGutters import org.thoughtcrime.securesms.R +import org.thoughtcrime.securesms.fonts.MonoTypeface import org.thoughtcrime.securesms.registrationv3.ui.restore.BackupKeyVisualTransformation import org.thoughtcrime.securesms.registrationv3.ui.restore.attachBackupKeyAutoFillHelper import org.thoughtcrime.securesms.registrationv3.ui.restore.backupKeyAutoFillHelper @@ -141,7 +140,7 @@ fun MessageBackupsKeyVerifyScreen( Text(text = stringResource(id = R.string.MessageBackupsKeyVerifyScreen__backup_key)) }, textStyle = LocalTextStyle.current.copy( - fontFamily = FontFamily(typeface = Typeface.MONOSPACE), + fontFamily = MonoTypeface.fontFamily(), lineHeight = 36.sp ), keyboardOptions = KeyboardOptions( diff --git a/app/src/main/java/org/thoughtcrime/securesms/fonts/MonoTypeface.kt b/app/src/main/java/org/thoughtcrime/securesms/fonts/MonoTypeface.kt new file mode 100644 index 0000000000..3dda687067 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/fonts/MonoTypeface.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2025 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.fonts + +import android.graphics.Typeface +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.text.font.FontFamily + +/** + * Special monospace font, primarily used for rendering AEPs. + */ +object MonoTypeface { + private var cached: Typeface? = null + + @Composable + fun fontFamily(): FontFamily { + val context = LocalContext.current + return FontFamily(cached ?: Typeface.createFromAsset(context.assets, "fonts/MonoSpecial-Regular.otf").also { cached = it }) + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyScreen.kt index 2f793d496d..4d4018481c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/registrationv3/ui/restore/EnterBackupKeyScreen.kt @@ -5,7 +5,6 @@ package org.thoughtcrime.securesms.registrationv3.ui.restore -import android.graphics.Typeface import androidx.compose.animation.AnimatedContent import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -43,7 +42,6 @@ import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalSoftwareKeyboardController import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.text.input.KeyboardType @@ -58,6 +56,7 @@ import org.signal.core.ui.compose.SignalPreview import org.signal.core.ui.compose.horizontalGutters import org.thoughtcrime.securesms.R import org.thoughtcrime.securesms.backup.v2.ui.BackupsIconColors +import org.thoughtcrime.securesms.fonts.MonoTypeface import org.thoughtcrime.securesms.registrationv3.ui.shared.RegistrationScreen import org.whispersystems.signalservice.api.AccountEntropyPool @@ -143,7 +142,7 @@ fun EnterBackupKeyScreen( Text(text = stringResource(id = R.string.EnterBackupKey_backup_key)) }, textStyle = LocalTextStyle.current.copy( - fontFamily = FontFamily(typeface = Typeface.MONOSPACE), + fontFamily = MonoTypeface.fontFamily(), lineHeight = 36.sp ), keyboardOptions = KeyboardOptions( @@ -215,7 +214,7 @@ private fun AccountEntropyPoolVerification.AEPValidationError.ValidationErrorMes private fun EnterBackupKeyScreenPreview() { Previews.Preview { EnterBackupKeyScreen( - backupKey = "UY38jh2778hjjhj8lk19ga61s672jsj089r023s6a57809bap92j2yh5t326vv7t", + backupKey = "UY38jh2778hjjhj8lk19ga61s672jsj089r023s6a57809bap92j2yh5t326vv7t".uppercase(), isBackupKeyValid = true, inProgress = false, chunkLength = 4, @@ -229,7 +228,7 @@ private fun EnterBackupKeyScreenPreview() { private fun EnterBackupKeyScreenErrorPreview() { Previews.Preview { EnterBackupKeyScreen( - backupKey = "UY38jh2778hjjhj8lk19ga61s672jsj089r023s6a57809bap92j2yh5t326vv7t", + backupKey = "UY38jh2778hjjhj8lk19ga61s672jsj089r023s6a57809bap92j2yh5t326vv7t".uppercase(), isBackupKeyValid = true, inProgress = false, chunkLength = 4,