From d7d9d53ff3693caf2b9247209a5510d8a479d7c2 Mon Sep 17 00:00:00 2001 From: darken Date: Mon, 9 Mar 2026 13:40:52 +0100 Subject: [PATCH] refactor: Replace MaterialAlertDialogBuilder with Compose AlertDialog Replace all 11 instances of MaterialAlertDialogBuilder across 5 files with Compose AlertDialog. Use sealed dialog state per screen to prevent dialog stacking. Add shared ConfirmationDialog composable. Delete dead ErrorDialog.kt. --- .../common/compose/ConfirmationDialog.kt | 32 +++++ .../debug/recording/ui/RecorderActivity.kt | 69 ++++----- .../recording/ui/RecorderConsentDialog.kt | 67 ++++++--- .../darken/capod/common/error/ErrorDialog.kt | 19 --- .../main/ui/settings/support/SupportScreen.kt | 133 ++++++++++-------- .../support/contactform/ContactFormScreen.kt | 128 ++++++++++------- 6 files changed, 272 insertions(+), 176 deletions(-) create mode 100644 app/src/main/java/eu/darken/capod/common/compose/ConfirmationDialog.kt delete mode 100644 app/src/main/java/eu/darken/capod/common/error/ErrorDialog.kt diff --git a/app/src/main/java/eu/darken/capod/common/compose/ConfirmationDialog.kt b/app/src/main/java/eu/darken/capod/common/compose/ConfirmationDialog.kt new file mode 100644 index 00000000..89fd25a2 --- /dev/null +++ b/app/src/main/java/eu/darken/capod/common/compose/ConfirmationDialog.kt @@ -0,0 +1,32 @@ +package eu.darken.capod.common.compose + +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable + +@Composable +fun ConfirmationDialog( + title: String, + message: String, + confirmLabel: String, + dismissLabel: String, + onConfirm: () -> Unit, + onDismiss: () -> Unit, +) { + AlertDialog( + onDismissRequest = onDismiss, + title = { Text(text = title) }, + text = { Text(text = message) }, + confirmButton = { + TextButton(onClick = onConfirm) { + Text(text = confirmLabel) + } + }, + dismissButton = { + TextButton(onClick = onDismiss) { + Text(text = dismissLabel) + } + }, + ) +} diff --git a/app/src/main/java/eu/darken/capod/common/debug/recording/ui/RecorderActivity.kt b/app/src/main/java/eu/darken/capod/common/debug/recording/ui/RecorderActivity.kt index efcb0ad3..36b6c7c0 100644 --- a/app/src/main/java/eu/darken/capod/common/debug/recording/ui/RecorderActivity.kt +++ b/app/src/main/java/eu/darken/capod/common/debug/recording/ui/RecorderActivity.kt @@ -17,10 +17,11 @@ import androidx.lifecycle.compose.LifecycleResumeEffect import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.compose.ui.graphics.luminance import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.res.stringResource import androidx.core.view.WindowCompat -import com.google.android.material.dialog.MaterialAlertDialogBuilder import dagger.hilt.android.AndroidEntryPoint import eu.darken.capod.R +import eu.darken.capod.common.compose.ConfirmationDialog import eu.darken.capod.common.debug.logging.logTag import eu.darken.capod.common.theming.CapodTheme import eu.darken.capod.common.uix.Activity2 @@ -29,6 +30,11 @@ import eu.darken.capod.main.core.currentThemeState import eu.darken.capod.main.core.themeState import javax.inject.Inject +private sealed interface RecorderDialog { + data object SentConfirm : RecorderDialog + data object DeleteConfirm : RecorderDialog +} + @AndroidEntryPoint class RecorderActivity : Activity2() { @@ -58,6 +64,7 @@ class RecorderActivity : Activity2() { } var hasShared by remember { mutableStateOf(false) } + var dialog by remember { mutableStateOf(null) } LaunchedEffect(Unit) { vm.events.collect { event -> @@ -71,50 +78,44 @@ class RecorderActivity : Activity2() { } } - var showSentConfirm by remember { mutableStateOf(false) } - LifecycleResumeEffect(hasShared) { if (hasShared) { - showSentConfirm = true + dialog = RecorderDialog.SentConfirm hasShared = false } onPauseOrDispose {} } - if (showSentConfirm) { - LaunchedEffect(Unit) { - MaterialAlertDialogBuilder(this@RecorderActivity).apply { - setTitle(R.string.support_debuglog_sent_title) - setMessage(R.string.support_debuglog_sent_message) - setPositiveButton(R.string.general_done_action) { _, _ -> - showSentConfirm = false + when (dialog) { + is RecorderDialog.SentConfirm -> { + ConfirmationDialog( + title = stringResource(R.string.support_debuglog_sent_title), + message = stringResource(R.string.support_debuglog_sent_message), + confirmLabel = stringResource(R.string.general_done_action), + dismissLabel = stringResource(R.string.general_cancel_action), + onConfirm = { + dialog = null vm.discard() - } - setNegativeButton(R.string.general_cancel_action) { _, _ -> - showSentConfirm = false - } - setOnCancelListener { showSentConfirm = false } - }.show() + }, + onDismiss = { dialog = null }, + ) } - } - var showDeleteConfirm by remember { mutableStateOf(false) } - - if (showDeleteConfirm) { - LaunchedEffect(Unit) { - MaterialAlertDialogBuilder(this@RecorderActivity).apply { - setTitle(R.string.support_debuglog_session_delete_title) - setMessage(R.string.support_debuglog_session_delete_message) - setPositiveButton(R.string.profiles_delete_action) { _, _ -> - showDeleteConfirm = false + is RecorderDialog.DeleteConfirm -> { + ConfirmationDialog( + title = stringResource(R.string.support_debuglog_session_delete_title), + message = stringResource(R.string.support_debuglog_session_delete_message), + confirmLabel = stringResource(R.string.profiles_delete_action), + dismissLabel = stringResource(R.string.general_cancel_action), + onConfirm = { + dialog = null vm.discard() - } - setNegativeButton(R.string.general_cancel_action) { _, _ -> - showDeleteConfirm = false - } - setOnCancelListener { showDeleteConfirm = false } - }.show() + }, + onDismiss = { dialog = null }, + ) } + + null -> {} } val state by vm.state.collectAsStateWithLifecycle(initialValue = null) @@ -123,7 +124,7 @@ class RecorderActivity : Activity2() { state = it, onShare = { vm.share() }, onKeep = { vm.keep() }, - onDiscard = { showDeleteConfirm = true }, + onDiscard = { dialog = RecorderDialog.DeleteConfirm }, onPrivacyPolicy = { vm.goPrivacyPolicy() }, ) } diff --git a/app/src/main/java/eu/darken/capod/common/debug/recording/ui/RecorderConsentDialog.kt b/app/src/main/java/eu/darken/capod/common/debug/recording/ui/RecorderConsentDialog.kt index 306614be..eeb7f033 100644 --- a/app/src/main/java/eu/darken/capod/common/debug/recording/ui/RecorderConsentDialog.kt +++ b/app/src/main/java/eu/darken/capod/common/debug/recording/ui/RecorderConsentDialog.kt @@ -1,24 +1,55 @@ package eu.darken.capod.common.debug.recording.ui -import android.content.Context -import com.google.android.material.dialog.MaterialAlertDialogBuilder +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.unit.dp import eu.darken.capod.R -import eu.darken.capod.common.PrivacyPolicy -import eu.darken.capod.common.WebpageTool -class RecorderConsentDialog( - private val context: Context, - private val webpageTool: WebpageTool +@Composable +fun RecorderConsentDialog( + onStartRecord: () -> Unit, + onOpenPrivacyPolicy: () -> Unit, + onDismiss: () -> Unit, ) { - fun showDialog(onStartRecord: () -> Unit) { - MaterialAlertDialogBuilder(context).apply { - setTitle(R.string.support_debuglog_label) - setMessage(R.string.settings_debuglog_explanation) - setPositiveButton(R.string.debug_debuglog_record_action) { _, _ -> onStartRecord() } - setNegativeButton(R.string.general_cancel_action) { _, _ -> } - setNeutralButton(R.string.settings_privacy_policy_label) { _, _ -> - webpageTool.open(PrivacyPolicy.URL) + AlertDialog( + onDismissRequest = onDismiss, + title = { Text(text = stringResource(R.string.support_debuglog_label)) }, + text = { + Column(modifier = Modifier.fillMaxWidth()) { + Text(text = stringResource(R.string.settings_debuglog_explanation)) + Spacer(modifier = Modifier.height(8.dp)) + TextButton( + onClick = { + onOpenPrivacyPolicy() + onDismiss() + }, + modifier = Modifier.align(Alignment.End), + ) { + Text(text = stringResource(R.string.settings_privacy_policy_label)) + } } - }.show() - } -} \ No newline at end of file + }, + confirmButton = { + TextButton(onClick = { + onDismiss() + onStartRecord() + }) { + Text(text = stringResource(R.string.debug_debuglog_record_action)) + } + }, + dismissButton = { + TextButton(onClick = onDismiss) { + Text(text = stringResource(R.string.general_cancel_action)) + } + }, + ) +} diff --git a/app/src/main/java/eu/darken/capod/common/error/ErrorDialog.kt b/app/src/main/java/eu/darken/capod/common/error/ErrorDialog.kt deleted file mode 100644 index 89e593e3..00000000 --- a/app/src/main/java/eu/darken/capod/common/error/ErrorDialog.kt +++ /dev/null @@ -1,19 +0,0 @@ -package eu.darken.capod.common.error - -import android.content.Context -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import eu.darken.capod.R - -fun Throwable.asErrorDialogBuilder( - context: Context -) = MaterialAlertDialogBuilder(context).apply { - val error = this@asErrorDialogBuilder - val localizedError = error.localized(context) - - setTitle(localizedError.label) - setMessage(localizedError.description) - - setPositiveButton(android.R.string.ok) { _, _ -> - - } -} \ No newline at end of file diff --git a/app/src/main/java/eu/darken/capod/main/ui/settings/support/SupportScreen.kt b/app/src/main/java/eu/darken/capod/main/ui/settings/support/SupportScreen.kt index 61e28677..20e1ee28 100644 --- a/app/src/main/java/eu/darken/capod/main/ui/settings/support/SupportScreen.kt +++ b/app/src/main/java/eu/darken/capod/main/ui/settings/support/SupportScreen.kt @@ -14,7 +14,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.twotone.ArrowBack import androidx.compose.material.icons.automirrored.twotone.MenuBook @@ -25,6 +24,7 @@ import androidx.compose.material.icons.twotone.Delete import androidx.compose.material.icons.twotone.FiberManualRecord import androidx.compose.material.icons.twotone.Settings import androidx.compose.material.icons.twotone.Warning +import androidx.compose.material3.AlertDialog import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -32,6 +32,7 @@ import androidx.compose.material3.MaterialTheme import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable @@ -50,10 +51,10 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel -import com.google.android.material.dialog.MaterialAlertDialogBuilder import eu.darken.capod.R import eu.darken.capod.common.PrivacyPolicy import eu.darken.capod.common.WebpageTool +import eu.darken.capod.common.compose.ConfirmationDialog import eu.darken.capod.common.compose.Preview2 import eu.darken.capod.common.compose.PreviewWrapper import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -65,6 +66,13 @@ import eu.darken.capod.common.navigation.NavigationEventHandler import eu.darken.capod.common.settings.SettingsBaseItem import eu.darken.capod.common.settings.SettingsCategoryHeader +private sealed interface SupportDialog { + data object Consent : SupportDialog + data object ShortRecordingWarning : SupportDialog + data class DeleteSession(val sessionId: String) : SupportDialog + data object ClearLogs : SupportDialog +} + @Composable fun SupportScreenHost(vm: SupportViewModel = hiltViewModel()) { ErrorEventHandler(vm) @@ -78,19 +86,17 @@ fun SupportScreenHost(vm: SupportViewModel = hiltViewModel()) { val state by vm.state.collectAsStateWithLifecycle(initialValue = null) - var showShortRecordingWarning by remember { mutableStateOf(false) } + var dialog by remember { mutableStateOf(null) } LaunchedEffect(Unit) { vm.events.collect { event -> when (event) { SupportViewModel.Event.ShowConsentDialog -> { - RecorderConsentDialog(context, WebpageTool(context)).showDialog { - vm.startDebugLog() - } + dialog = SupportDialog.Consent } SupportViewModel.Event.ShowShortRecordingWarning -> { - showShortRecordingWarning = true + dialog = SupportDialog.ShortRecordingWarning } is SupportViewModel.Event.OpenRecorderActivity -> { @@ -103,12 +109,69 @@ fun SupportScreenHost(vm: SupportViewModel = hiltViewModel()) { } } - if (showShortRecordingWarning) { - ShortRecordingWarningDialog( - context = context, - onDismiss = { showShortRecordingWarning = false }, - onStopAnyway = { vm.forceStopDebugLog() }, - ) + when (val d = dialog) { + is SupportDialog.Consent -> { + RecorderConsentDialog( + onStartRecord = { + vm.startDebugLog() + }, + onOpenPrivacyPolicy = { + WebpageTool(context).open(PrivacyPolicy.URL) + }, + onDismiss = { dialog = null }, + ) + } + + is SupportDialog.ShortRecordingWarning -> { + AlertDialog( + onDismissRequest = { dialog = null }, + title = { Text(text = stringResource(R.string.debug_debuglog_short_recording_title)) }, + text = { Text(text = stringResource(R.string.debug_debuglog_short_recording_message)) }, + confirmButton = { + TextButton(onClick = { dialog = null }) { + Text(text = stringResource(R.string.debug_debuglog_short_recording_continue)) + } + }, + dismissButton = { + TextButton(onClick = { + dialog = null + vm.forceStopDebugLog() + }) { + Text(text = stringResource(R.string.debug_debuglog_short_recording_stop)) + } + }, + ) + } + + is SupportDialog.DeleteSession -> { + ConfirmationDialog( + title = stringResource(R.string.support_debuglog_session_delete_title), + message = stringResource(R.string.support_debuglog_session_delete_message), + confirmLabel = stringResource(R.string.profiles_delete_action), + dismissLabel = stringResource(R.string.general_cancel_action), + onConfirm = { + dialog = null + vm.deleteSession(d.sessionId) + }, + onDismiss = { dialog = null }, + ) + } + + is SupportDialog.ClearLogs -> { + ConfirmationDialog( + title = stringResource(R.string.support_debuglog_session_delete_title), + message = stringResource(R.string.support_debuglog_clear_all_message), + confirmLabel = stringResource(R.string.profiles_delete_action), + dismissLabel = stringResource(R.string.general_cancel_action), + onConfirm = { + dialog = null + vm.clearDebugLogs() + }, + onDismiss = { dialog = null }, + ) + } + + null -> {} } state?.let { @@ -122,53 +185,13 @@ fun SupportScreenHost(vm: SupportViewModel = hiltViewModel()) { onTroubleShooter = { vm.goToTroubleShooter() }, onDebugLogToggle = { vm.onDebugLogToggle() }, onOpenSession = { vm.openSession(it) }, - onDeleteSession = { id -> - MaterialAlertDialogBuilder(context).apply { - setTitle(R.string.support_debuglog_session_delete_title) - setMessage(R.string.support_debuglog_session_delete_message) - setPositiveButton(R.string.profiles_delete_action) { _, _ -> - vm.deleteSession(id) - } - setNegativeButton(R.string.general_cancel_action) { _, _ -> } - }.show() - }, + onDeleteSession = { id -> dialog = SupportDialog.DeleteSession(id) }, onStopRecording = { vm.onDebugLogToggle() }, - onClearLogs = { - MaterialAlertDialogBuilder(context).apply { - setTitle(R.string.support_debuglog_session_delete_title) - setMessage(R.string.support_debuglog_clear_all_message) - setPositiveButton(R.string.profiles_delete_action) { _, _ -> - vm.clearDebugLogs() - } - setNegativeButton(R.string.general_cancel_action) { _, _ -> } - }.show() - }, + onClearLogs = { dialog = SupportDialog.ClearLogs }, ) } } -@Composable -private fun ShortRecordingWarningDialog( - context: android.content.Context, - onDismiss: () -> Unit, - onStopAnyway: () -> Unit, -) { - LaunchedEffect(Unit) { - MaterialAlertDialogBuilder(context).apply { - setTitle(R.string.debug_debuglog_short_recording_title) - setMessage(R.string.debug_debuglog_short_recording_message) - setPositiveButton(R.string.debug_debuglog_short_recording_continue) { _, _ -> - onDismiss() - } - setNegativeButton(R.string.debug_debuglog_short_recording_stop) { _, _ -> - onDismiss() - onStopAnyway() - } - setOnCancelListener { onDismiss() } - }.show() - } -} - @Composable fun SupportScreen( state: SupportViewModel.State, diff --git a/app/src/main/java/eu/darken/capod/main/ui/settings/support/contactform/ContactFormScreen.kt b/app/src/main/java/eu/darken/capod/main/ui/settings/support/contactform/ContactFormScreen.kt index e096ddb6..dfe32d14 100644 --- a/app/src/main/java/eu/darken/capod/main/ui/settings/support/contactform/ContactFormScreen.kt +++ b/app/src/main/java/eu/darken/capod/main/ui/settings/support/contactform/ContactFormScreen.kt @@ -23,6 +23,7 @@ import androidx.compose.material.icons.twotone.BugReport import androidx.compose.material.icons.twotone.Cancel import androidx.compose.material.icons.twotone.Delete import androidx.compose.material.icons.twotone.Email +import androidx.compose.material3.AlertDialog import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.CircularProgressIndicator @@ -37,6 +38,7 @@ import androidx.compose.material3.Scaffold import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -55,15 +57,23 @@ import androidx.compose.ui.text.input.KeyboardCapitalization import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LifecycleResumeEffect -import com.google.android.material.dialog.MaterialAlertDialogBuilder import eu.darken.capod.R +import eu.darken.capod.common.PrivacyPolicy import eu.darken.capod.common.WebpageTool +import eu.darken.capod.common.compose.ConfirmationDialog import androidx.lifecycle.compose.collectAsStateWithLifecycle import eu.darken.capod.common.debug.recording.ui.RecorderConsentDialog import eu.darken.capod.common.error.ErrorEventHandler import eu.darken.capod.common.navigation.NavigationEventHandler import eu.darken.capod.main.ui.settings.support.contactform.ContactFormViewModel.Category +private sealed interface ContactFormDialog { + data object SentConfirm : ContactFormDialog + data object Consent : ContactFormDialog + data object ShortRecordingWarning : ContactFormDialog + data class DeleteSession(val sessionId: String) : ContactFormDialog +} + @Composable fun ContactFormScreenHost(vm: ContactFormViewModel = hiltViewModel()) { ErrorEventHandler(vm) @@ -73,36 +83,17 @@ fun ContactFormScreenHost(vm: ContactFormViewModel = hiltViewModel()) { val snackbarHostState = remember { SnackbarHostState() } var hasSentEmail by remember { mutableStateOf(false) } - var showSentConfirm by remember { mutableStateOf(false) } + var dialog by remember { mutableStateOf(null) } LifecycleResumeEffect(hasSentEmail) { vm.refreshLogSessions() if (hasSentEmail) { - showSentConfirm = true + dialog = ContactFormDialog.SentConfirm hasSentEmail = false } onPauseOrDispose {} } - if (showSentConfirm) { - LaunchedEffect(Unit) { - MaterialAlertDialogBuilder(context).apply { - setTitle(R.string.support_contact_sent_title) - setMessage(R.string.support_contact_sent_message) - setPositiveButton(R.string.general_done_action) { _, _ -> - showSentConfirm = false - vm.confirmSent() - } - setNegativeButton(R.string.general_cancel_action) { _, _ -> - showSentConfirm = false - } - setOnCancelListener { showSentConfirm = false } - }.show() - } - } - - var showShortRecordingWarning by remember { mutableStateOf(false) } - LaunchedEffect(Unit) { vm.events.collect { event -> when (event) { @@ -123,33 +114,79 @@ fun ContactFormScreenHost(vm: ContactFormViewModel = hiltViewModel()) { } ContactFormViewModel.Event.ShowConsentDialog -> { - RecorderConsentDialog(context, WebpageTool(context)).showDialog { - vm.doStartRecording() - } + dialog = ContactFormDialog.Consent } ContactFormViewModel.Event.ShowShortRecordingWarning -> { - showShortRecordingWarning = true + dialog = ContactFormDialog.ShortRecordingWarning } } } } - if (showShortRecordingWarning) { - LaunchedEffect(Unit) { - MaterialAlertDialogBuilder(context).apply { - setTitle(R.string.debug_debuglog_short_recording_title) - setMessage(R.string.debug_debuglog_short_recording_message) - setPositiveButton(R.string.debug_debuglog_short_recording_continue) { _, _ -> - showShortRecordingWarning = false - } - setNegativeButton(R.string.debug_debuglog_short_recording_stop) { _, _ -> - showShortRecordingWarning = false - vm.forceStopRecording() - } - setOnCancelListener { showShortRecordingWarning = false } - }.show() + when (val d = dialog) { + is ContactFormDialog.SentConfirm -> { + ConfirmationDialog( + title = stringResource(R.string.support_contact_sent_title), + message = stringResource(R.string.support_contact_sent_message), + confirmLabel = stringResource(R.string.general_done_action), + dismissLabel = stringResource(R.string.general_cancel_action), + onConfirm = { + dialog = null + vm.confirmSent() + }, + onDismiss = { dialog = null }, + ) } + + is ContactFormDialog.Consent -> { + RecorderConsentDialog( + onStartRecord = { + vm.doStartRecording() + }, + onOpenPrivacyPolicy = { + WebpageTool(context).open(PrivacyPolicy.URL) + }, + onDismiss = { dialog = null }, + ) + } + + is ContactFormDialog.ShortRecordingWarning -> { + AlertDialog( + onDismissRequest = { dialog = null }, + title = { Text(text = stringResource(R.string.debug_debuglog_short_recording_title)) }, + text = { Text(text = stringResource(R.string.debug_debuglog_short_recording_message)) }, + confirmButton = { + TextButton(onClick = { dialog = null }) { + Text(text = stringResource(R.string.debug_debuglog_short_recording_continue)) + } + }, + dismissButton = { + TextButton(onClick = { + dialog = null + vm.forceStopRecording() + }) { + Text(text = stringResource(R.string.debug_debuglog_short_recording_stop)) + } + }, + ) + } + + is ContactFormDialog.DeleteSession -> { + ConfirmationDialog( + title = stringResource(R.string.support_contact_debuglog_delete_title), + message = stringResource(R.string.support_contact_debuglog_delete_message), + confirmLabel = stringResource(R.string.profiles_delete_action), + dismissLabel = stringResource(R.string.general_cancel_action), + onConfirm = { + dialog = null + vm.deleteLogSession(d.sessionId) + }, + onDismiss = { dialog = null }, + ) + } + + null -> {} } val state by vm.state.collectAsStateWithLifecycle(initialValue = null) @@ -162,16 +199,7 @@ fun ContactFormScreenHost(vm: ContactFormViewModel = hiltViewModel()) { onDescriptionChange = { vm.updateDescription(it) }, onExpectedChange = { vm.updateExpectedBehavior(it) }, onSelectSession = { vm.selectLogSession(it) }, - onDeleteSession = { id -> - MaterialAlertDialogBuilder(context).apply { - setTitle(R.string.support_contact_debuglog_delete_title) - setMessage(R.string.support_contact_debuglog_delete_message) - setPositiveButton(R.string.profiles_delete_action) { _, _ -> - vm.deleteLogSession(id) - } - setNegativeButton(R.string.general_cancel_action) { _, _ -> } - }.show() - }, + onDeleteSession = { id -> dialog = ContactFormDialog.DeleteSession(id) }, onStartRecording = { vm.startRecording() }, onStopRecording = { vm.stopRecording() }, onSend = { vm.send() },