From ff64a8bc137ccf52c8d5f67e9961feb2fe2d367b Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 1 May 2024 15:18:00 +0930 Subject: [PATCH] Improve themes, styling and animations --- .../ui/DisappearingMessages.kt | 7 +- .../securesms/dms/NewMessageFragment.kt | 22 +- .../securesms/home/HomeActivity.kt | 13 +- .../securesms/onboarding/LandingActivity.kt | 105 ++++----- .../onboarding/LinkDeviceActivity.kt | 13 +- .../MessageNotificationsActivity.kt | 5 +- .../pickname/PickDisplayNameActivity.kt | 9 +- .../RecoveryPasswordActivity.kt | 84 ++++--- .../securesms/preferences/SettingsActivity.kt | 33 +-- .../appearance/AppearanceSettingsActivity.kt | 11 +- .../thoughtcrime/securesms/ui/Components.kt | 220 +++--------------- .../org/thoughtcrime/securesms/ui/Themes.kt | 32 +-- .../securesms/ui/components/Button.kt | 174 ++++++++++++++ .../securesms/ui/components/QR.kt | 24 +- .../securesms/ui/components/QrImage.kt | 40 +++- .../securesms/ui/components/SessionTabRow.kt | 4 +- 16 files changed, 428 insertions(+), 368 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt 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 3fec60a0a3..82c87fae9f 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 @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms.conversation.disappearingmessages.ui +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -24,8 +25,8 @@ import org.thoughtcrime.securesms.ui.Callbacks import org.thoughtcrime.securesms.ui.GetString import org.thoughtcrime.securesms.ui.NoOpCallbacks import org.thoughtcrime.securesms.ui.OptionsCard -import org.thoughtcrime.securesms.ui.OutlineButton import org.thoughtcrime.securesms.ui.RadioOption +import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.fadingEdges @@ -64,9 +65,9 @@ fun DisappearingMessages( } if (state.showSetButton) OutlineButton( - GetString(R.string.disappearing_messages_set_button_title), + textId = R.string.disappearing_messages_set_button_title, modifier = Modifier - .contentDescription(GetString(R.string.AccessibilityId_set_button)) + .contentDescription(R.string.AccessibilityId_set_button) .align(Alignment.CenterHorizontally) .padding(bottom = 20.dp), onClick = callbacks::onSetClick diff --git a/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt index 8e9cd2673c..78364532e4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/dms/NewMessageFragment.kt @@ -1,12 +1,10 @@ package org.thoughtcrime.securesms.dms import android.content.Intent -import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.Toast import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -17,13 +15,13 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter @@ -41,14 +39,16 @@ import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2 import org.thoughtcrime.securesms.dependencies.DatabaseComponent import org.thoughtcrime.securesms.showOpenUrlDialog import org.thoughtcrime.securesms.ui.AppTheme -import org.thoughtcrime.securesms.ui.BorderlessButtonSecondary -import org.thoughtcrime.securesms.ui.OutlineButton +import org.thoughtcrime.securesms.ui.LoadingArcOr import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider import org.thoughtcrime.securesms.ui.components.AppBar +import org.thoughtcrime.securesms.ui.components.BorderlessButtonSecondary import org.thoughtcrime.securesms.ui.components.MaybeScanQrCode +import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.components.SessionOutlinedTextField import org.thoughtcrime.securesms.ui.components.SessionTabRow +import org.thoughtcrime.securesms.ui.contentDescription @AndroidEntryPoint class NewMessageFragment : Fragment() { @@ -157,12 +157,16 @@ fun EnterAccountId( Spacer(modifier = Modifier.weight(1f)) OutlineButton( - text = stringResource(id = R.string.continue_2), modifier = Modifier .align(Alignment.CenterHorizontally) .padding(horizontal = 64.dp, vertical = 20.dp) - .width(200.dp), - loading = state.loading - ) { callbacks.onContinue() } + .width(200.dp) + .contentDescription(R.string.continue_2), + onClick = { callbacks.onContinue() } + ) { + LoadingArcOr(state.loading) { + Text(stringResource(R.string.continue_2)) + } + } } } 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 3bd695b1ee..fb6a501dbc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -98,11 +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.GetString -import org.thoughtcrime.securesms.ui.OutlineButton import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.SessionShieldIcon import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider +import org.thoughtcrime.securesms.ui.components.OutlineButton +import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.h8 import org.thoughtcrime.securesms.ui.small import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities @@ -372,10 +372,11 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), } Spacer(Modifier.width(12.dp)) OutlineButton( - stringResource(R.string.continue_2), - Modifier.align(Alignment.CenterVertically), - contentDescription = GetString(R.string.AccessibilityId_reveal_recovery_phrase_button) - ) { start() } + textId = R.string.continue_2, + Modifier.align(Alignment.CenterVertically) + .contentDescription(R.string.AccessibilityId_reveal_recovery_phrase_button), + onClick = { start() } + ) } } } 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 c173eb9d42..75e96bd333 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LandingActivity.kt @@ -32,15 +32,14 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.onboarding.pickname.startPickDisplayNameActivity import org.thoughtcrime.securesms.service.KeyCachingService import org.thoughtcrime.securesms.showOpenUrlDialog -import org.thoughtcrime.securesms.showSessionDialog import org.thoughtcrime.securesms.ui.AppTheme -import org.thoughtcrime.securesms.ui.BorderlessButton -import org.thoughtcrime.securesms.ui.FilledButton import org.thoughtcrime.securesms.ui.GetString -import org.thoughtcrime.securesms.ui.OutlineButton 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.FilledButton +import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.session_accent import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo @@ -94,28 +93,30 @@ class LandingActivity : BaseActionBarActivity() { OutlineButton( text = stringResource(R.string.onboardingAccountCreate), modifier = Modifier + .contentDescription(R.string.AccessibilityId_create_account_button) .width(262.dp) .align(Alignment.CenterHorizontally), - contentDescription = GetString(R.string.AccessibilityId_create_account_button) - ) { startPickDisplayNameActivity() } + onClick = ::startPickDisplayNameActivity + ) Spacer(modifier = Modifier.height(14.dp)) FilledButton( text = stringResource(R.string.onboardingAccountExists), modifier = Modifier .width(262.dp) - .align(Alignment.CenterHorizontally), - contentDescription = GetString(R.string.AccessibilityId_restore_account_button) + .align(Alignment.CenterHorizontally) + .contentDescription(R.string.AccessibilityId_restore_account_button) ) { startLinkDeviceActivity() } Spacer(modifier = Modifier.height(8.dp)) BorderlessButton( text = stringResource(R.string.onboardingTosPrivacy), modifier = Modifier .width(262.dp) - .align(Alignment.CenterHorizontally), - contentDescription = GetString(R.string.AccessibilityId_privacy_policy_link), + .align(Alignment.CenterHorizontally) + .contentDescription(R.string.AccessibilityId_privacy_policy_link), fontSize = 11.sp, - lineHeight = 13.sp - ) { openDialog() } + lineHeight = 13.sp, + onClick = ::openDialog + ) Spacer(modifier = Modifier.height(8.dp)) } } @@ -136,44 +137,44 @@ class LandingActivity : BaseActionBarActivity() { private fun open(url: String) { Intent(Intent.ACTION_VIEW, Uri.parse(url)).let(::startActivity) } - - @Composable - private fun IncomingText(text: String) { - ChatText( - text, - color = classicDarkColors[2] - ) - } - - @Composable - private fun ColumnScope.OutgoingText(text: String) { - ChatText( - text, - color = session_accent, - textColor = MaterialTheme.colors.primary, - modifier = Modifier.align(Alignment.End) - ) - } - - @Composable - private fun ChatText( - text: String, - color: Color, - modifier: Modifier = Modifier, - textColor: Color = Color.Unspecified - ) { - Text( - text, - fontSize = 16.sp, - lineHeight = 19.sp, - color = textColor, - modifier = modifier - .fillMaxWidth(0.666f) - .background( - color = color, - shape = RoundedCornerShape(size = 13.dp) - ) - .padding(horizontal = 16.dp, vertical = 12.dp) - ) - } +} + +@Composable +private fun IncomingText(text: String) { + ChatText( + text, + color = classicDarkColors[2] + ) +} + +@Composable +private fun ColumnScope.OutgoingText(text: String) { + ChatText( + text, + color = session_accent, + textColor = MaterialTheme.colors.primary, + modifier = Modifier.align(Alignment.End) + ) +} + +@Composable +private fun ChatText( + text: String, + color: Color, + modifier: Modifier = Modifier, + textColor: Color = Color.Unspecified +) { + Text( + text, + fontSize = 16.sp, + lineHeight = 19.sp, + color = textColor, + modifier = modifier + .fillMaxWidth(0.666f) + .background( + color = color, + shape = RoundedCornerShape(size = 13.dp) + ) + .padding(horizontal = 16.dp, vertical = 12.dp) + ) } 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 fc0421edf4..db408fa9f7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/LinkDeviceActivity.kt @@ -40,9 +40,9 @@ 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.OutlineButton import org.thoughtcrime.securesms.ui.baseBold import org.thoughtcrime.securesms.ui.components.MaybeScanQrCode +import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.components.SessionOutlinedTextField import org.thoughtcrime.securesms.ui.components.SessionTabRow import org.thoughtcrime.securesms.ui.contentDescription @@ -150,12 +150,13 @@ fun RecoveryPassword(state: LinkDeviceState, onChange: (String) -> Unit = {}, on } Spacer(Modifier.weight(2f)) OutlineButton( - text = stringResource(id = R.string.continue_2), + textId = R.string.continue_2, modifier = Modifier - .align(Alignment.CenterHorizontally) - .padding(horizontal = 64.dp, vertical = 20.dp) - .width(200.dp) - ) { onContinue() } + .align(Alignment.CenterHorizontally) + .padding(horizontal = 64.dp, vertical = 20.dp) + .width(200.dp), + onClick = onContinue + ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt index 71c1786e4c..c13f881654 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/messagenotifications/MessageNotificationsActivity.kt @@ -38,10 +38,9 @@ import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.home.HomeActivity import org.thoughtcrime.securesms.notifications.PushRegistry import org.thoughtcrime.securesms.ui.AppTheme -import org.thoughtcrime.securesms.ui.GetString -import org.thoughtcrime.securesms.ui.OutlineButton import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider +import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.h8 import org.thoughtcrime.securesms.ui.h9 @@ -127,7 +126,7 @@ fun MessageNotificationsScreen( ) Spacer(Modifier.weight(1f)) OutlineButton( - stringResource(R.string.continue_2), + textId = R.string.continue_2, modifier = Modifier .align(Alignment.CenterHorizontally) .width(262.dp), diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt index e6a0993222..e2620bdd2c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/pickname/PickDisplayNameActivity.kt @@ -36,10 +36,10 @@ import org.thoughtcrime.securesms.ApplicationContext import org.thoughtcrime.securesms.BaseActionBarActivity import org.thoughtcrime.securesms.onboarding.messagenotifications.startPNModeActivity import org.thoughtcrime.securesms.ui.AppTheme -import org.thoughtcrime.securesms.ui.OutlineButton import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.base import org.thoughtcrime.securesms.ui.baseBold +import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.outlinedTextFieldColors import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo @@ -129,11 +129,12 @@ class PickDisplayNameActivity : BaseActionBarActivity() { Spacer(modifier = Modifier.weight(2f)) OutlineButton( - stringResource(R.string.continue_2), + textId = R.string.continue_2, modifier = Modifier .align(Alignment.CenterHorizontally) - .width(262.dp) - ) { onContinue() } + .width(262.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 500b4cea08..03c9c40d65 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 @@ -1,8 +1,5 @@ package org.thoughtcrime.securesms.onboarding.recoverypassword -import android.app.Activity -import android.content.Context -import android.content.Intent import android.os.Bundle import androidx.activity.viewModels import androidx.compose.animation.AnimatedVisibility @@ -13,15 +10,19 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width +import androidx.compose.foundation.layout.wrapContentWidth import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.verticalScroll import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.MutableState +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.ComposeView @@ -35,15 +36,16 @@ 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.GetString -import org.thoughtcrime.securesms.ui.LocalExtraColors -import org.thoughtcrime.securesms.ui.OutlineButton +import org.thoughtcrime.securesms.ui.LocalButtonColor import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.SessionShieldIcon import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider import org.thoughtcrime.securesms.ui.classicDarkColors import org.thoughtcrime.securesms.ui.colorDestructive +import org.thoughtcrime.securesms.ui.components.OutlineButton import org.thoughtcrime.securesms.ui.components.QrImageCard +import org.thoughtcrime.securesms.ui.components.SmallButtons +import org.thoughtcrime.securesms.ui.components.TemporaryStateButton import org.thoughtcrime.securesms.ui.contentDescription import org.thoughtcrime.securesms.ui.h8 import org.thoughtcrime.securesms.ui.small @@ -114,15 +116,17 @@ fun RecoveryPassword( .verticalScroll(rememberScrollState()) .padding(bottom = 16.dp) ) { - RecoveryPasswordCell(seed, copySeed) - HideRecoveryPasswordCell(onHide) + SmallButtons { + RecoveryPasswordCell(seed, copySeed) + HideRecoveryPasswordCell(onHide) + } } } } @Composable fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) { - val showQr = remember { + var showQr by remember { mutableStateOf(false) } @@ -136,7 +140,7 @@ fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) { Text(stringResource(R.string.recoveryPasswordDescription)) - AnimatedVisibility(!showQr.value) { + AnimatedVisibility(!showQr) { Text( seed, modifier = Modifier @@ -149,62 +153,70 @@ fun RecoveryPasswordCell(seed: String, copySeed:() -> Unit = {}) { ) .padding(24.dp), style = MaterialTheme.typography.small.copy(fontFamily = FontFamily.Monospace), - color = LocalExtraColors.current.prominentButtonColor, + color = MaterialTheme.colors.run { if (isLight) onSurface else secondary }, ) } AnimatedVisibility( - showQr.value, - modifier = Modifier.align(Alignment.CenterHorizontally).padding(vertical = 24.dp) + showQr, + modifier = Modifier.align(Alignment.CenterHorizontally) ) { QrImageCard( seed, + modifier = Modifier.padding(vertical = 24.dp), contentDescription = "QR code of your recovery password", icon = R.drawable.session_shield ) } - AnimatedVisibility(!showQr.value) { + AnimatedVisibility(!showQr) { Row(horizontalArrangement = Arrangement.spacedBy(32.dp)) { - OutlineButton( - modifier = Modifier.weight(1f), - color = MaterialTheme.colors.onPrimary, - onClick = copySeed, - temporaryContent = { Text(stringResource(R.string.copied)) } - ) { - Text(stringResource(R.string.copy)) + TemporaryStateButton { source, temporary -> + OutlineButton( + modifier = Modifier.weight(1f), + interactionSource = source, + onClick = { copySeed() }, + ) { + AnimatedVisibility(temporary) { Text(stringResource(R.string.copied)) } + AnimatedVisibility(!temporary) { Text(stringResource(R.string.copy)) } + } } - OutlineButton(text = stringResource(R.string.qrView), modifier = Modifier.weight(1f), color = MaterialTheme.colors.onPrimary) { showQr.toggle() } + OutlineButton(textId = R.string.qrView, modifier = Modifier.weight(1f), onClick = { showQr = !showQr }) } } - AnimatedVisibility(showQr.value, modifier = Modifier.align(Alignment.CenterHorizontally)) { + AnimatedVisibility(showQr, modifier = Modifier.align(Alignment.CenterHorizontally)) { OutlineButton( - text = stringResource(R.string.recoveryPasswordView), - color = MaterialTheme.colors.onPrimary, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) { showQr.toggle() } + textId = R.string.recoveryPasswordView, + onClick = { showQr = !showQr } + ) } } } } -private fun MutableState.toggle() { value = !value } - @Composable fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) { CellWithPaddingAndMargin { Row { - Column(Modifier.weight(1f)) { + Column( + Modifier.weight(1f) + ) { Text(text = stringResource(R.string.recoveryPasswordHideRecoveryPassword), style = MaterialTheme.typography.h8) Text(text = stringResource(R.string.recoveryPasswordHideRecoveryPasswordDescription)) } - OutlineButton( - stringResource(R.string.hide), - contentDescription = GetString(R.string.AccessibilityId_hide_recovery_password_button), - modifier = Modifier.align(Alignment.CenterVertically), - color = colorDestructive - ) { onHide() } + CompositionLocalProvider( + LocalButtonColor provides colorDestructive, + ) { + OutlineButton( + textId = R.string.hide, + modifier = Modifier + .wrapContentWidth() + .align(Alignment.CenterVertically) + .contentDescription(R.string.AccessibilityId_hide_recovery_password_button), + onClick = onHide + ) + } } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt index 4545f9b7a1..6668ae7a3a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt @@ -19,12 +19,15 @@ import android.view.View import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager import android.widget.Toast +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.interaction.InteractionSource 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.wrapContentHeight import androidx.compose.material.Card import androidx.compose.material.MaterialTheme import androidx.compose.material.Text @@ -84,19 +87,16 @@ import org.thoughtcrime.securesms.preferences.appearance.AppearanceSettingsActiv import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints import org.thoughtcrime.securesms.showSessionDialog import org.thoughtcrime.securesms.ui.AppTheme -import org.thoughtcrime.securesms.ui.BorderlessButton import org.thoughtcrime.securesms.ui.Cell import org.thoughtcrime.securesms.ui.Divider import org.thoughtcrime.securesms.ui.ItemButton import org.thoughtcrime.securesms.ui.ItemButtonWithDrawable -import org.thoughtcrime.securesms.ui.OutlineButton -import org.thoughtcrime.securesms.ui.PreviewTheme -import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider +import org.thoughtcrime.securesms.ui.components.OutlineButton +import org.thoughtcrime.securesms.ui.components.TemporaryStateButton import org.thoughtcrime.securesms.ui.destructiveButtonColors import org.thoughtcrime.securesms.util.BitmapDecodingException import org.thoughtcrime.securesms.util.BitmapUtil import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities -import org.thoughtcrime.securesms.util.disableClipping import org.thoughtcrime.securesms.util.push import org.thoughtcrime.securesms.util.show import java.io.File @@ -429,20 +429,25 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() { fun Buttons() { Column { Row( - modifier = Modifier.padding(horizontal = 24.dp), + modifier = Modifier.padding(horizontal = 24.dp).padding(top = 8.dp), horizontalArrangement = Arrangement.spacedBy(16.dp), ) { OutlineButton( modifier = Modifier.weight(1f), - onClick = { sharePublicKey() } - ) { Text(stringResource(R.string.share)) } - - OutlineButton( - modifier = Modifier.weight(1f), - onClick = { copyPublicKey() }, - temporaryContent = { Text(stringResource(R.string.copied)) } + onClick = ::sharePublicKey ) { - Text(stringResource(R.string.copy)) + Text(stringResource(R.string.share)) + } + + TemporaryStateButton { source, temporary -> + OutlineButton( + modifier = Modifier.weight(1f), + interactionSource = source, + onClick = { copyPublicKey() }, + ) { + AnimatedVisibility(temporary) { Text(stringResource(R.string.copied)) } + AnimatedVisibility(!temporary) { Text(stringResource(R.string.copy)) } + } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsActivity.kt index 823728c359..34547c999e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsActivity.kt @@ -5,7 +5,6 @@ import android.os.Parcelable import android.util.SparseArray import android.view.View import androidx.activity.viewModels -import androidx.appcompat.widget.SwitchCompat import androidx.core.view.children import androidx.lifecycle.lifecycleScope import dagger.hilt.android.AndroidEntryPoint @@ -31,8 +30,8 @@ class AppearanceSettingsActivity: PassphraseRequiredActionBarActivity(), View.On var currentTheme: ThemeState? = null - private val accentColors - get() = mapOf( + private val accentColors by lazy { + mapOf( binding.accentGreen to R.style.PrimaryGreen, binding.accentBlue to R.style.PrimaryBlue, binding.accentYellow to R.style.PrimaryYellow, @@ -41,9 +40,10 @@ class AppearanceSettingsActivity: PassphraseRequiredActionBarActivity(), View.On binding.accentOrange to R.style.PrimaryOrange, binding.accentRed to R.style.PrimaryRed ) + } - private val themeViews - get() = listOf( + private val themeViews by lazy { + listOf( binding.themeOptionClassicDark, binding.themeRadioClassicDark, binding.themeOptionClassicLight, @@ -53,6 +53,7 @@ class AppearanceSettingsActivity: PassphraseRequiredActionBarActivity(), View.On binding.themeOptionOceanLight, binding.themeRadioOceanLight ) + } override fun onClick(v: View?) { v ?: return 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 5b62a91135..44c996b6de 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt @@ -1,14 +1,13 @@ package org.thoughtcrime.securesms.ui -import android.graphics.drawable.BitmapDrawable import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Canvas +import androidx.compose.foundation.Image import androidx.compose.foundation.ScrollState import androidx.compose.foundation.clickable -import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope @@ -27,7 +26,6 @@ import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Button import androidx.compose.material.ButtonColors import androidx.compose.material.ButtonDefaults import androidx.compose.material.Card @@ -35,12 +33,14 @@ import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Colors import androidx.compose.material.ContentAlpha import androidx.compose.material.Icon +import androidx.compose.material.LocalContentColor import androidx.compose.material.MaterialTheme import androidx.compose.material.OutlinedButton import androidx.compose.material.RadioButton import androidx.compose.material.Text import androidx.compose.material.TextButton import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -49,6 +49,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.composed import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.geometry.Size @@ -57,7 +58,6 @@ import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.StrokeCap -import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.drawscope.Stroke import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.platform.LocalContext @@ -71,10 +71,9 @@ import androidx.compose.ui.unit.TextUnit import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.compose.ui.viewinterop.AndroidView -import androidx.core.content.res.ResourcesCompat import com.google.accompanist.drawablepainter.rememberDrawablePainter import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.delay +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import network.loki.messenger.R import org.session.libsession.utilities.recipients.Recipient @@ -83,155 +82,6 @@ import org.thoughtcrime.securesms.components.ProfilePictureView import org.thoughtcrime.securesms.conversation.disappearingmessages.ui.OptionsCard import kotlin.math.min import kotlin.math.roundToInt -import kotlin.time.Duration.Companion.seconds - -@Composable -fun OutlineButton( - text: String, - modifier: Modifier = Modifier, - contentDescription: GetString = GetString(text), - color: Color = LocalExtraColors.current.prominentButtonColor, - loading: Boolean = false, - onClick: () -> Unit -) { - OutlinedButton( - modifier = modifier.contentDescription(contentDescription), - onClick = onClick, - border = BorderStroke(1.dp, color), - shape = RoundedCornerShape(50), // = 50% percent - colors = ButtonDefaults.outlinedButtonColors( - contentColor = color, - backgroundColor = Color.Unspecified - ) - ) { - AnimatedVisibility(loading) { - CircularProgressIndicator( - modifier = Modifier.size(20.dp), - color = color, - strokeWidth = 2.dp - ) - } - AnimatedVisibility(!loading) { Text(text = text) } - } -} - -@Composable -fun OutlineButton( - modifier: Modifier = Modifier, - color: Color = LocalExtraColors.current.prominentButtonColor, - onClick: () -> Unit = {}, - content: @Composable () -> Unit = {} -) { - OutlinedButton( - modifier = modifier, - onClick = onClick, - border = BorderStroke(1.dp, color), - shape = RoundedCornerShape(percent = 50), - colors = ButtonDefaults.outlinedButtonColors( - contentColor = color, - backgroundColor = Color.Unspecified - ) - ) { - content() - } -} - -@Composable -fun OutlineButton( - temporaryContent: @Composable () -> Unit, - modifier: Modifier = Modifier, - color: Color = LocalExtraColors.current.prominentButtonColor, - onClick: () -> Unit = {}, - content: @Composable () -> Unit = {} -) { - var clicked by remember { mutableStateOf(false) } - if (clicked) LaunchedEffectAsync { - delay(2.seconds) - clicked = false - } - - OutlinedButton( - modifier = modifier, - onClick = { - onClick() - clicked = true - }, - border = BorderStroke(1.dp, color), - shape = RoundedCornerShape(percent = 50), - colors = ButtonDefaults.outlinedButtonColors( - contentColor = color, - backgroundColor = Color.Unspecified - ) - ) { - AnimatedVisibility(clicked) { - temporaryContent() - } - AnimatedVisibility(!clicked) { - content() - } - } -} - -@Composable -fun FilledButton( - text: String, - modifier: Modifier = Modifier, - contentDescription: GetString? = GetString(text), - onClick: () -> Unit) { - OutlinedButton( - modifier = modifier.size(108.dp, 34.dp), - onClick = onClick, - shape = RoundedCornerShape(50), // = 50% percent - colors = ButtonDefaults.outlinedButtonColors( - contentColor = MaterialTheme.colors.background, - backgroundColor = LocalExtraColors.current.prominentButtonColor - ) - ) { - Text(text = text) - } -} - -@Composable -fun BorderlessButtonSecondary( - text: String, - onClick: () -> Unit -) { - BorderlessButton( - text, - contentColor = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium), - onClick = onClick - ) -} - -@Composable -fun BorderlessButton( - text: String, - modifier: Modifier = Modifier, - contentDescription: GetString = GetString(text), - fontSize: TextUnit = TextUnit.Unspecified, - lineHeight: TextUnit = TextUnit.Unspecified, - contentColor: Color = MaterialTheme.colors.onBackground, - backgroundColor: Color = Color.Transparent, - onClick: () -> Unit -) { - TextButton( - onClick = onClick, - modifier = modifier.contentDescription(contentDescription), - shape = RoundedCornerShape(percent = 50), - colors = ButtonDefaults.outlinedButtonColors( - contentColor = contentColor, - backgroundColor = backgroundColor - ) - ) { - Text( - text = text, - textAlign = TextAlign.Center, - fontSize = fontSize, - lineHeight = lineHeight, - modifier = Modifier.padding(horizontal = 2.dp) - ) - } -} interface Callbacks { fun onSetClick(): Any? @@ -367,16 +217,18 @@ fun CellWithPaddingAndMargin( margin: Dp = 32.dp, content: @Composable () -> Unit ) { - Card( - backgroundColor = MaterialTheme.colors.cellColor, - shape = RoundedCornerShape(16.dp), - elevation = 0.dp, - modifier = Modifier - .wrapContentHeight() - .fillMaxWidth() - .padding(horizontal = margin), - ) { - Box(Modifier.padding(padding)) { content() } + CompositionLocalProvider(LocalButtonColor provides MaterialTheme.colors.onPrimary) { + Card( + backgroundColor = LocalCellColor.current, + shape = RoundedCornerShape(16.dp), + elevation = 0.dp, + modifier = Modifier + .wrapContentHeight() + .fillMaxWidth() + .padding(horizontal = margin), + ) { + Box(Modifier.padding(padding)) { content() } + } } } @@ -434,27 +286,10 @@ fun Modifier.contentDescription(id: Int?): Modifier { } @Composable -fun OutlineButton(text: GetString, contentDescription: GetString? = text, modifier: Modifier = Modifier, onClick: () -> Unit) { - OutlinedButton( - modifier = modifier - .size(108.dp, 34.dp) - .contentDescription(contentDescription), - onClick = onClick, - border = BorderStroke(1.dp, LocalExtraColors.current.prominentButtonColor), - shape = RoundedCornerShape(50), // = 50% percent - colors = ButtonDefaults.outlinedButtonColors( - contentColor = LocalExtraColors.current.prominentButtonColor, - backgroundColor = MaterialTheme.colors.background - ) - ){ - Text(text = text()) - } +fun Modifier.contentDescription(text: String?): Modifier { + return text?.let { semantics { contentDescription = it } } ?: this } -private val Colors.cellColor: Color - @Composable - get() = LocalExtraColors.current.settingsBackground - fun Modifier.fadingEdges( scrollState: ScrollState, topEdgeHeight: Dp = 0.dp, @@ -577,5 +412,20 @@ fun RowScope.SessionShieldIcon() { @Composable fun LaunchedEffectAsync(block: suspend CoroutineScope.() -> Unit) { - rememberCoroutineScope().apply { LaunchedEffect(Unit) { launch { block() } } } + val scope = rememberCoroutineScope() + LaunchedEffect(Unit) { scope.launch(Dispatchers.IO) { block() } } +} + +@Composable +fun LoadingArcOr(loading: Boolean, content: @Composable () -> Unit) { + AnimatedVisibility(loading) { + CircularProgressIndicator( + modifier = Modifier.size(20.dp), + color = LocalContentColor.current, + strokeWidth = 2.dp + ) + } + AnimatedVisibility(!loading) { + content() + } } 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 9e681868b4..51cdf01f71 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt @@ -27,15 +27,10 @@ import com.google.accompanist.themeadapter.appcompat.createAppCompatTheme import com.google.android.material.color.MaterialColors import network.loki.messenger.R -val LocalExtraColors = staticCompositionLocalOf { error("No Custom Attribute value provided") } - - -data class ExtraColors( - val settingsBackground: Color, - val prominentButtonColor: Color, - val lightCell: Color, - val onLightCell: Color, -) +val LocalCellColor = staticCompositionLocalOf { Color.Black } +val LocalButtonColor = staticCompositionLocalOf { Color.Black } +val LocalLightCell = staticCompositionLocalOf { Color.Black } +val LocalOnLightCell = staticCompositionLocalOf { Color.Black } /** * Converts current Theme to Compose Theme. @@ -46,19 +41,16 @@ fun AppTheme( ) { val context = LocalContext.current - val extraColors = context.run { - ExtraColors( - settingsBackground = getColorFromTheme(R.attr.colorSettingsBackground), - prominentButtonColor = getColorFromTheme(R.attr.prominentButtonColor), - lightCell = getColorFromTheme(R.attr.lightCell), - onLightCell = getColorFromTheme(R.attr.onLightCell), - ) - } - val surface = context.getColorFromTheme(R.attr.colorSettingsBackground) - - CompositionLocalProvider(LocalExtraColors provides extraColors) { + CompositionLocalProvider( + *listOf( + LocalCellColor to R.attr.colorSettingsBackground, + LocalButtonColor to R.attr.prominentButtonColor, + LocalLightCell to R.attr.lightCell, + LocalOnLightCell to R.attr.onLightCell + ).map { (local, attr) -> local provides context.getColorFromTheme(attr) }.toTypedArray() + ) { AppCompatTheme(surface = surface) { CompositionLocalProvider(LocalTextSelectionColors provides TextSelectionColors( handleColor = MaterialTheme.colors.secondary, 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 new file mode 100644 index 0000000000..ec54846b19 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/components/Button.kt @@ -0,0 +1,174 @@ +package org.thoughtcrime.securesms.ui.components + +import androidx.annotation.StringRes +import androidx.compose.foundation.BorderStroke +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 +import androidx.compose.material.ContentAlpha +import androidx.compose.material.MaterialTheme +import androidx.compose.material.OutlinedButton +import androidx.compose.material.Text +import androidx.compose.material.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.runtime.staticCompositionLocalOf +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.TextUnit +import androidx.compose.ui.unit.dp +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.filter +import org.thoughtcrime.securesms.ui.GetString +import org.thoughtcrime.securesms.ui.LaunchedEffectAsync +import org.thoughtcrime.securesms.ui.LocalButtonColor +import org.thoughtcrime.securesms.ui.colorDestructive +import org.thoughtcrime.securesms.ui.contentDescription +import kotlin.time.Duration.Companion.seconds + +val LocalButtonSize = staticCompositionLocalOf { mediumButton } +val LocalButtonShape = staticCompositionLocalOf { RoundedCornerShape(percent = 50) } + +@Composable +fun Modifier.applyButtonSize() = then(LocalButtonSize.current) + +val mediumButton = Modifier.height(41.dp) +val smallButton = Modifier.wrapContentHeight() + +@Composable +fun OutlineButton(@StringRes textId: Int, modifier: Modifier = Modifier, onClick: () -> Unit) { + OutlineButton(stringResource(textId), modifier, onClick) +} + +@Composable +fun OutlineButton(text: String, modifier: Modifier = Modifier, onClick: () -> Unit) { + OutlineButton(modifier.contentDescription(text), onClick = onClick) { Text(text) } +} + +@Composable +fun OutlineButton( + modifier: Modifier = Modifier, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + onClick: () -> Unit, + content: @Composable () -> Unit = {} +) { + OutlinedButton( + modifier = modifier.applyButtonSize(), + interactionSource = interactionSource, + onClick = onClick, + border = BorderStroke(1.dp, LocalButtonColor.current), + shape = LocalButtonShape.current, + colors = ButtonDefaults.outlinedButtonColors( + contentColor = LocalButtonColor.current, + backgroundColor = Color.Unspecified + ) + ) { + content() + } +} + +@Composable +fun TemporaryStateButton( + content: @Composable (MutableInteractionSource, Boolean) -> Unit, +) { + val interactions = remember { MutableInteractionSource() } + + var clicked by remember { mutableStateOf(false) } + + content(interactions, clicked) + + LaunchedEffectAsync { + interactions.releases.collectLatest { + clicked = true + delay(2.seconds) + clicked = false + } + } +} + +@Composable +fun FilledButton( + text: String, + modifier: Modifier = Modifier, + onClick: () -> Unit +) { + OutlinedButton( + modifier = modifier.size(108.dp, 34.dp), + onClick = onClick, + shape = RoundedCornerShape(50), + colors = ButtonDefaults.outlinedButtonColors( + contentColor = MaterialTheme.colors.background, + backgroundColor = LocalButtonColor.current + ) + ) { + Text(text = text) + } +} + +@Composable +fun BorderlessButtonSecondary( + text: String, + onClick: () -> Unit +) { + BorderlessButton( + text, + contentColor = MaterialTheme.colors.onSurface.copy(ContentAlpha.medium), + onClick = onClick + ) +} + +@Composable +fun BorderlessButton( + text: String, + modifier: Modifier = Modifier, + contentDescription: GetString = GetString(text), + fontSize: TextUnit = TextUnit.Unspecified, + lineHeight: TextUnit = TextUnit.Unspecified, + contentColor: Color = MaterialTheme.colors.onBackground, + backgroundColor: Color = Color.Transparent, + onClick: () -> Unit +) { + TextButton( + onClick = onClick, + modifier = modifier.contentDescription(contentDescription), + shape = RoundedCornerShape(percent = 50), + colors = ButtonDefaults.outlinedButtonColors( + contentColor = contentColor, + backgroundColor = backgroundColor + ) + ) { + Text( + text = text, + textAlign = TextAlign.Center, + fontSize = fontSize, + lineHeight = lineHeight, + modifier = Modifier.padding(horizontal = 2.dp) + ) + } +} + +private val MutableInteractionSource.releases + get() = interactions.filter { it is PressInteraction.Release } + +@Composable +fun SmallButtons(content: @Composable () -> Unit) { + CompositionLocalProvider(LocalButtonSize provides smallButton) { content() } +} + +@Composable +fun DestructiveButtons(content: @Composable () -> Unit) { + CompositionLocalProvider(LocalButtonColor provides colorDestructive) { content() } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/components/QR.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/components/QR.kt index 8c2143168e..0b314fecce 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/components/QR.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/components/QR.kt @@ -52,7 +52,6 @@ import kotlinx.coroutines.flow.emptyFlow import network.loki.messenger.R import org.session.libsignal.utilities.Log import org.thoughtcrime.securesms.onboarding.Analyzer -import org.thoughtcrime.securesms.ui.OutlineButton import java.util.concurrent.Executors typealias CameraPreview = androidx.camera.core.Preview @@ -96,17 +95,18 @@ fun MaybeScanQrCode( ) Spacer(modifier = Modifier.size(20.dp)) OutlineButton( - text = stringResource(R.string.sessionSettings), modifier = Modifier.align(Alignment.CenterHorizontally), onClick = onClickSettings - ) + ) { + Text(stringResource(R.string.sessionSettings)) + } } } else { OutlineButton( - text = stringResource(R.string.cameraGrantAccess), - modifier = Modifier.align(Alignment.Center) + modifier = Modifier.align(Alignment.Center), + onClick = { cameraPermissionState.run { launchPermissionRequest() } } ) { - cameraPermissionState.run { launchPermissionRequest() } + Text(stringResource(R.string.cameraGrantAccess)) } } } @@ -173,12 +173,12 @@ fun ScanQrCode(errors: Flow, onScan: (String) -> Unit) { ) Box( - Modifier - .aspectRatio(1f) - .padding(20.dp) - .clip(shape = RoundedCornerShape(20.dp)) - .background(Color(0x33ffffff)) - .align(Alignment.Center) + Modifier + .aspectRatio(1f) + .padding(20.dp) + .clip(shape = RoundedCornerShape(20.dp)) + .background(Color(0x33ffffff)) + .align(Alignment.Center) ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/ui/components/QrImage.kt b/app/src/main/java/org/thoughtcrime/securesms/ui/components/QrImage.kt index 49b8942882..e36660340d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/components/QrImage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/components/QrImage.kt @@ -1,9 +1,13 @@ package org.thoughtcrime.securesms.ui.components import android.graphics.Bitmap +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.scaleIn import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width @@ -25,7 +29,8 @@ import androidx.compose.ui.unit.dp import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import network.loki.messenger.R -import org.thoughtcrime.securesms.ui.LocalExtraColors +import org.thoughtcrime.securesms.ui.LocalLightCell +import org.thoughtcrime.securesms.ui.LocalOnLightCell import org.thoughtcrime.securesms.util.QRCodeUtilities @Composable @@ -36,7 +41,7 @@ fun QrImageCard( icon: Int = R.drawable.session_shield ) { Card( - backgroundColor = LocalExtraColors.current.lightCell, + backgroundColor = LocalLightCell.current, elevation = 0.dp, modifier = modifier ) { QrImage(string, contentDescription, icon) } @@ -55,24 +60,37 @@ fun QrImage(string: String, contentDescription: String, icon: Int = R.drawable.s } } - Box { - bitmap?.let { - Image( - bitmap = it.asImageBitmap(), - contentDescription = contentDescription, - colorFilter = ColorFilter.tint(LocalExtraColors.current.onLightCell) - ) + Box( + modifier = Modifier + .fillMaxWidth() + .aspectRatio(1f) + ) { + AnimatedVisibility( + visible = bitmap != null, + enter = scaleIn() + ) { + bitmap?.let { + Image( + bitmap = it.asImageBitmap(), + modifier = Modifier + .fillMaxWidth() + .aspectRatio(1f), + contentDescription = contentDescription, + colorFilter = ColorFilter.tint(LocalOnLightCell.current) + ) + } + } Icon( painter = painterResource(id = icon), contentDescription = "", - tint = LocalExtraColors.current.onLightCell, + tint = LocalOnLightCell.current, modifier = Modifier .align(Alignment.Center) .width(46.dp) .height(56.dp) - .background(color = LocalExtraColors.current.lightCell) + .background(color = LocalLightCell.current) .padding(horizontal = 3.dp, vertical = 1.dp) ) } 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 2b51632fd6..935cc7e33d 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 @@ -19,7 +19,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import kotlinx.coroutines.launch import network.loki.messenger.R -import org.thoughtcrime.securesms.ui.LocalExtraColors +import org.thoughtcrime.securesms.ui.LocalButtonColor import org.thoughtcrime.securesms.ui.PreviewTheme import org.thoughtcrime.securesms.ui.ThemeResPreviewParameterProvider @@ -31,7 +31,7 @@ fun SessionTabRow(pagerState: PagerState, titles: List) { TabRow( backgroundColor = Color.Unspecified, selectedTabIndex = pagerState.currentPage, - contentColor = LocalExtraColors.current.prominentButtonColor, + contentColor = LocalButtonColor.current, divider = { TabRowDefaults.Divider(color = MaterialTheme.colors.onPrimary.copy(alpha = TabRowDefaults.DividerOpacity)) }, modifier = Modifier .height(48.dp)