tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit d619745e1b6843b64cb9b79db651a460b029e4be
parent a69a7f3a76482340340cad04819070a7fd6e8a5b
Author: Gabriel Luong <gabriel.luong@gmail.com>
Date:   Tue,  2 Dec 2025 16:41:27 +0000

Bug 1993368 - Part 36: Migrate UnsubmittedCrashDialog to M3 color tokens r=android-reviewers,007

- Simplified CrashCard composable method to have 2 separate composable functions to render the dialog content.
- Migrated the acorn color tokens to use M3 color tokens.
- Used PreviewParameterProvider to simplify the Composable Previews.
- Figma: https://www.figma.com/design/CaopY3iqHHpyLYjhhR78wI/In-app-Crash-Reporter?node-id=600-2098&m=dev

- M3 update of the dialog will be filed as a followup.

Differential Revision: https://phabricator.services.mozilla.com/D274539

Diffstat:
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/crashes/UnsubmittedCrashDialog.kt | 348+++++++++++++++++++++++++++++++++++++++++--------------------------------------
1 file changed, 180 insertions(+), 168 deletions(-)

diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/crashes/UnsubmittedCrashDialog.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/crashes/UnsubmittedCrashDialog.kt @@ -8,10 +8,8 @@ import android.app.Dialog import android.content.Context import android.os.Bundle import android.view.ViewGroup -import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -22,10 +20,9 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Checkbox -import androidx.compose.material3.CheckboxDefaults import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.material3.Text -import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -33,7 +30,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.ViewCompositionStrategy @@ -42,8 +38,11 @@ import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.tooling.preview.PreviewLightDark +import androidx.compose.ui.tooling.preview.PreviewParameter +import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp import androidx.fragment.app.DialogFragment +import mozilla.components.compose.base.button.TextButton import mozilla.components.lib.crash.store.CrashAction import org.mozilla.fenix.R import org.mozilla.fenix.compose.LinkText @@ -71,18 +70,12 @@ class UnsubmittedCrashDialog( setViewCompositionStrategy(ViewCompositionStrategy.DisposeOnViewTreeLifecycleDestroyed) setContent { FirefoxTheme { - Box( - modifier = Modifier - .clip(RoundedCornerShape(8.dp)) - .background(FirefoxTheme.colors.layer1), - ) { - CrashCard( - dismiss = ::dismiss, - dispatcher = dispatcher, - crashIDs = crashIDs, - cardContext = localContext, - ) - } + CrashCard( + dismiss = ::dismiss, + dispatcher = dispatcher, + crashIDs = crashIDs, + cardContext = localContext, + ) } } }, @@ -101,7 +94,6 @@ class UnsubmittedCrashDialog( } } -@Suppress("LongMethod") @Composable private fun CrashCard( dismiss: () -> Unit, @@ -109,11 +101,9 @@ private fun CrashCard( crashIDs: List<String>?, cardContext: Context?, ) { - val requestedByDevs = !crashIDs.isNullOrEmpty() - val context = LocalContext.current - dispatcher(CrashAction.PromptShown) + val requestedByDevs = !crashIDs.isNullOrEmpty() val msg = if (requestedByDevs) { if (crashIDs.size == 1) { stringResource( @@ -134,150 +124,93 @@ private fun CrashCard( ) } + Surface( + shape = RoundedCornerShape(8.dp), + ) { + if (!requestedByDevs) { + CrashDialog( + msg = msg, + dismiss = dismiss, + dispatcher = dispatcher, + ) + } else { + CrashPullDialog( + msg = msg, + dismiss = dismiss, + dispatcher = dispatcher, + crashIDs = crashIDs, + cardContext = cardContext, + ) + } + } +} + +@Composable +private fun CrashDialog( + msg: String, + dismiss: () -> Unit, + dispatcher: (action: CrashAction) -> Unit, +) { var checkboxChecked by remember { mutableStateOf(false) } - if (!requestedByDevs) { - Column( + Column( + modifier = Modifier + .width(280.dp) + .padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 0.dp), + verticalArrangement = Arrangement.spacedBy(16.dp), + ) { + Text( + text = msg, + style = FirefoxTheme.typography.headline7, modifier = Modifier - .width(280.dp) - .padding(top = 16.dp, start = 16.dp, end = 16.dp, bottom = 0.dp), - verticalArrangement = Arrangement.spacedBy(16.dp), + .semantics { heading() }, + ) + + AnnotatedStringBody() + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.widthIn(max = 248.dp), ) { - Text( - text = msg, - color = FirefoxTheme.colors.textPrimary, - style = FirefoxTheme.typography.headline7, - modifier = Modifier - .semantics { heading() }, + Checkbox( + checked = checkboxChecked, + onCheckedChange = { checkboxChecked = it }, + modifier = Modifier.padding(start = 0.dp, end = 0.dp), ) - AnnotatedStringBody() - - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.widthIn(max = 248.dp), - ) { - Checkbox( - checked = checkboxChecked, - colors = CheckboxDefaults.colors( - checkedColor = FirefoxTheme.colors.formSelected, - uncheckedColor = FirefoxTheme.colors.formDefault, - ), - onCheckedChange = { checkboxChecked = it }, - modifier = Modifier.padding(start = 0.dp, end = 0.dp), - ) - Text( - text = stringResource(R.string.unsubmitted_crash_dialog_checkbox_label), - color = FirefoxTheme.colors.textPrimary, - style = FirefoxTheme.typography.subtitle1, - ) - } - Row( - horizontalArrangement = Arrangement.spacedBy( - space = 8.dp, - alignment = Alignment.End, - ), - modifier = Modifier.fillMaxWidth(), - ) { - TextButton( - onClick = { - dispatcher(CrashAction.CancelTapped) - dismiss() - }, - ) { - Text( - text = stringResource(R.string.unsubmitted_crash_dialog_negative_button_2), - color = MaterialTheme.colorScheme.tertiary, - style = FirefoxTheme.typography.button, - ) - } - TextButton( - onClick = { - dispatcher( - CrashAction.ReportTapped( - checkboxChecked, - listOf(), - ), - ) - dismiss() - }, - ) { - Text( - text = stringResource(R.string.unsubmitted_crash_dialog_positive_button_2), - color = MaterialTheme.colorScheme.tertiary, - style = FirefoxTheme.typography.button, - ) - } - } - } - } else { - Column(modifier = Modifier.padding(16.dp)) { Text( - text = msg, - modifier = Modifier - .semantics { heading() }, - color = FirefoxTheme.colors.textPrimary, - style = FirefoxTheme.typography.headline5, + text = stringResource(R.string.unsubmitted_crash_dialog_checkbox_label), + style = FirefoxTheme.typography.subtitle1, ) + } - Spacer(modifier = Modifier.height(16.dp)) - - Row( - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = stringResource(R.string.unsubmitted_crash_requested_by_devs_learn_more).uppercase(), - color = FirefoxTheme.colors.actionPrimary, - modifier = Modifier.clickable { - if (cardContext != null) { - SupportUtils.launchSandboxCustomTab( - context = cardContext, - url = SupportUtils.getSumoURLForTopic( - context = cardContext, - topic = SupportUtils.SumoTopic.REQUESTED_CRASH_MINIDUMP, - ), - ) - } - }, - ) - Text( - text = stringResource(R.string.unsubmitted_crash_requested_by_devs_dialog_never_button).uppercase(), - color = FirefoxTheme.colors.textSecondary, - modifier = Modifier.clickable { - dispatcher(CrashAction.CancelForEverTapped) - dismiss() - }, - ) - } - Spacer(modifier = Modifier.height(16.dp)) + Row( + horizontalArrangement = Arrangement.spacedBy( + space = 8.dp, + alignment = Alignment.End, + ), + modifier = Modifier.fillMaxWidth(), + ) { + TextButton( + text = stringResource(R.string.unsubmitted_crash_dialog_negative_button_2), + onClick = { + dispatcher(CrashAction.CancelTapped) + dismiss() + }, + ) - Row( - horizontalArrangement = Arrangement.SpaceBetween, - modifier = Modifier.fillMaxWidth(), - ) { - Text( - text = stringResource(R.string.unsubmitted_crash_dialog_negative_button).uppercase(), - color = FirefoxTheme.colors.textSecondary, - modifier = Modifier.clickable { - dispatcher(CrashAction.CancelTapped) - dismiss() - }, - ) - Text( - text = stringResource(R.string.unsubmitted_crash_dialog_positive_button).uppercase(), - color = FirefoxTheme.colors.textSecondary, - modifier = Modifier.clickable { - dispatcher( - CrashAction.ReportTapped( - automaticallySendChecked = false, - crashIDs = crashIDs, - ), - ) - dismiss() - }, - ) - } + TextButton( + text = stringResource(R.string.unsubmitted_crash_dialog_positive_button_2), + onClick = { + dispatcher( + CrashAction.ReportTapped( + checkboxChecked, + listOf(), + ), + ) + dismiss() + }, + ) } } } @@ -306,7 +239,7 @@ private fun AnnotatedStringBody() { stringResource(R.string.unsubmitted_crash_dialog_learn_more), ), linkTextStates = listOf(linkStateLearnMore), - style = FirefoxTheme.typography.body2.copy(FirefoxTheme.colors.textPrimary), + style = FirefoxTheme.typography.body2, linkTextColor = MaterialTheme.colorScheme.tertiary, linkTextDecoration = TextDecoration.Underline, textAlign = null, @@ -314,30 +247,109 @@ private fun AnnotatedStringBody() { ) } -@PreviewLightDark @Composable -private fun CrashDialogPreview() { - FirefoxTheme { - Box(Modifier.background(FirefoxTheme.colors.layer1)) { - CrashCard( - dismiss = {}, - dispatcher = {}, - crashIDs = null, - cardContext = null, +private fun CrashPullDialog( + msg: String, + dismiss: () -> Unit, + dispatcher: (action: CrashAction) -> Unit, + crashIDs: List<String>, + cardContext: Context?, +) { + Column(modifier = Modifier.padding(16.dp)) { + Text( + text = msg, + modifier = Modifier + .semantics { heading() }, + style = FirefoxTheme.typography.headline5, + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth(), + ) { + Text( + text = stringResource(R.string.unsubmitted_crash_requested_by_devs_learn_more).uppercase(), + color = MaterialTheme.colorScheme.tertiary, + modifier = Modifier.clickable { + if (cardContext != null) { + SupportUtils.launchSandboxCustomTab( + context = cardContext, + url = SupportUtils.getSumoURLForTopic( + context = cardContext, + topic = SupportUtils.SumoTopic.REQUESTED_CRASH_MINIDUMP, + ), + ) + } + }, + ) + + Text( + text = stringResource(R.string.unsubmitted_crash_requested_by_devs_dialog_never_button).uppercase(), + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.clickable { + dispatcher(CrashAction.CancelForEverTapped) + dismiss() + }, + ) + } + + Spacer(modifier = Modifier.height(16.dp)) + + Row( + horizontalArrangement = Arrangement.SpaceBetween, + modifier = Modifier.fillMaxWidth(), + ) { + Text( + text = stringResource(R.string.unsubmitted_crash_dialog_negative_button).uppercase(), + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.clickable { + dispatcher(CrashAction.CancelTapped) + dismiss() + }, + ) + + Text( + text = stringResource(R.string.unsubmitted_crash_dialog_positive_button).uppercase(), + color = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.clickable { + dispatcher( + CrashAction.ReportTapped( + automaticallySendChecked = false, + crashIDs = crashIDs, + ), + ) + dismiss() + }, ) } } } +private data class CrashDialogState( + val crashIDs: List<String>?, +) + +private class CrashDialogPreviewProvider : PreviewParameterProvider<CrashDialogState> { + override val values = sequenceOf( + CrashDialogState(crashIDs = null), + CrashDialogState(crashIDs = listOf("12345")), + CrashDialogState(crashIDs = listOf("12345", "67890")), + ) +} + @PreviewLightDark @Composable -private fun CrashPullDialogPreview() { +private fun UnsubmittedCrashDialogPreview( + @PreviewParameter(CrashDialogPreviewProvider::class) state: CrashDialogState, +) { FirefoxTheme { - Box(Modifier.background(FirefoxTheme.colors.layer1)) { + Column(modifier = Modifier.padding(all = 16.dp)) { CrashCard( dismiss = {}, dispatcher = {}, - crashIDs = listOf("12345", "67890"), + crashIDs = state.crashIDs, cardContext = null, ) }