From ea0bcbe7c56431cb3e188629dfa16e34f0d24442 Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 20 Oct 2023 01:45:33 +1030 Subject: [PATCH] Populate RecoveryPasswordActivity --- app/src/main/AndroidManifest.xml | 2 +- .../conversation/v2/ConversationActivityV2.kt | 2 +- .../conversation/v2/MessageDetailActivity.kt | 8 +- .../securesms/home/HomeActivity.kt | 10 +- .../onboarding/RecoveryPasswordActivity.kt | 50 ------ .../RecoveryPasswordActivity.kt | 154 ++++++++++++++++++ .../securesms/preferences/SettingsActivity.kt | 2 +- .../thoughtcrime/securesms/ui/Components.kt | 24 ++- .../org/thoughtcrime/securesms/ui/Themes.kt | 1 + 9 files changed, 185 insertions(+), 68 deletions(-) delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/onboarding/RecoveryPasswordActivity.kt create mode 100644 app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ad84947575..3ba789b60e 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -157,7 +157,7 @@ android:label="@string/activity_edit_closed_group_title" android:screenOrientation="portrait" /> ) { fun TitledErrorText(titledText: TitledText?) { TitledText( titledText, - valueStyle = LocalTextStyle.current.copy(color = colorDestructive) + style = LocalTextStyle.current.copy(color = colorDestructive) ) } @@ -370,7 +370,7 @@ fun TitledErrorText(titledText: TitledText?) { fun TitledMonospaceText(titledText: TitledText?) { TitledText( titledText, - valueStyle = LocalTextStyle.current.copy(fontFamily = FontFamily.Monospace) + style = LocalTextStyle.current.copy(fontFamily = FontFamily.Monospace) ) } @@ -378,11 +378,11 @@ fun TitledMonospaceText(titledText: TitledText?) { fun TitledText( titledText: TitledText?, modifier: Modifier = Modifier, - valueStyle: TextStyle = LocalTextStyle.current, + style: TextStyle = LocalTextStyle.current, ) { titledText?.apply { TitledView(title, modifier) { - Text(text, style = valueStyle, modifier = Modifier.fillMaxWidth()) + Text(text, style = style, modifier = Modifier.fillMaxWidth()) } } } 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 29d4f4df2e..e806266baf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt @@ -93,7 +93,7 @@ import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideRequests import org.thoughtcrime.securesms.notifications.PushRegistry -import org.thoughtcrime.securesms.onboarding.startRecoveryPasswordActivity +import org.thoughtcrime.securesms.onboarding.recoverypassword.startRecoveryPasswordActivity import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.preferences.SettingsActivity import org.thoughtcrime.securesms.showMuteDialog @@ -101,6 +101,7 @@ import org.thoughtcrime.securesms.showSessionDialog import org.thoughtcrime.securesms.ui.AppTheme 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.h8 import org.thoughtcrime.securesms.ui.small @@ -365,12 +366,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(), Row { Text("Save your recovery password", style = MaterialTheme.typography.h8) Spacer(Modifier.requiredWidth(8.dp)) - Icon( - painter = painterResource(R.drawable.session_shield), - contentDescription = null, - modifier = Modifier.align(Alignment.CenterVertically) - .wrapContentSize(unbounded = true) - ) + SessionShieldIcon() } Text("Save your recovery password to make sure you don't lose access to your account.", style = MaterialTheme.typography.small) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/RecoveryPasswordActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/RecoveryPasswordActivity.kt deleted file mode 100644 index 821599ad01..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/RecoveryPasswordActivity.kt +++ /dev/null @@ -1,50 +0,0 @@ -package org.thoughtcrime.securesms.onboarding - -import android.content.ClipData -import android.content.ClipboardManager -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.widget.Toast -import network.loki.messenger.R -import org.session.libsession.utilities.TextSecurePreferences -import org.session.libsignal.crypto.MnemonicCodec -import org.session.libsignal.utilities.hexEncodedPrivateKey -import org.thoughtcrime.securesms.BaseActionBarActivity -import org.thoughtcrime.securesms.crypto.IdentityKeyUtil -import org.thoughtcrime.securesms.crypto.MnemonicUtilities - -class RecoveryPasswordActivity : BaseActionBarActivity() { - - private val seed by lazy { - var hexEncodedSeed = IdentityKeyUtil.retrieve(this, IdentityKeyUtil.LOKI_SEED) - if (hexEncodedSeed == null) { - hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(this).hexEncodedPrivateKey // Legacy account - } - val loadFileContents: (String) -> String = { fileName -> - MnemonicUtilities.loadFileContents(this, fileName) - } - MnemonicCodec(loadFileContents).encode(hexEncodedSeed!!, MnemonicCodec.Language.Configuration.english) - } - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - supportActionBar!!.title = resources.getString(R.string.activity_recovery_password) - } - - private fun revealSeed() { - TextSecurePreferences.setHasViewedSeed(this, true) - } - - private fun copySeed() { - revealSeed() - val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip = ClipData.newPlainText("Seed", seed) - clipboard.setPrimaryClip(clip) - Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show() - } -} - -fun Context.startRecoveryPasswordActivity() { - Intent(this, RecoveryPasswordActivity::class.java).also(::startActivity) -} 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 new file mode 100644 index 0000000000..82b0bd33c6 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/recoverypassword/RecoveryPasswordActivity.kt @@ -0,0 +1,154 @@ +package org.thoughtcrime.securesms.onboarding.recoverypassword + +import android.content.ClipData +import android.content.ClipboardManager +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.widget.Toast +import androidx.compose.foundation.border +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.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.ComposeView +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.unit.dp +import network.loki.messenger.R +import org.session.libsession.utilities.TextSecurePreferences +import org.session.libsignal.crypto.MnemonicCodec +import org.session.libsignal.utilities.hexEncodedPrivateKey +import org.thoughtcrime.securesms.BaseActionBarActivity +import org.thoughtcrime.securesms.crypto.IdentityKeyUtil +import org.thoughtcrime.securesms.crypto.MnemonicUtilities +import org.thoughtcrime.securesms.ui.AppTheme +import org.thoughtcrime.securesms.ui.CellWithPaddingAndMargin +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.classicDarkColors +import org.thoughtcrime.securesms.ui.colorDestructive +import org.thoughtcrime.securesms.ui.extraSmall +import org.thoughtcrime.securesms.ui.h8 + +class RecoveryPasswordActivity : BaseActionBarActivity() { + + private val seed by lazy { + var hexEncodedSeed = IdentityKeyUtil.retrieve(this, IdentityKeyUtil.LOKI_SEED) + if (hexEncodedSeed == null) { + hexEncodedSeed = IdentityKeyUtil.getIdentityKeyPair(this).hexEncodedPrivateKey // Legacy account + } + val loadFileContents: (String) -> String = { fileName -> + MnemonicUtilities.loadFileContents(this, fileName) + } + MnemonicCodec(loadFileContents).encode(hexEncodedSeed!!, MnemonicCodec.Language.Configuration.english) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + supportActionBar!!.title = resources.getString(R.string.activity_recovery_password) + + ComposeView(this) + .apply { setContent { RecoveryPassword() } } + .let(::setContentView) + } + + private fun revealSeed() { + TextSecurePreferences.setHasViewedSeed(this, true) + } + + private fun copySeed() { + revealSeed() + val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager + val clip = ClipData.newPlainText("Seed", seed) + clipboard.setPrimaryClip(clip) + Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show() + } +} + +@Preview +@Composable +fun PreviewMessageDetails( + @PreviewParameter(ThemeResPreviewParameterProvider::class) themeResId: Int +) { + PreviewTheme(themeResId) { + RecoveryPassword() + } +} + +@Composable +fun RecoveryPassword() { + AppTheme { + Column(verticalArrangement = Arrangement.spacedBy(16.dp)) { + RecoveryPasswordCell() + HideRecoveryPasswordCell() + } + } +} + + +@Composable +fun RecoveryPasswordCell() { + CellWithPaddingAndMargin { + Column { + Row { + Text("Recovery Password") + Spacer(Modifier.width(8.dp)) + SessionShieldIcon() + } + + Text("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.") + + Text( + "Voyage urban toyed maverick peculiar tuxedo penguin tree grass building listen speak withdraw terminal plane", + modifier = Modifier + .padding(vertical = 24.dp) + .border( + width = 1.dp, + color = classicDarkColors[3], + shape = RoundedCornerShape(11.dp) + ) + .padding(24.dp), + style = MaterialTheme.typography.extraSmall.copy(fontFamily = FontFamily.Monospace) + ) + + Row(horizontalArrangement = Arrangement.spacedBy(32.dp)) { + OutlineButton(text = stringResource(R.string.copy), modifier = Modifier.weight(1f), color = MaterialTheme.colors.onPrimary) {} + OutlineButton(text = "View QR", modifier = Modifier.weight(1f), color = MaterialTheme.colors.onPrimary) {} + } + } + } +} + +@Composable +fun HideRecoveryPasswordCell() { + CellWithPaddingAndMargin { + Row { + Column(Modifier.weight(1f)) { + Text(text = "Hide Recovery Password", style = MaterialTheme.typography.h8) + Text(text = "Permanently hide your recovery password on this device.") + } + OutlineButton( + "Hide", + modifier = Modifier.align(Alignment.CenterVertically), + color = colorDestructive + ) {} + } + } +} + +fun Context.startRecoveryPasswordActivity() { + Intent(this, RecoveryPasswordActivity::class.java).also(::startActivity) +} 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 f966b3f5e0..f650502cd9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt @@ -44,7 +44,7 @@ import org.thoughtcrime.securesms.home.PathActivity import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity import org.thoughtcrime.securesms.mms.GlideApp import org.thoughtcrime.securesms.mms.GlideRequests -import org.thoughtcrime.securesms.onboarding.startRecoveryPasswordActivity +import org.thoughtcrime.securesms.onboarding.recoverypassword.startRecoveryPasswordActivity import org.thoughtcrime.securesms.permissions.Permissions import org.thoughtcrime.securesms.preferences.appearance.AppearanceSettingsActivity import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints 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 3c540a4107..27370e0482 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Components.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight +import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.ButtonColors @@ -50,14 +51,19 @@ import org.thoughtcrime.securesms.components.ProfilePictureView import kotlin.math.roundToInt @Composable -fun OutlineButton(text: String, modifier: Modifier = Modifier, onClick: () -> Unit) { +fun OutlineButton( + text: String, + modifier: Modifier = Modifier, + color: Color = LocalExtraColors.current.prominentButtonColor, + onClick: () -> Unit +) { OutlinedButton( - modifier = modifier.size(108.dp, 34.dp), + modifier = modifier, onClick = onClick, - border = BorderStroke(1.dp, LocalExtraColors.current.prominentButtonColor), + border = BorderStroke(1.dp, color), shape = RoundedCornerShape(50), // = 50% percent colors = ButtonDefaults.outlinedButtonColors( - contentColor = LocalExtraColors.current.prominentButtonColor, + contentColor = color, backgroundColor = Color.Unspecified ) ) { @@ -294,3 +300,13 @@ fun Arc( ) } } + +@Composable +fun RowScope.SessionShieldIcon() { + Icon( + painter = painterResource(R.drawable.session_shield), + contentDescription = null, + modifier = Modifier.align(Alignment.CenterVertically) + .wrapContentSize(unbounded = true) + ) +} 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 95953ecff9..55acd90b49 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/ui/Themes.kt @@ -111,6 +111,7 @@ val sessionTypography = Typography( val Typography.base get() = defaultStyle(14.sp) val Typography.baseBold get() = boldStyle(14.sp) val Typography.small get() = defaultStyle(12.sp) +val Typography.extraSmall get() = defaultStyle(11.sp) val Typography.h7 get() = boldStyle(18.sp) val Typography.h8 get() = boldStyle(16.sp)