From 73f81075cec5fd9173edfc3e90fafd007f9ea2fd Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Fri, 12 Jun 2026 11:16:19 -0300 Subject: [PATCH] Removes second dialog and adds learnmore. --- .../MessageBackupsKeyRecordScreen.kt | 3 +- .../RecoveryKeyPasteWarningFragment.kt | 66 ++++++---------- .../warning/RecoveryKeyWarningSheetContent.kt | 77 ++++++++----------- .../warning/RecoveryKeyWarningSheetEvent.kt | 1 - app/src/main/res/values/strings.xml | 2 + 5 files changed, 57 insertions(+), 92 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt index 4b17253ef1..d8e1fdb8ca 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/subscription/MessageBackupsKeyRecordScreen.kt @@ -157,7 +157,6 @@ fun MessageBackupsKeyRecordScreen( val url = stringResource(R.string.recovery_key_phishing_support_url) val events: (RecoveryKeyWarningSheetEvent) -> Unit = { when (it) { - RecoveryKeyWarningSheetEvent.DoNotShareClick -> error("Not supported") RecoveryKeyWarningSheetEvent.GotItClick -> { onCopyToClipboardClick(backupKeyString) displayRecoveryKeyCopyWarning = false @@ -167,7 +166,7 @@ fun MessageBackupsKeyRecordScreen( displayRecoveryKeyCopyWarning = false } - RecoveryKeyWarningSheetEvent.PasteKeyClick -> error("Not supported") + RecoveryKeyWarningSheetEvent.DoNotShareClick -> error("Not supported") RecoveryKeyWarningSheetEvent.ShareKeyClick -> error("Not supported") } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyPasteWarningFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyPasteWarningFragment.kt index 164c656b1c..79df72f4fe 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyPasteWarningFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyPasteWarningFragment.kt @@ -5,22 +5,16 @@ package org.thoughtcrime.securesms.backup.v2.ui.warning -import android.app.Dialog import android.content.DialogInterface -import android.graphics.Color -import android.graphics.drawable.ColorDrawable import android.os.Bundle -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.ModalBottomSheet -import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource import androidx.fragment.app.setFragmentResult -import org.signal.core.ui.compose.BottomSheets -import org.signal.core.ui.compose.ComposeFullScreenDialogFragment +import org.signal.core.ui.compose.ComposeBottomSheetDialogFragment +import org.thoughtcrime.securesms.R +import org.thoughtcrime.securesms.backup.v2.ui.warning.RecoveryKeyPasteWarningFragment.Companion.REQUEST_KEY +import org.thoughtcrime.securesms.util.CommunicationActions /** * Displayed via the [org.thoughtcrime.securesms.components.settings.conversation.ConversationSettingsFragment] whenever the user @@ -30,7 +24,7 @@ import org.signal.core.ui.compose.ComposeFullScreenDialogFragment * indicating whether the user chose to proceed with the paste. The host can rely on this firing for * every dismissal path (paste, decline, or cancel) to restore its own state. */ -class RecoveryKeyPasteWarningFragment : ComposeFullScreenDialogFragment() { +class RecoveryKeyPasteWarningFragment : ComposeBottomSheetDialogFragment() { companion object { const val REQUEST_KEY = "recovery_key_request" @@ -38,13 +32,6 @@ class RecoveryKeyPasteWarningFragment : ComposeFullScreenDialogFragment() { private var shouldPaste = false - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - return super.onCreateDialog(savedInstanceState).apply { - window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) - window?.setWindowAnimations(0) - } - } - override fun onDismiss(dialog: DialogInterface) { setFragmentResult( REQUEST_KEY, @@ -56,10 +43,10 @@ class RecoveryKeyPasteWarningFragment : ComposeFullScreenDialogFragment() { super.onDismiss(dialog) } - @OptIn(ExperimentalMaterial3Api::class) @Composable - override fun DialogContent() { - var isDisplayingFinalWarningDialog by remember { mutableStateOf(false) } + override fun SheetContent() { + val context = LocalContext.current + val url = stringResource(R.string.recovery_key_phishing_support_url) val eventHandler: (RecoveryKeyWarningSheetEvent) -> Unit = { when (it) { @@ -67,34 +54,25 @@ class RecoveryKeyPasteWarningFragment : ComposeFullScreenDialogFragment() { dismissAllowingStateLoss() } - RecoveryKeyWarningSheetEvent.GotItClick -> error("Not supported for paste") - RecoveryKeyWarningSheetEvent.LearnMoreClick -> error("Not supported for paste") - RecoveryKeyWarningSheetEvent.PasteKeyClick -> { - shouldPaste = true + RecoveryKeyWarningSheetEvent.GotItClick -> { + error("Not supported for paste") + } + + RecoveryKeyWarningSheetEvent.LearnMoreClick -> { + CommunicationActions.openBrowserLink(context, url) dismissAllowingStateLoss() } RecoveryKeyWarningSheetEvent.ShareKeyClick -> { - isDisplayingFinalWarningDialog = true + shouldPaste = true + dismissAllowingStateLoss() } } } - if (isDisplayingFinalWarningDialog) { - RecoveryKeyWarningDialog( - events = eventHandler - ) - } else { - ModalBottomSheet( - onDismissRequest = { dismissAllowingStateLoss() }, - dragHandle = { BottomSheets.Handle() }, - sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) - ) { - RecoveryKeyWarningSheetContent( - clipStage = ClipStage.PASTE, - events = eventHandler - ) - } - } + RecoveryKeyWarningSheetContent( + clipStage = ClipStage.PASTE, + events = eventHandler + ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyWarningSheetContent.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyWarningSheetContent.kt index b564a0415b..eab8e09cc5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyWarningSheetContent.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyWarningSheetContent.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text @@ -22,16 +23,17 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource -import androidx.compose.ui.text.AnnotatedString +import androidx.compose.ui.text.LinkAnnotation import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.TextLinkStyles import androidx.compose.ui.text.buildAnnotatedString import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.withLink import androidx.compose.ui.text.withStyle import androidx.compose.ui.unit.dp import org.signal.core.ui.compose.Buttons import org.signal.core.ui.compose.DayNightPreviews -import org.signal.core.ui.compose.Dialogs import org.signal.core.ui.compose.Previews import org.signal.core.ui.compose.horizontalGutters import org.thoughtcrime.securesms.R @@ -64,17 +66,32 @@ fun RecoveryKeyWarningSheetContent( modifier = Modifier.padding(bottom = 12.dp) ) - val signalWillNeverMessageYou = stringResource(R.string.RecoveryKeyWarningSheetContent__signal_will_never_message_you) - val recoveryKeyWarningBody = stringResource(R.string.RecoveryKeyWarningSheetContent__for_your_recovery_key_never_respond) - Text( text = buildAnnotatedString { withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) { - append(signalWillNeverMessageYou) + append(stringResource(R.string.RecoveryKeyWarningSheetContent__signal_will_never_message_you)) } append(" ") - append(recoveryKeyWarningBody) + append(stringResource(R.string.RecoveryKeyWarningSheetContent__for_your_recovery_key_never_respond)) + + if (clipStage == ClipStage.PASTE) { + append(" ") + withLink( + link = LinkAnnotation.Clickable( + tag = "learn-more", + styles = TextLinkStyles( + style = SpanStyle( + color = MaterialTheme.colorScheme.primary + ) + ) + ) { + events(RecoveryKeyWarningSheetEvent.LearnMoreClick) + } + ) { + append(stringResource(R.string.RecoveryKeyWarningSheetContent__learn_more_period)) + } + } }, textAlign = TextAlign.Center, color = MaterialTheme.colorScheme.onSurfaceVariant, @@ -113,40 +130,18 @@ fun PasteActionButtons(events: (RecoveryKeyWarningSheetEvent) -> Unit) { Text(text = stringResource(R.string.RecoveryKeyWarningSheetContent__do_not_share_key)) } - TextButton(onClick = { - events(RecoveryKeyWarningSheetEvent.ShareKeyClick) - }) { + TextButton( + colors = ButtonDefaults.textButtonColors( + contentColor = MaterialTheme.colorScheme.error + ), + onClick = { + events(RecoveryKeyWarningSheetEvent.ShareKeyClick) + } + ) { Text(text = stringResource(R.string.RecoveryKeyWarningSheetContent__share_key)) } } -@Composable -fun RecoveryKeyWarningDialog(events: (RecoveryKeyWarningSheetEvent) -> Unit) { - val bodyIntro = stringResource(R.string.RecoveryKeyWarningDialog__do_not_share_your_recovery_key_with_anyone) - val bodyEmphasis = stringResource(R.string.RecoveryKeyWarningDialog__signal_will_never_message_you_for_your_recovery_key) - val bodyOutro = stringResource(R.string.RecoveryKeyWarningDialog__never_respond_to_a_chat) - - Dialogs.SimpleAlertDialog( - title = AnnotatedString(stringResource(R.string.RecoveryKeyWarningDialog__do_not_share_recovery_key)), - body = buildAnnotatedString { - append(bodyIntro) - append(" ") - - withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) { - append(bodyEmphasis) - } - - append(" ") - append(bodyOutro) - }, - confirm = AnnotatedString(stringResource(R.string.RecoveryKeyWarningDialog__paste_key)), - confirmColor = MaterialTheme.colorScheme.error, - dismiss = AnnotatedString(stringResource(R.string.RecoveryKeyWarningDialog__dont_share)), - onConfirm = { events(RecoveryKeyWarningSheetEvent.PasteKeyClick) }, - onDeny = { events(RecoveryKeyWarningSheetEvent.DoNotShareClick) } - ) -} - enum class ClipStage { COPY, PASTE @@ -175,11 +170,3 @@ private fun RecoveryKeyWarningSheetContentPastePreview() { ) } } - -@DayNightPreviews -@Composable -private fun RecoveryKeyWarningDialogPreview() { - Previews.Preview { - RecoveryKeyWarningDialog(events = {}) - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyWarningSheetEvent.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyWarningSheetEvent.kt index 7a61317dbb..1a5da458e6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyWarningSheetEvent.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ui/warning/RecoveryKeyWarningSheetEvent.kt @@ -8,7 +8,6 @@ package org.thoughtcrime.securesms.backup.v2.ui.warning sealed interface RecoveryKeyWarningSheetEvent { data object DoNotShareClick : RecoveryKeyWarningSheetEvent data object ShareKeyClick : RecoveryKeyWarningSheetEvent - data object PasteKeyClick : RecoveryKeyWarningSheetEvent data object GotItClick : RecoveryKeyWarningSheetEvent data object LearnMoreClick : RecoveryKeyWarningSheetEvent } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9cc6350492..9ebcd0c1c0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -9946,6 +9946,8 @@ Got it Learn more + + Learn more. Do not share key