Iterate on Save change dialog.

This commit is contained in:
Benoit Marty 2025-12-03 14:35:52 +01:00 committed by Benoit Marty
parent 5bd194b2b6
commit eeef1b11ea
10 changed files with 36 additions and 25 deletions

View file

@ -66,8 +66,9 @@ fun CreatePollView(
BackHandler(onBack = navBack) BackHandler(onBack = navBack)
if (state.showBackConfirmation) { if (state.showBackConfirmation) {
SaveChangesDialog( SaveChangesDialog(
onSubmitClick = { state.eventSink(CreatePollEvents.NavBack) }, onSaveClick = { state.eventSink(CreatePollEvents.Save) },
onDismiss = { state.eventSink(CreatePollEvents.HideConfirmation) } onDiscardClick = { state.eventSink(CreatePollEvents.NavBack) },
onDismiss = { state.eventSink(CreatePollEvents.HideConfirmation) },
) )
} }
if (state.showDeleteConfirmation) { if (state.showDeleteConfirmation) {

View file

@ -147,8 +147,9 @@ fun EditUserProfileView(
when (confirming) { when (confirming) {
is AsyncAction.ConfirmingCancellation -> { is AsyncAction.ConfirmingCancellation -> {
SaveChangesDialog( SaveChangesDialog(
onSubmitClick = { state.eventSink(EditUserProfileEvents.Exit) }, onSaveClick = { state.eventSink(EditUserProfileEvents.Save) },
onDismiss = { state.eventSink(EditUserProfileEvents.CloseDialog) } onDiscardClick = { state.eventSink(EditUserProfileEvents.Exit) },
onDismiss = { state.eventSink(EditUserProfileEvents.CloseDialog) },
) )
} }
} }

View file

@ -20,7 +20,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import io.element.android.features.rolesandpermissions.impl.R import io.element.android.features.rolesandpermissions.impl.R
import io.element.android.libraries.designsystem.components.async.AsyncActionView import io.element.android.libraries.designsystem.components.async.AsyncActionView
import io.element.android.libraries.designsystem.components.button.BackButton import io.element.android.libraries.designsystem.components.button.BackButton
import io.element.android.libraries.designsystem.components.dialogs.ConfirmationDialog import io.element.android.libraries.designsystem.components.dialogs.SaveChangesDialog
import io.element.android.libraries.designsystem.components.preferences.PreferenceDropdown import io.element.android.libraries.designsystem.components.preferences.PreferenceDropdown
import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.preview.PreviewsDayNight
@ -99,13 +99,10 @@ fun ChangeRoomPermissionsView(
async = state.confirmExitAction, async = state.confirmExitAction,
onSuccess = { onComplete(false) }, onSuccess = { onComplete(false) },
confirmationDialog = { confirmationDialog = {
ConfirmationDialog( SaveChangesDialog(
title = stringResource(R.string.screen_room_change_role_unsaved_changes_title), onSaveClick = { state.eventSink(ChangeRoomPermissionsEvent.Save) },
content = stringResource(R.string.screen_room_change_role_unsaved_changes_description), onDiscardClick = { state.eventSink(ChangeRoomPermissionsEvent.Exit) },
submitText = stringResource(CommonStrings.action_save), onDismiss = { state.eventSink(ChangeRoomPermissionsEvent.ResetPendingActions) },
cancelText = stringResource(CommonStrings.action_discard),
onSubmitClick = { state.eventSink(ChangeRoomPermissionsEvent.Save) },
onDismiss = { state.eventSink(ChangeRoomPermissionsEvent.Exit) }
) )
}, },
onErrorDismiss = {}, onErrorDismiss = {},

View file

@ -172,8 +172,9 @@ fun ChangeRolesView(
when (confirming) { when (confirming) {
is AsyncAction.ConfirmingCancellation -> { is AsyncAction.ConfirmingCancellation -> {
SaveChangesDialog( SaveChangesDialog(
onSubmitClick = { state.eventSink(ChangeRolesEvent.Exit) }, onSaveClick = { state.eventSink(ChangeRolesEvent.Save) },
onDismiss = { state.eventSink(ChangeRolesEvent.CloseDialog) } onDiscardClick = { state.eventSink(ChangeRolesEvent.Exit) },
onDismiss = { state.eventSink(ChangeRolesEvent.CloseDialog) },
) )
} }
is ConfirmingModifyingOwners -> { is ConfirmingModifyingOwners -> {

View file

@ -119,7 +119,7 @@ class ChangeRolesViewTest {
} }
@Test @Test
fun `exit confirmation dialog - submit exits the screen`() { fun `exit confirmation dialog - discard exits the screen`() {
val eventsRecorder = EventsRecorder<ChangeRolesEvent>() val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
rule.setChangeRolesContent( rule.setChangeRolesContent(
state = aChangeRolesState( state = aChangeRolesState(
@ -128,12 +128,12 @@ class ChangeRolesViewTest {
eventSink = eventsRecorder, eventSink = eventsRecorder,
), ),
) )
rule.clickOn(CommonStrings.action_ok) rule.clickOn(CommonStrings.action_discard)
eventsRecorder.assertSingle(ChangeRolesEvent.Exit) eventsRecorder.assertSingle(ChangeRolesEvent.Exit)
} }
@Test @Test
fun `exit confirmation dialog - cancel removes the dialog`() { fun `exit confirmation dialog - save emits the save event`() {
val eventsRecorder = EventsRecorder<ChangeRolesEvent>() val eventsRecorder = EventsRecorder<ChangeRolesEvent>()
rule.setChangeRolesContent( rule.setChangeRolesContent(
state = aChangeRolesState( state = aChangeRolesState(
@ -142,8 +142,8 @@ class ChangeRolesViewTest {
eventSink = eventsRecorder, eventSink = eventsRecorder,
), ),
) )
rule.clickOn(CommonStrings.action_cancel) rule.clickOn(CommonStrings.action_save)
eventsRecorder.assertSingle(ChangeRolesEvent.CloseDialog) eventsRecorder.assertSingle(ChangeRolesEvent.Save)
} }
@Test @Test

View file

@ -159,7 +159,8 @@ fun RoomDetailsEditView(
confirmationDialog = { confirmationDialog = {
if (state.saveAction == AsyncAction.ConfirmingCancellation) { if (state.saveAction == AsyncAction.ConfirmingCancellation) {
SaveChangesDialog( SaveChangesDialog(
onSubmitClick = { state.eventSink(RoomDetailsEditEvents.OnBackPress) }, onSaveClick = { state.eventSink(RoomDetailsEditEvents.Save) },
onDiscardClick = { state.eventSink(RoomDetailsEditEvents.OnBackPress) },
onDismiss = { state.eventSink(RoomDetailsEditEvents.CloseDialog) } onDismiss = { state.eventSink(RoomDetailsEditEvents.CloseDialog) }
) )
} }

View file

@ -144,7 +144,8 @@ fun SecurityAndPrivacyView(
onErrorDismiss = { }, onErrorDismiss = { },
confirmationDialog = { confirmationDialog = {
SaveChangesDialog( SaveChangesDialog(
onSubmitClick = { state.eventSink(SecurityAndPrivacyEvents.Exit) }, onSaveClick = { state.eventSink(SecurityAndPrivacyEvents.Save) },
onDiscardClick = { state.eventSink(SecurityAndPrivacyEvents.Exit) },
onDismiss = { state.eventSink(SecurityAndPrivacyEvents.DismissExitConfirmation) } onDismiss = { state.eventSink(SecurityAndPrivacyEvents.DismissExitConfirmation) }
) )
}, },

View file

@ -17,16 +17,22 @@ import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
fun SaveChangesDialog( fun SaveChangesDialog(
onSubmitClick: () -> Unit, onSaveClick: () -> Unit,
onDiscardClick: () -> Unit,
onDismiss: () -> Unit, onDismiss: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
title: String = stringResource(CommonStrings.dialog_unsaved_changes_title), title: String = stringResource(CommonStrings.dialog_unsaved_changes_title),
content: String = stringResource(CommonStrings.dialog_unsaved_changes_description_android), content: String = stringResource(CommonStrings.dialog_unsaved_changes_description),
submitText: String = stringResource(CommonStrings.action_save),
cancelText: String = stringResource(CommonStrings.action_discard),
) = ConfirmationDialog( ) = ConfirmationDialog(
modifier = modifier, modifier = modifier,
title = title, title = title,
content = content, content = content,
onSubmitClick = onSubmitClick, submitText = submitText,
cancelText = cancelText,
onSubmitClick = onSaveClick,
onCancelClick = onDiscardClick,
onDismiss = onDismiss, onDismiss = onDismiss,
) )
@ -34,7 +40,8 @@ fun SaveChangesDialog(
@Composable @Composable
internal fun SaveChangesDialogPreview() = ElementPreview { internal fun SaveChangesDialogPreview() = ElementPreview {
SaveChangesDialog( SaveChangesDialog(
onSubmitClick = {}, onSaveClick = {},
onDiscardClick = {},
onDismiss = {} onDismiss = {}
) )
} }

View file

@ -38,6 +38,7 @@
<string name="notification_room_invite_body_with_sender">"%1$s invited you to join the room"</string> <string name="notification_room_invite_body_with_sender">"%1$s invited you to join the room"</string>
<string name="notification_sender_me">"Me"</string> <string name="notification_sender_me">"Me"</string>
<string name="notification_sender_mention_reply">"%1$s mentioned or replied"</string> <string name="notification_sender_mention_reply">"%1$s mentioned or replied"</string>
<string name="notification_space_invite_body">"Invited you to join the space"</string>
<string name="notification_test_push_notification_content">"You are viewing the notification! Click me!"</string> <string name="notification_test_push_notification_content">"You are viewing the notification! Click me!"</string>
<string name="notification_thread_in_room">"Thread in %1$s"</string> <string name="notification_thread_in_room">"Thread in %1$s"</string>
<string name="notification_ticker_text_dm">"%1$s: %2$s"</string> <string name="notification_ticker_text_dm">"%1$s: %2$s"</string>

View file

@ -392,6 +392,7 @@ Are you sure you want to continue?"</string>
<string name="dialog_title_error">"Error"</string> <string name="dialog_title_error">"Error"</string>
<string name="dialog_title_success">"Success"</string> <string name="dialog_title_success">"Success"</string>
<string name="dialog_title_warning">"Warning"</string> <string name="dialog_title_warning">"Warning"</string>
<string name="dialog_unsaved_changes_description">"You have unsaved changes."</string>
<string name="dialog_unsaved_changes_description_android">"Your changes have not been saved. Are you sure you want to go back?"</string> <string name="dialog_unsaved_changes_description_android">"Your changes have not been saved. Are you sure you want to go back?"</string>
<string name="dialog_unsaved_changes_title">"Save changes?"</string> <string name="dialog_unsaved_changes_title">"Save changes?"</string>
<string name="dialog_video_quality_selector_subtitle_file_size">"The max file size allowed is: %1$s"</string> <string name="dialog_video_quality_selector_subtitle_file_size">"The max file size allowed is: %1$s"</string>