From 037c8b13f3425b7c6d9d171622975b58ef594c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacy=20Kuchci=C5=84ski?= Date: Thu, 18 Aug 2022 10:59:47 +0200 Subject: [PATCH] window: Batch multiple undo toasts together Currently, if the user quickly performs multiple delete operations, undo toasts queue in an awkward way. This results in both confusing and slow user experience. To fix that, batch the multiple undo toasts into a toast that undoes deleting all of those items at once. Fixes https://gitlab.gnome.org/GNOME/nautilus/-/issues/2350 --- src/nautilus-window.c | 63 ++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 15 deletions(-) diff --git a/src/nautilus-window.c b/src/nautilus-window.c index f1e1e341af..2577648fe7 100644 --- a/src/nautilus-window.c +++ b/src/nautilus-window.c @@ -111,6 +111,8 @@ struct _NautilusWindow /* Notifications */ AdwToastOverlay *toast_overlay; + AdwToast *undo_toast; + int toast_undo_items; /* Toolbar */ GtkWidget *toolbar; @@ -1164,7 +1166,9 @@ nautilus_window_ensure_location_entry (NautilusWindow *window) } static gchar * -toast_undo_deleted_get_label (NautilusFileUndoInfo *undo_info) +toast_undo_deleted_get_label (NautilusFileUndoInfo *undo_info, + gboolean stacked, + NautilusWindow *window) { GList *files; gchar *file_label; @@ -1173,8 +1177,9 @@ toast_undo_deleted_get_label (NautilusFileUndoInfo *undo_info) files = nautilus_file_undo_info_trash_get_files (NAUTILUS_FILE_UNDO_INFO_TRASH (undo_info)); length = g_list_length (files); - if (length == 1) + if (length == 1 && stacked) { + window->toast_undo_items++; file_label = g_file_get_basename (files->data); /* Translators: only one item has been deleted and %s is its name. */ label = g_markup_printf_escaped (_("ā€œ%sā€ moved to trash"), file_label); @@ -1182,16 +1187,22 @@ toast_undo_deleted_get_label (NautilusFileUndoInfo *undo_info) } else { + window->toast_undo_items += length; /* Translators: one or more items might have been deleted, and %d * is the count. */ - label = g_markup_printf_escaped (ngettext ("%d file deleted", "%d files deleted", length), length); + label = g_markup_printf_escaped (ngettext ("%d file deleted", + "%d files deleted", + window->toast_undo_items), + window->toast_undo_items); } return label; } static gchar * -toast_undo_unstar_get_label (NautilusFileUndoInfo *undo_info) +toast_undo_unstar_get_label (NautilusFileUndoInfo *undo_info, + gboolean stacked, + NautilusWindow *window) { GList *files; gchar *label; @@ -1199,31 +1210,43 @@ toast_undo_unstar_get_label (NautilusFileUndoInfo *undo_info) files = nautilus_file_undo_info_starred_get_files (NAUTILUS_FILE_UNDO_INFO_STARRED (undo_info)); length = g_list_length (files); - if (length == 1) + if (length == 1 && stacked) { g_autofree gchar *file_label = NULL; + window->toast_undo_items++; file_label = nautilus_file_get_display_name (files->data); /* Translators: one item has been unstarred and %s is its name. */ label = g_markup_printf_escaped (_("ā€œ%sā€ unstarred"), file_label); } else { + window->toast_undo_items += length; /* Translators: one or more items have been unstarred, and %d * is the count. */ - label = g_markup_printf_escaped (ngettext ("%d file unstarred", "%d files unstarred", length), length); + label = g_markup_printf_escaped (ngettext ("%d file unstarred", + "%d files unstarred", + window->toast_undo_items), + window->toast_undo_items); } return label; } +static void +toast_dismissed_cb (AdwToast *toast, + NautilusWindow *window) +{ + window->undo_toast = NULL; + window->toast_undo_items = 0; +} + static void nautilus_window_on_undo_changed (NautilusFileUndoManager *manager, NautilusWindow *window) { NautilusFileUndoInfo *undo_info; NautilusFileUndoManagerState state; - AdwToast *toast; undo_info = nautilus_file_undo_manager_get_action (); state = nautilus_file_undo_manager_get_state (); @@ -1232,6 +1255,7 @@ nautilus_window_on_undo_changed (NautilusFileUndoManager *manager, state == NAUTILUS_FILE_UNDO_MANAGER_STATE_UNDO) { gboolean popup_toast = FALSE; + gboolean stacked = window->undo_toast == NULL; g_autofree gchar *label = NULL; if (nautilus_file_undo_info_get_op_type (undo_info) == NAUTILUS_FILE_UNDO_OP_MOVE_TO_TRASH) @@ -1246,7 +1270,7 @@ nautilus_window_on_undo_changed (NautilusFileUndoManager *manager, if (files != NULL && gtk_window_is_active (GTK_WINDOW (window))) { popup_toast = TRUE; - label = toast_undo_deleted_get_label (undo_info); + label = toast_undo_deleted_get_label (undo_info, stacked, window); } } else if (nautilus_file_undo_info_get_op_type (undo_info) == NAUTILUS_FILE_UNDO_OP_STARRED) @@ -1264,17 +1288,26 @@ nautilus_window_on_undo_changed (NautilusFileUndoManager *manager, !nautilus_file_undo_info_starred_is_starred (NAUTILUS_FILE_UNDO_INFO_STARRED (undo_info))) { popup_toast = TRUE; - label = toast_undo_unstar_get_label (undo_info); + label = toast_undo_unstar_get_label (undo_info, stacked, window); } } - if (popup_toast) + if (popup_toast && !window->undo_toast) + { + window->undo_toast = adw_toast_new (label); + adw_toast_set_button_label (window->undo_toast, _("Undo")); + adw_toast_set_action_name (window->undo_toast, "win.undo"); + adw_toast_set_priority (window->undo_toast, ADW_TOAST_PRIORITY_HIGH); + + g_signal_connect_object (window->undo_toast, "dismissed", + G_CALLBACK (toast_dismissed_cb), window, 0); + + adw_toast_overlay_add_toast (window->toast_overlay, window->undo_toast); + } + else if (popup_toast) { - toast = adw_toast_new (label); - adw_toast_set_button_label (toast, _("Undo")); - adw_toast_set_action_name (toast, "win.undo"); - adw_toast_set_priority (toast, ADW_TOAST_PRIORITY_HIGH); - adw_toast_overlay_add_toast (window->toast_overlay, toast); + adw_toast_set_title (window->undo_toast, label); + /*adw_toast_overlay_add_toast (window->toast_overlay, window->undo_toast); */ } } } -- GitLab