From 3c36f1247b4c45510cbe67905508889cc7fd63d1 Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 12 Jun 2024 01:13:47 +0930 Subject: [PATCH] Styling --- .../ui/DisappearingMessages.kt | 3 +- .../newmessage/NewMessageFragment.kt | 6 +- .../start/InviteFriendFragment.kt | 23 ++- .../start/NewConversationHomeFragment.kt | 17 +- .../conversation/v2/MessageDetailActivity.kt | 21 +- .../securesms/home/HomeActivity.kt | 51 +++-- .../securesms/onboarding/LandingActivity.kt | 7 +- .../onboarding/LinkDeviceActivity.kt | 26 ++- .../RecoveryPasswordActivity.kt | 61 +++--- .../thoughtcrime/securesms/ui/Components.kt | 2 +- .../org/thoughtcrime/securesms/ui/Themes.kt | 11 +- .../securesms/ui/components/Button.kt | 36 +++- .../securesms/ui/components/Html.kt | 180 ++++++++++++++++++ .../securesms/ui/components/SessionTabRow.kt | 6 +- .../securesms/ui/components/Text.kt | 9 +- .../res/drawable/ic_circle_question_mark.xml | 15 ++ app/src/main/res/values/strings.xml | 4 +- 17 files changed, 387 insertions(+), 91 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/ui/components/Html.kt create mode 100644 app/src/main/res/drawable/ic_circle_question_mark.xml diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/disappearingmessages/ui/DisappearingMessages.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/disappearingmessages/ui/DisappearingMessages.kt index e694b3740f..6dd98dce9b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/disappearingmessages/ui/DisappearingMessages.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/disappearingmessages/ui/DisappearingMessages.kt @@ -52,7 +52,8 @@ fun DisappearingMessages( OptionsCard(it, callbacks) } - if (state.showGroupFooter) Text(text = stringResource(R.string.activity_disappearing_messages_group_footer), + if (state.showGroupFooter) Text( + text = stringResource(R.string.activity_disappearing_messages_group_footer), style = MaterialTheme.typography.extraSmall, fontWeight = FontWeight(400), color = Color(0xFFA1A2A1), diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/newmessage/NewMessageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/newmessage/NewMessageFragment.kt index 8bfe504223..0f1a279286 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/newmessage/NewMessageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/newmessage/NewMessageFragment.kt @@ -49,6 +49,7 @@ import org.thoughtcrime.securesms.ui.AppTheme import org.thoughtcrime.securesms.ui.LoadingArcOr import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider +import org.thoughtcrime.securesms.ui.baseBold import org.thoughtcrime.securesms.ui.components.AppBar import org.thoughtcrime.securesms.ui.components.BorderlessButtonSecondary import org.thoughtcrime.securesms.ui.components.MaybeScanQrCode @@ -175,7 +176,10 @@ fun EnterAccountId( onClick = { callbacks.onContinue() } ) { LoadingArcOr(state.loading) { - Text(stringResource(R.string.next)) + Text( + stringResource(R.string.next), + style = MaterialTheme.typography.baseBold + ) } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/InviteFriendFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/InviteFriendFragment.kt index 992a6604eb..79f6dc4776 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/InviteFriendFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/InviteFriendFragment.kt @@ -33,6 +33,8 @@ import org.session.libsession.utilities.TextSecurePreferences import org.thoughtcrime.securesms.preferences.copyPublicKey import org.thoughtcrime.securesms.preferences.sendInvitationToUseSession import org.thoughtcrime.securesms.ui.AppTheme +import org.thoughtcrime.securesms.ui.base +import org.thoughtcrime.securesms.ui.baseBold import org.thoughtcrime.securesms.ui.classicDarkColors import org.thoughtcrime.securesms.ui.components.AppBar import org.thoughtcrime.securesms.ui.components.OnPrimaryButtons @@ -53,6 +55,7 @@ class InviteFriendFragment : Fragment() { setContent { AppTheme { InviteFriend( + TextSecurePreferences.getLocalNumber(LocalContext.current)!!, onBack = { delegate.onDialogBackPressed() }, onClose = { delegate.onDialogClosePressed() }, copyPublicKey = requireContext()::copyPublicKey, @@ -66,11 +69,12 @@ class InviteFriendFragment : Fragment() { @Preview @Composable private fun PreviewInviteFriend() { - InviteFriend() + InviteFriend("050000000") } @Composable private fun InviteFriend( + accountId: String, onBack: () -> Unit = {}, onClose: () -> Unit = {}, copyPublicKey: () -> Unit = {}, @@ -93,12 +97,13 @@ private fun InviteFriend( .wrapContentHeight() ) { Text( - TextSecurePreferences.getLocalNumber(LocalContext.current)!!, - textAlign = TextAlign.Center, + accountId, modifier = Modifier .contentDescription("Your account ID") .align(Alignment.Center) - .padding(22.dp) + .padding(22.dp), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.base ) } @@ -118,7 +123,10 @@ private fun InviteFriend( .contentDescription("Share button"), onClick = sendInvitation ) { - Text(stringResource(R.string.share)) + Text( + stringResource(R.string.share), + style = MaterialTheme.typography.baseBold + ) } OutlineTemporaryStateButton( @@ -127,7 +135,10 @@ private fun InviteFriend( .contentDescription(R.string.AccessibilityId_copy_button), onClick = copyPublicKey ) { isTemporary -> - Text(stringResource(if (isTemporary) R.string.copied else R.string.copy)) + Text( + stringResource(if (isTemporary) R.string.copied else R.string.copy), + style = MaterialTheme.typography.baseBold + ) } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt index c88a01f2aa..2df0897869 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt @@ -17,7 +17,6 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp import androidx.fragment.app.Fragment import dagger.hilt.android.AndroidEntryPoint import network.loki.messenger.R @@ -29,8 +28,8 @@ import org.thoughtcrime.securesms.ui.classicDarkColors import org.thoughtcrime.securesms.ui.components.AppBar import org.thoughtcrime.securesms.ui.components.QrImage import org.thoughtcrime.securesms.ui.contentDescription -import org.thoughtcrime.securesms.ui.medium import org.thoughtcrime.securesms.ui.small +import org.thoughtcrime.securesms.ui.xl import javax.inject.Inject @AndroidEntryPoint @@ -67,10 +66,18 @@ class NewConversationHomeFragment : Fragment() { Column( modifier = Modifier .padding(horizontal = LocalDimensions.current.marginMedium) - .padding(top = LocalDimensions.current.itemSpacingMedium)) { - Text(text = stringResource(R.string.accountIdYours), style = MaterialTheme.typography.medium) + .padding(top = LocalDimensions.current.itemSpacingMedium) + ) { + Text( + text = stringResource(R.string.accountIdYours), + style = MaterialTheme.typography.xl + ) Spacer(modifier = Modifier.height(LocalDimensions.current.itemSpacingTiny)) - Text(text = stringResource(R.string.qrYoursDescription), color = classicDarkColors[5], style = MaterialTheme.typography.small) + Text( + text = stringResource(R.string.qrYoursDescription), + color = classicDarkColors[5], + style = MaterialTheme.typography.small + ) Spacer(modifier = Modifier.height(LocalDimensions.current.itemSpacingSmall)) QrImage(string = TextSecurePreferences.getLocalNumber(requireContext())!!, Modifier.contentDescription(R.string.AccessibilityId_qr_code)) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt index 00550c8d52..9390f60d5f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/MessageDetailActivity.kt @@ -29,6 +29,7 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.Icon import androidx.compose.material.LocalTextStyle +import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -72,6 +73,9 @@ import org.thoughtcrime.securesms.ui.ItemButton import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider import org.thoughtcrime.securesms.ui.TitledText +import org.thoughtcrime.securesms.ui.base +import org.thoughtcrime.securesms.ui.baseBold +import org.thoughtcrime.securesms.ui.baseMonospace import org.thoughtcrime.securesms.ui.blackAlpha40 import org.thoughtcrime.securesms.ui.colorDestructive import org.thoughtcrime.securesms.ui.destructiveButtonColors @@ -364,7 +368,7 @@ fun FileDetails(fileDetails: List) { fun TitledErrorText(titledText: TitledText?) { TitledText( titledText, - style = LocalTextStyle.current.copy(color = colorDestructive) + style = MaterialTheme.typography.base.copy(color = colorDestructive) ) } @@ -372,7 +376,7 @@ fun TitledErrorText(titledText: TitledText?) { fun TitledMonospaceText(titledText: TitledText?) { TitledText( titledText, - style = LocalTextStyle.current.copy(fontFamily = FontFamily.Monospace) + style = MaterialTheme.typography.baseMonospace ) } @@ -380,11 +384,15 @@ fun TitledMonospaceText(titledText: TitledText?) { fun TitledText( titledText: TitledText?, modifier: Modifier = Modifier, - style: TextStyle = LocalTextStyle.current, + style: TextStyle = MaterialTheme.typography.base, ) { titledText?.apply { TitledView(title, modifier) { - Text(text, style = style, modifier = Modifier.fillMaxWidth()) + Text( + text, + style = style, + modifier = Modifier.fillMaxWidth() + ) } } } @@ -399,5 +407,8 @@ fun TitledView(title: GetString, modifier: Modifier = Modifier, content: @Compos @Composable fun Title(title: GetString) { - Text(title.string(), fontWeight = FontWeight.Bold) + Text( + title.string(), + style = MaterialTheme.typography.baseBold + ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt index d289022cff..b12553ec83 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -98,9 +98,11 @@ import org.thoughtcrime.securesms.preferences.SettingsActivity import org.thoughtcrime.securesms.showMuteDialog import org.thoughtcrime.securesms.showSessionDialog import org.thoughtcrime.securesms.ui.AppTheme +import org.thoughtcrime.securesms.ui.LocalDimensions import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.SessionShieldIcon import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider +import org.thoughtcrime.securesms.ui.base import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.h8 @@ -372,25 +374,33 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), private fun SeedReminder() { AppTheme { Column { + // Color Strip Box( Modifier .fillMaxWidth() .height(4.dp) - .background(MaterialTheme.colors.secondary)) + .background(MaterialTheme.colors.secondary) + ) Row( Modifier .background(MaterialTheme.colors.surface) - .padding(horizontal = 24.dp, vertical = 16.dp) + .padding(horizontal = LocalDimensions.current.marginSmall, vertical = LocalDimensions.current.marginExtraSmall) ) { Column(Modifier.weight(1f)) { Row { - Text(stringResource(R.string.save_your_recovery_password), style = MaterialTheme.typography.h8) - Spacer(Modifier.requiredWidth(8.dp)) + Text( + stringResource(R.string.save_your_recovery_password), + style = MaterialTheme.typography.h8 + ) + Spacer(Modifier.requiredWidth(LocalDimensions.current.itemSpacingSmall)) SessionShieldIcon() } - Text(stringResource(R.string.save_your_recovery_password_to_make_sure_you_don_t_lose_access_to_your_account), style = MaterialTheme.typography.small) + Text( + stringResource(R.string.save_your_recovery_password_to_make_sure_you_don_t_lose_access_to_your_account), + style = MaterialTheme.typography.small + ) } - Spacer(Modifier.width(12.dp)) + Spacer(Modifier.width(LocalDimensions.current.marginExtraExtraSmall)) OutlineButton( textId = R.string.continue_2, modifier = Modifier @@ -418,27 +428,38 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), contentDescription = null, tint = Color.Unspecified ) - if (newAccount) Text(stringResource(R.string.onboardingAccountCreated), style = MaterialTheme.typography.h4, textAlign = TextAlign.Center) - if (newAccount) Text(stringResource(R.string.welcome_to_session), color = MaterialTheme.colors.secondary, textAlign = TextAlign.Center) + if (newAccount) { + Text( + stringResource(R.string.onboardingAccountCreated), + style = MaterialTheme.typography.h4, + textAlign = TextAlign.Center + ) + Text( + stringResource(R.string.welcome_to_session), + style = MaterialTheme.typography.base, + color = MaterialTheme.colors.secondary, + textAlign = TextAlign.Center + ) + } - Divider(modifier = Modifier.padding(vertical = 16.dp)) + Divider(modifier = Modifier.padding(vertical = LocalDimensions.current.marginExtraSmall)) Text( stringResource(R.string.conversationsNone), style = MaterialTheme.typography.h8, textAlign = TextAlign.Center, modifier = Modifier.padding(bottom = 12.dp)) - Text(stringResource(R.string.onboardingHitThePlusButton), textAlign = TextAlign.Center) + Text( + stringResource(R.string.onboardingHitThePlusButton), + style = MaterialTheme.typography.small, + textAlign = TextAlign.Center + ) Spacer(modifier = Modifier.weight(2f)) } } } override fun onInputFocusChanged(hasFocus: Boolean) { - if (hasFocus) { - setSearchShown(true) - } else { - setSearchShown(binding.globalSearchInputLayout.query.value.isNotEmpty()) - } + setSearchShown(hasFocus || binding.globalSearchInputLayout.query.value.isNotEmpty()) } private fun setSearchShown(isShown: Boolean) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt index 05bb3ac5cb..7ae4c0c150 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt @@ -8,7 +8,6 @@ import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.slideInVertically -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -49,12 +48,12 @@ import org.thoughtcrime.securesms.onboarding.pickname.startPickDisplayNameActivi import org.thoughtcrime.securesms.service.KeyCachingService import org.thoughtcrime.securesms.showOpenUrlDialog import org.thoughtcrime.securesms.ui.AppTheme -import org.thoughtcrime.securesms.ui.Cell import org.thoughtcrime.securesms.ui.LocalDimensions import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider import org.thoughtcrime.securesms.ui.classicDarkColors import org.thoughtcrime.securesms.ui.components.BorderlessButton +import org.thoughtcrime.securesms.ui.components.BorderlessHtmlButton import org.thoughtcrime.securesms.ui.components.FilledButton import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.contentDescription @@ -173,8 +172,8 @@ class LandingActivity : BaseActionBarActivity() { .align(Alignment.CenterHorizontally) .contentDescription(R.string.AccessibilityId_restore_account_button) ) { start() } - BorderlessButton( - text = stringResource(R.string.onboardingTosPrivacy), + BorderlessHtmlButton( + textId = R.string.onboardingTosPrivacy, modifier = Modifier .fillMaxWidth() .align(Alignment.CenterHorizontally) diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt index c4e7cca883..af9e7d0bd7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt @@ -33,6 +33,8 @@ import network.loki.messenger.R import org.session.libsession.utilities.TextSecurePreferences import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.ui.AppTheme +import org.thoughtcrime.securesms.ui.LocalDimensions +import org.thoughtcrime.securesms.ui.base import org.thoughtcrime.securesms.ui.baseBold import org.thoughtcrime.securesms.ui.components.MaybeScanQrCode import org.thoughtcrime.securesms.ui.components.OutlineButton @@ -113,11 +115,14 @@ fun PreviewRecoveryPassword() = RecoveryPassword(state = LinkDeviceState()) @Composable fun RecoveryPassword(state: LinkDeviceState, onChange: (String) -> Unit = {}, onContinue: () -> Unit = {}) { Column( - modifier = Modifier.padding(horizontal = 60.dp) + modifier = Modifier.padding(horizontal = LocalDimensions.current.marginLarge) ) { Spacer(Modifier.weight(1f)) Row { - Text(stringResource(R.string.sessionRecoveryPassword), style = MaterialTheme.typography.h4) + Text( + stringResource(R.string.sessionRecoveryPassword), + style = MaterialTheme.typography.h4 + ) Spacer(Modifier.width(6.dp)) Icon( painter = painterResource(id = R.drawable.ic_shield_outline), @@ -125,7 +130,10 @@ fun RecoveryPassword(state: LinkDeviceState, onChange: (String) -> Unit = {}, on ) } Spacer(Modifier.size(28.dp)) - Text(stringResource(R.string.activity_link_enter_your_recovery_password_to_load_your_account_if_you_haven_t_saved_it_you_can_find_it_in_your_app_settings)) + Text( + stringResource(R.string.activity_link_enter_your_recovery_password_to_load_your_account_if_you_haven_t_saved_it_you_can_find_it_in_your_app_settings), + style = MaterialTheme.typography.base + ) Spacer(Modifier.size(24.dp)) SessionOutlinedTextField( text = state.recoveryPhrase, @@ -137,24 +145,14 @@ fun RecoveryPassword(state: LinkDeviceState, onChange: (String) -> Unit = {}, on onContinue = onContinue, error = state.error ) - Spacer(Modifier.size(12.dp)) - state.error?.let { - Text( - it, - modifier = Modifier.contentDescription(R.string.AccessibilityId_error_message), - style = MaterialTheme.typography.baseBold, - color = MaterialTheme.colors.error - ) - } Spacer(Modifier.weight(2f)) OutlineButton( textId = R.string.continue_2, modifier = Modifier .align(Alignment.CenterHorizontally) - .padding(horizontal = 64.dp, vertical = 20.dp) + .padding(horizontal = LocalDimensions.current.marginLarge, vertical = 20.dp) .width(200.dp), onClick = onContinue ) } } - diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt index 5de14fa3e8..c744b7469c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentWidth @@ -35,9 +36,11 @@ import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.showSessionDialog import org.thoughtcrime.securesms.ui.AppTheme import org.thoughtcrime.securesms.ui.CellWithPaddingAndMargin +import org.thoughtcrime.securesms.ui.LocalDimensions import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.SessionShieldIcon import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider +import org.thoughtcrime.securesms.ui.base import org.thoughtcrime.securesms.ui.classicDarkColors import org.thoughtcrime.securesms.ui.components.DestructiveButtons import org.thoughtcrime.securesms.ui.components.OutlineButton @@ -58,7 +61,7 @@ class RecoveryPasswordActivity : BaseActionBarActivity() { ComposeView(this).apply { setContent { - RecoveryPassword( + RecoveryPasswordScreen( viewModel.seed, { viewModel.copySeed(context) } ) { onHide() } @@ -93,27 +96,27 @@ class RecoveryPasswordActivity : BaseActionBarActivity() { @Preview @Composable -fun PreviewRecoveryPassword( +fun PreviewRecoveryPasswordScreen( @PreviewParameter(ThemeResPreviewParameterProvider::class) themeResId: Int ) { PreviewTheme(themeResId) { - RecoveryPassword(seed = "Voyage urban toyed maverick peculiar tuxedo penguin tree grass building listen speak withdraw terminal plane") + RecoveryPasswordScreen(seed = "Voyage urban toyed maverick peculiar tuxedo penguin tree grass building listen speak withdraw terminal plane") } } @Composable -fun RecoveryPassword( +fun RecoveryPasswordScreen( seed: String = "", copySeed:() -> Unit = {}, onHide:() -> Unit = {} ) { AppTheme { Column( - verticalArrangement = Arrangement.spacedBy(16.dp), + verticalArrangement = Arrangement.spacedBy(LocalDimensions.current.marginExtraSmall), modifier = Modifier .contentDescription(R.string.AccessibilityId_recovery_password) .verticalScroll(rememberScrollState()) - .padding(bottom = 16.dp) + .padding(bottom = LocalDimensions.current.marginExtraSmall) ) { SmallButtons { RecoveryPasswordCell(seed, copySeed) @@ -132,29 +135,17 @@ fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) { CellWithPaddingAndMargin { Column { Row { - Text(stringResource(R.string.sessionRecoveryPassword)) + Text(stringResource(R.string.sessionRecoveryPassword), style = MaterialTheme.typography.h8) Spacer(Modifier.width(8.dp)) SessionShieldIcon() } - Text(stringResource(R.string.recoveryPasswordDescription)) + Spacer(modifier = Modifier.height(LocalDimensions.current.marginTiny)) + + Text(stringResource(R.string.recoveryPasswordDescription), style = MaterialTheme.typography.base) AnimatedVisibility(!showQr) { - Text( - seed, - modifier = Modifier - .contentDescription(R.string.AccessibilityId_recovery_password_container) - .padding(vertical = 24.dp) - .border( - width = 1.dp, - color = classicDarkColors[3], - shape = RoundedCornerShape(11.dp) - ) - .padding(24.dp), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.small.copy(fontFamily = FontFamily.Monospace), - color = MaterialTheme.colors.run { if (isLight) onSurface else secondary }, - ) + RecoveryPassword(seed) } AnimatedVisibility( @@ -163,7 +154,8 @@ fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) { ) { QrImage( seed, - modifier = Modifier.padding(vertical = 24.dp) + modifier = Modifier + .padding(vertical = 24.dp) .contentDescription(R.string.AccessibilityId_qr_code), icon = R.drawable.session_shield ) @@ -194,7 +186,26 @@ fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) { } @Composable -fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) { +private fun RecoveryPassword(seed: String) { + Text( + seed, + modifier = Modifier + .contentDescription(R.string.AccessibilityId_recovery_password_container) + .padding(vertical = 24.dp) + .border( + width = 1.dp, + color = classicDarkColors[3], + shape = RoundedCornerShape(11.dp) + ) + .padding(24.dp), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.small.copy(fontFamily = FontFamily.Monospace), + color = MaterialTheme.colors.run { if (isLight) onSurface else secondary }, + ) +} + +@Composable +private fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) { CellWithPaddingAndMargin { Row { Column( diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt index 7440cde47c..0ba995351c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt @@ -187,7 +187,7 @@ fun ItemButton( ) { icon() } - Text(text, modifier = Modifier.fillMaxWidth(), style = MaterialTheme.typography.h8) + Text(text, modifier = Modifier.fillMaxWidth(), style = MaterialTheme.typography.xl) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt index a1b962b7fb..b0339038f9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt @@ -20,6 +20,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.Dp @@ -43,7 +44,9 @@ data class Dimensions( val itemSpacingSmall: Dp = 16.dp, val itemSpacingMedium: Dp = 24.dp, val marginTiny: Dp = 8.dp, - val marginSmall: Dp = 16.dp, + val marginExtraExtraSmall: Dp = 12.dp, + val marginExtraSmall: Dp = 16.dp, + val marginSmall: Dp = 24.dp, val marginMedium: Dp = 32.dp, val marginLarge: Dp = 64.dp, val dividerIndent: Dp = 80.dp, @@ -65,7 +68,7 @@ fun AppTheme( LocalCellColor to R.attr.colorSettingsBackground, LocalButtonColor to R.attr.prominentButtonColor, LocalLightCell to R.attr.lightCell, - LocalOnLightCell to R.attr.onLightCell + LocalOnLightCell to R.attr.onLightCell, ).map { (local, attr) -> local provides context.getColorFromTheme(attr) }.toTypedArray() ) { AppCompatTheme(surface = surface) { @@ -134,12 +137,14 @@ val sessionTypography = Typography( h6 = boldStyle(20.sp), ) -val Typography.medium get() = defaultStyle(18.sp) +val Typography.xl get() = defaultStyle(18.sp) val Typography.large get() = defaultStyle(16.sp) val Typography.base get() = defaultStyle(14.sp) val Typography.baseBold get() = boldStyle(14.sp) +val Typography.baseMonospace get() = defaultStyle(14.sp).copy(fontFamily = FontFamily.Monospace) val Typography.small get() = defaultStyle(12.sp) val Typography.extraSmall get() = defaultStyle(11.sp) +val Typography.fine get() = defaultStyle(9.sp) val Typography.h7 get() = boldStyle(18.sp) val Typography.h8 get() = boldStyle(16.sp) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt index 2e6d5578e8..985d657bf5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.PressInteraction import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.ButtonDefaults @@ -23,19 +22,19 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.runtime.staticCompositionLocalOf -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Shape import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.filter +import network.loki.messenger.R import org.thoughtcrime.securesms.ui.GetString import org.thoughtcrime.securesms.ui.LaunchedEffectAsync import org.thoughtcrime.securesms.ui.LocalButtonColor +import org.thoughtcrime.securesms.ui.baseBold import org.thoughtcrime.securesms.ui.colorDestructive import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.extraSmall @@ -59,7 +58,7 @@ fun OutlineButton(text: String, modifier: Modifier = Modifier, onClick: () -> Un OutlineButton( modifier.contentDescription(text), onClick = onClick - ) { Text(text) } + ) { Text(text, style = MaterialTheme.typography.baseBold) } } @Composable @@ -129,13 +128,12 @@ fun FilledButton( OutlinedButton( modifier = modifier, onClick = onClick, - shape = RoundedCornerShape(50), colors = ButtonDefaults.outlinedButtonColors( contentColor = MaterialTheme.colors.background, backgroundColor = LocalButtonColor.current ) ) { - Text(text = text) + Text(text = text, style = MaterialTheme.typography.baseBold) } } @@ -165,7 +163,6 @@ fun BorderlessButton( TextButton( onClick = onClick, modifier = modifier.contentDescription(contentDescription), - shape = RoundedCornerShape(percent = 50), colors = ButtonDefaults.outlinedButtonColors( contentColor = contentColor, backgroundColor = backgroundColor @@ -180,6 +177,31 @@ fun BorderlessButton( } } +@Composable +fun BorderlessHtmlButton( + textId: Int, + modifier: Modifier = Modifier, + contentColor: Color = MaterialTheme.colors.onBackground, + backgroundColor: Color = Color.Transparent, + onClick: () -> Unit +) { + TextButton( + onClick = onClick, + modifier = modifier, + colors = ButtonDefaults.outlinedButtonColors( + contentColor = contentColor, + backgroundColor = backgroundColor + ) + ) { + Text( + text = annotatedStringResource(textId), + textAlign = TextAlign.Center, + style = MaterialTheme.typography.extraSmall, + modifier = Modifier.padding(horizontal = 2.dp) + ) + } +} + private val MutableInteractionSource.releases get() = interactions.filter { it is PressInteraction.Release } diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/components/Html.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/components/Html.kt new file mode 100644 index 0000000000..951db1816e --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/components/Html.kt @@ -0,0 +1,180 @@ +package org.thoughtcrime.securesms.ui.components + +import android.content.res.Resources +import android.graphics.Typeface +import android.text.Spanned +import android.text.SpannedString +import android.text.style.* +import android.util.Log +import androidx.annotation.StringRes +import androidx.compose.runtime.Composable +import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.remember +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.text.font.FontStyle +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.BaselineShift +import androidx.compose.ui.text.style.TextDecoration +import androidx.compose.ui.unit.Density +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.em +import androidx.core.text.HtmlCompat + +// TODO Remove this file once we update to composeVersion=1.7.0-alpha06 fixes https://issuetracker.google.com/issues/139320238?pli=1 +// which allows Stylized string in string resources +@Composable +@ReadOnlyComposable +private fun resources(): Resources { + LocalConfiguration.current + return LocalContext.current.resources +} + +fun Spanned.toHtmlWithoutParagraphs(): String { + return HtmlCompat.toHtml(this, HtmlCompat.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE) + .substringAfter("

").substringBeforeLast("

") +} + +fun Resources.getText(@StringRes id: Int, vararg args: Any): CharSequence { + val escapedArgs = args.map { + if (it is Spanned) it.toHtmlWithoutParagraphs() else it + }.toTypedArray() + val resource = SpannedString(getText(id)) + val htmlResource = resource.toHtmlWithoutParagraphs() + val formattedHtml = String.format(htmlResource, *escapedArgs) + return HtmlCompat.fromHtml(formattedHtml, HtmlCompat.FROM_HTML_MODE_LEGACY) +} + +@Composable +fun annotatedStringResource(@StringRes id: Int, vararg formatArgs: Any): AnnotatedString { + val resources = resources() + val density = LocalDensity.current + return remember(id, formatArgs) { + val text = resources.getText(id, *formatArgs) + spannableStringToAnnotatedString(text, density) + } +} + +@Composable +fun annotatedStringResource(@StringRes id: Int): AnnotatedString { + val resources = resources() + val density = LocalDensity.current + return remember(id) { + val text = resources.getText(id) + spannableStringToAnnotatedString(text, density) + } +} + +private fun spannableStringToAnnotatedString( + text: CharSequence, + density: Density +): AnnotatedString { + return if (text is Spanned) { + with(density) { + buildAnnotatedString { + append((text.toString())) + text.getSpans(0, text.length, Any::class.java).forEach { + val start = text.getSpanStart(it) + val end = text.getSpanEnd(it) + when (it) { + is StyleSpan -> when (it.style) { + Typeface.NORMAL -> addStyle( + SpanStyle( + fontWeight = FontWeight.Normal, + fontStyle = FontStyle.Normal + ), + start, + end + ) + Typeface.BOLD -> addStyle( + SpanStyle( + fontWeight = FontWeight.Bold, + fontStyle = FontStyle.Normal + ), + start, + end + ) + Typeface.ITALIC -> addStyle( + SpanStyle( + fontWeight = FontWeight.Normal, + fontStyle = FontStyle.Italic + ), + start, + end + ) + Typeface.BOLD_ITALIC -> addStyle( + SpanStyle( + fontWeight = FontWeight.Bold, + fontStyle = FontStyle.Italic + ), + start, + end + ) + } + is TypefaceSpan -> addStyle( + SpanStyle( + fontFamily = when (it.family) { + FontFamily.SansSerif.name -> FontFamily.SansSerif + FontFamily.Serif.name -> FontFamily.Serif + FontFamily.Monospace.name -> FontFamily.Monospace + FontFamily.Cursive.name -> FontFamily.Cursive + else -> FontFamily.Default + } + ), + start, + end + ) + is BulletSpan -> { + Log.d("StringResources", "BulletSpan not supported yet") + addStyle(SpanStyle(), start, end) + } + is AbsoluteSizeSpan -> addStyle( + SpanStyle(fontSize = if (it.dip) it.size.dp.toSp() else it.size.toSp()), + start, + end + ) + is RelativeSizeSpan -> addStyle( + SpanStyle(fontSize = it.sizeChange.em), + start, + end + ) + is StrikethroughSpan -> addStyle( + SpanStyle(textDecoration = TextDecoration.LineThrough), + start, + end + ) + is UnderlineSpan -> addStyle( + SpanStyle(textDecoration = TextDecoration.Underline), + start, + end + ) + is SuperscriptSpan -> addStyle( + SpanStyle(baselineShift = BaselineShift.Superscript), + start, + end + ) + is SubscriptSpan -> addStyle( + SpanStyle(baselineShift = BaselineShift.Subscript), + start, + end + ) + is ForegroundColorSpan -> addStyle( + SpanStyle(color = Color(it.foregroundColor)), + start, + end + ) + else -> addStyle(SpanStyle(), start, end) + } + } + } + } + } else { + AnnotatedString(text.toString()) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/components/SessionTabRow.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/components/SessionTabRow.kt index 935cc7e33d..b1ac553058 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/components/SessionTabRow.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/components/SessionTabRow.kt @@ -22,6 +22,7 @@ import network.loki.messenger.R import org.thoughtcrime.securesms.ui.LocalButtonColor import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider +import org.thoughtcrime.securesms.ui.h8 private val TITLES = listOf(R.string.sessionRecoveryPassword, R.string.qrScan) @@ -45,7 +46,10 @@ fun SessionTabRow(pagerState: PagerState, titles: List) { selectedContentColor = MaterialTheme.colors.onPrimary, unselectedContentColor = MaterialTheme.colors.onPrimary, ) { - Text(stringResource(id = it)) + Text( + stringResource(id = it), + style = MaterialTheme.typography.h8 + ) } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/components/Text.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/components/Text.kt index d52f8c0dbf..7374f9ac84 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/components/Text.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/components/Text.kt @@ -12,6 +12,7 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import org.thoughtcrime.securesms.ui.base import org.thoughtcrime.securesms.ui.baseBold import org.thoughtcrime.securesms.ui.outlinedTextFieldColors @@ -28,8 +29,14 @@ fun SessionOutlinedTextField( OutlinedTextField( value = text, modifier = Modifier.fillMaxWidth(), + textStyle = MaterialTheme.typography.base, onValueChange = { onChange(it) }, - placeholder = { Text(placeholder) }, + placeholder = { + Text( + placeholder, + style = MaterialTheme.typography.base + ) + }, colors = outlinedTextFieldColors(error != null), singleLine = true, keyboardActions = KeyboardActions( diff --git a/app/src/main/res/drawable/ic_circle_question_mark.xml b/app/src/main/res/drawable/ic_circle_question_mark.xml new file mode 100644 index 0000000000..9bc2b817f1 --- /dev/null +++ b/app/src/main/res/drawable/ic_circle_question_mark.xml @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f3508c9277..d7f642dc8a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1067,7 +1067,7 @@ Creating an account is \ninstant, free, and \nanonymous 👇 Create account I have an account - By using this service, you agree to our Terms of Service and Privacy Policy + By using this service, you agree to our Terms of Service and Privacy Policy This QR code does not contain a Recovery Password. @@ -1091,7 +1091,7 @@ Hide Recovery Password Permanently
We strongly recommend you save your recovery password in a safe and secure place before continuing.]]>
Are you sure you want to permanently hide your recovery password on this device? This cannot be undone. - Use your recovery password to load your account on new devices. Your account cannot be recovered without your recovery password. Make sure it\'s stored somewhere safe and secure — and don\'t share it with anyone. + Use your recovery password to load your account on new devices.\n\nYour account cannot be recovered without your recovery password. Make sure it\'s stored somewhere safe and secure — and don\'t share it with anyone. Hide Hide Recovery Password View QR