Add hide password dialogs

This commit is contained in:
andrew 2023-11-30 00:45:53 +10:30
parent a256a04154
commit 62ef9d3ed4
6 changed files with 73 additions and 15 deletions

View File

@ -105,7 +105,7 @@ class SessionDialogBuilder(val context: Context) {
fun destructiveButton(
@StringRes text: Int,
@StringRes contentDescription: Int,
@StringRes contentDescription: Int = text,
listener: () -> Unit = {}
) = button(
text,

View File

@ -46,6 +46,7 @@ import androidx.compose.ui.unit.dp
import network.loki.messenger.R
import org.session.libsession.utilities.TextSecurePreferences
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.LocalExtraColors
@ -68,7 +69,7 @@ class RecoveryPasswordActivity : BaseActionBarActivity() {
ComposeView(this).apply {
setContent {
RecoveryPassword(viewModel.seed, viewModel.qrBitmap) { copySeed() }
RecoveryPassword(viewModel.seed, viewModel.qrBitmap, { copySeed() }) { onHide() }
}
}.let(::setContentView)
}
@ -84,6 +85,29 @@ class RecoveryPasswordActivity : BaseActionBarActivity() {
clipboard.setPrimaryClip(clip)
Toast.makeText(this, R.string.copied_to_clipboard, Toast.LENGTH_SHORT).show()
}
private fun onHide() {
showSessionDialog {
title("Hide Recovery Password Permanently")
text("Without your recovery password, you cannot load your account on new devices.\n" +
"\n" +
"We strongly recommend you save your recovery password in a safe and secure place before continuing.")
destructiveButton(R.string.continue_2) { onHideConfirm() }
button(R.string.cancel) {}
}
}
private fun onHideConfirm() {
showSessionDialog {
title("Hide Recovery Password Permanently")
text("Are you sure you want to permanently hide your recovery password on this device? This cannot be undone.")
button(R.string.cancel) {}
destructiveButton(R.string.yes) {
viewModel.permanentlyHidePassword()
finish()
}
}
}
}
@Preview
@ -97,7 +121,12 @@ fun PreviewMessageDetails(
}
@Composable
fun RecoveryPassword(seed: String = "", qrBitmap: Bitmap? = null, copySeed:() -> Unit = {}) {
fun RecoveryPassword(
seed: String = "",
qrBitmap: Bitmap? = null,
copySeed:() -> Unit = {},
onHide:() -> Unit = {}
) {
AppTheme {
Column(
verticalArrangement = Arrangement.spacedBy(16.dp),
@ -105,7 +134,7 @@ fun RecoveryPassword(seed: String = "", qrBitmap: Bitmap? = null, copySeed:() ->
.padding(bottom = 16.dp)
) {
RecoveryPasswordCell(seed, qrBitmap, copySeed)
HideRecoveryPasswordCell()
HideRecoveryPasswordCell(onHide)
}
}
}
@ -194,7 +223,7 @@ fun RecoveryPasswordCell(seed: String = "", qrBitmap: Bitmap? = null, copySeed:(
private fun MutableState<Boolean>.toggle() { value = !value }
@Composable
fun HideRecoveryPasswordCell() {
fun HideRecoveryPasswordCell(onHide: () -> Unit = {}) {
CellWithPaddingAndMargin {
Row {
Column(Modifier.weight(1f)) {
@ -205,7 +234,7 @@ fun HideRecoveryPasswordCell() {
"Hide",
modifier = Modifier.align(Alignment.CenterVertically),
color = colorDestructive
) {}
) { onHide() }
}
}
}

View File

@ -3,7 +3,9 @@ package org.thoughtcrime.securesms.onboarding.recoverypassword
import android.app.Application
import android.graphics.Bitmap
import androidx.lifecycle.AndroidViewModel
import androidx.preference.PreferenceFragmentCompat.OnPreferenceStartFragmentCallback
import dagger.hilt.android.lifecycle.HiltViewModel
import org.session.libsession.utilities.AppTextSecurePreferences
import org.session.libsession.utilities.TextSecurePreferences
import org.session.libsignal.crypto.MnemonicCodec
import org.session.libsignal.utilities.hexEncodedPrivateKey
@ -18,6 +20,12 @@ class RecoveryPasswordViewModel @Inject constructor(
private val application: Application
): AndroidViewModel(application) {
val prefs = AppTextSecurePreferences(application)
fun permanentlyHidePassword() {
prefs.setHidePassword(true)
}
val seed by lazy {
val hexEncodedSeed = IdentityKeyUtil.retrieve(application, IdentityKeyUtil.LOKI_SEED)
?: IdentityKeyUtil.getIdentityKeyPair(application).hexEncodedPrivateKey // Legacy account

View File

@ -19,6 +19,7 @@ import android.view.MenuItem
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
import androidx.core.view.isGone
import androidx.core.view.isVisible
import dagger.hilt.android.AndroidEntryPoint
import network.loki.messenger.BuildConfig
@ -64,6 +65,10 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
@Inject
lateinit var configFactory: ConfigFactory
@Inject
lateinit var prefs: TextSecurePreferences
private lateinit var binding: ActivitySettingsBinding
private var displayNameEditActionMode: ActionMode? = null
@ -86,13 +91,17 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
super.onCreate(savedInstanceState, isReady)
binding = ActivitySettingsBinding.inflate(layoutInflater)
setContentView(binding.root)
val displayName = getDisplayName()
glide = GlideApp.with(this)
with(binding) {
}
override fun onStart() {
super.onStart()
binding.run {
setupProfilePictureView(profilePictureView)
profilePictureView.setOnClickListener { showEditProfilePictureUI() }
ctnGroupNameSection.setOnClickListener { startActionMode(DisplayNameEditActionModeCallback()) }
btnGroupNameDisplay.text = displayName
btnGroupNameDisplay.text = getDisplayName()
publicKeyTextView.text = hexEncodedPublicKey
copyButton.setOnClickListener { copyPublicKey() }
shareButton.setOnClickListener { sharePublicKey() }
@ -105,7 +114,8 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
appearanceButton.setOnClickListener { showAppearanceSettings() }
inviteFriendButton.setOnClickListener { sendInvitation() }
helpButton.setOnClickListener { showHelp() }
seedButton.setOnClickListener { showSeed() }
passwordButton.isGone = prefs.getHidePassword()
passwordButton.setOnClickListener { showPassword() }
clearAllDataButton.setOnClickListener { clearAllData() }
versionTextView.text = String.format(getString(R.string.version_s), "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
}
@ -384,7 +394,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
show(intent)
}
private fun showSeed() {
private fun showPassword() {
startRecoveryPasswordActivity()
}

View File

@ -369,14 +369,14 @@
android:background="?colorDividerBackground" />
<RelativeLayout
android:id="@+id/seedButton"
android:id="@+id/passwordButton"
android:background="?selectableItemBackground"
android:paddingHorizontal="@dimen/large_spacing"
android:layout_width="match_parent"
android:layout_height="@dimen/setting_button_height"
android:contentDescription="@string/AccessibilityId_recovery_password">
<ImageView
android:id="@+id/seedContainer"
android:id="@+id/passwordContainer"
android:layout_width="@dimen/small_profile_picture_size"
android:layout_height="@dimen/small_profile_picture_size"
android:layout_alignParentStart="true"
@ -393,7 +393,7 @@
android:layout_marginHorizontal="@dimen/medium_spacing"
android:textStyle="bold"
android:gravity="center"
android:layout_toEndOf="@+id/seedContainer"
android:layout_toEndOf="@+id/passwordContainer"
android:text="@string/activity_settings_recovery_password_button_title" />
</RelativeLayout>

View File

@ -18,6 +18,7 @@ import org.session.libsession.utilities.TextSecurePreferences.Companion.CALL_NOT
import org.session.libsession.utilities.TextSecurePreferences.Companion.CLASSIC_DARK
import org.session.libsession.utilities.TextSecurePreferences.Companion.CLASSIC_LIGHT
import org.session.libsession.utilities.TextSecurePreferences.Companion.FOLLOW_SYSTEM_SETTINGS
import org.session.libsession.utilities.TextSecurePreferences.Companion.HIDE_PASSWORD
import org.session.libsession.utilities.TextSecurePreferences.Companion.LAST_VACUUM_TIME
import org.session.libsession.utilities.TextSecurePreferences.Companion.LEGACY_PREF_KEY_SELECTED_UI_MODE
import org.session.libsession.utilities.TextSecurePreferences.Companion.OCEAN_DARK
@ -30,6 +31,7 @@ import java.io.IOException
import java.util.Arrays
import java.util.Date
import javax.inject.Inject
import javax.inject.Singleton
interface TextSecurePreferences {
@ -182,6 +184,8 @@ interface TextSecurePreferences {
fun hasForcedNewConfig(): Boolean
fun hasPreference(key: String): Boolean
fun clearAll()
fun getHidePassword(): Boolean
fun setHidePassword(value: Boolean)
companion object {
val TAG = TextSecurePreferences::class.simpleName
@ -283,6 +287,7 @@ interface TextSecurePreferences {
const val SELECTED_STYLE = "pref_selected_style" // classic_dark/light, ocean_dark/light
const val FOLLOW_SYSTEM_SETTINGS = "pref_follow_system" // follow system day/night
const val HIDE_PASSWORD = "pref_hide_password"
const val LEGACY_PREF_KEY_SELECTED_UI_MODE = "SELECTED_UI_MODE" // this will be cleared upon launching app, for users migrating to theming build
const val CLASSIC_DARK = "classic.dark"
@ -1016,6 +1021,7 @@ interface TextSecurePreferences {
}
}
@Singleton
class AppTextSecurePreferences @Inject constructor(
@ApplicationContext private val context: Context
): TextSecurePreferences {
@ -1711,4 +1717,9 @@ class AppTextSecurePreferences @Inject constructor(
getDefaultSharedPreferences(context).edit().clear().commit()
}
}
override fun getHidePassword() = getBooleanPreference(HIDE_PASSWORD, false)
override fun setHidePassword(value: Boolean) {
setBooleanPreference(HIDE_PASSWORD, value)
}
}