[geary/gnumdk/fix_mark_menu_actions] client: Fix updating actions state in mark messages menu




commit 25132d98e46932520ff5cb976293e155bee3aba1
Author: Cédric Bellegarde <cedric bellegarde adishatz org>
Date:   Sat Jul 16 18:05:03 2022 +0200

    client: Fix updating actions state in mark messages menu

 .../application/application-main-window.vala       |  12 +-
 .../components-conversation-actions.vala           |   8 ++
 .../conversation-list/conversation-list-model.vala | 123 +++++++++++++++++++++
 3 files changed, 137 insertions(+), 6 deletions(-)
---
diff --git a/src/client/application/application-main-window.vala 
b/src/client/application/application-main-window.vala
index 8e969d108..0d56cbfbe 100644
--- a/src/client/application/application-main-window.vala
+++ b/src/client/application/application-main-window.vala
@@ -27,7 +27,6 @@ public class Application.MainWindow :
     public const string ACTION_SEARCH = "search";
     public const string ACTION_SELECT_INBOX = "select-inbox";
     public const string ACTION_SHOW_COPY_MENU = "show-copy-menu";
-    public const string ACTION_SHOW_MARK_MENU = "show-mark-menu";
     public const string ACTION_SHOW_MOVE_MENU = "show-move-menu";
     public const string ACTION_TOGGLE_JUNK = "toggle-conversation-junk";
     public const string ACTION_TRASH_CONVERSATION = "trash-conversation";
@@ -61,7 +60,6 @@ public class Application.MainWindow :
         { ACTION_CONVERSATION_UP, on_conversation_up },
         { ACTION_CONVERSATION_DOWN, on_conversation_down },
         // Message marking actions
-        { ACTION_SHOW_MARK_MENU, on_show_mark_menu },
         { ACTION_MARK_AS_READ, on_mark_as_read },
         { ACTION_MARK_AS_UNREAD, on_mark_as_unread },
         { ACTION_MARK_AS_STARRED, on_mark_as_starred },
@@ -673,9 +671,15 @@ public class Application.MainWindow :
         this.cert_problem_infobar.get_action_area().add(cert_retry);
 
         this.conversation_list_view.grab_focus();
+
+        this.conversation_list_actions.mark_message_button_toggled.connect(on_show_mark_menu);
+        this.main_toolbar.full_actions.mark_message_button_toggled.connect(on_show_mark_menu);
     }
 
     ~MainWindow() {
+        this.conversation_list_actions.mark_message_button_toggled.disconnect(on_show_mark_menu);
+        this.main_toolbar.full_actions.mark_message_button_toggled.connect(on_show_mark_menu);
+
         base_unref();
     }
 
@@ -1915,10 +1919,6 @@ public class Application.MainWindow :
                 supported_operations.add_all(selected_operations.get_values());
             }
 
-            get_window_action(ACTION_SHOW_MARK_MENU).set_enabled(
-                sensitive &&
-                (typeof(Geary.FolderSupport.Mark) in supported_operations)
-            );
             get_window_action(ACTION_SHOW_COPY_MENU).set_enabled(
                 sensitive &&
                 (supported_operations.contains(typeof(Geary.FolderSupport.Copy)))
diff --git a/src/client/components/components-conversation-actions.vala 
b/src/client/components/components-conversation-actions.vala
index f7df39fb9..dcd78434c 100644
--- a/src/client/components/components-conversation-actions.vala
+++ b/src/client/components/components-conversation-actions.vala
@@ -60,6 +60,11 @@ public class Components.ConversationActions : Gtk.Box {
         this.copy_message_button.popover = copy_folder_menu;
         this.move_message_button.popover = move_folder_menu;
 
+        this.mark_message_button.toggled.connect((button) => {
+            if (button.active)
+                mark_message_button_toggled();
+        });
+
         this.response_buttons.set_visible(this.show_response_actions);
         this.mark_copy_move_buttons.set_visible(this.show_conversation_actions);
         this.archive_trash_delete_buttons.set_visible(this.show_conversation_actions);
@@ -91,6 +96,9 @@ public class Components.ConversationActions : Gtk.Box {
         update_conversation_buttons();
     }
 
+    /** Fired when the user toggles the mark message button. */
+    public signal void mark_message_button_toggled();
+
     /** Updates tooltip text depending on number of conversations selected. */
     private void update_conversation_buttons() {
         this.mark_message_button.tooltip_text = ngettext(
diff --git a/src/client/conversation-list/conversation-list-model.vala 
b/src/client/conversation-list/conversation-list-model.vala
new file mode 100644
index 000000000..8108caeff
--- /dev/null
+++ b/src/client/conversation-list/conversation-list-model.vala
@@ -0,0 +1,123 @@
+// The whole goal of this class to wrap the ConversationMonitor with a view that presents a sorted list
+public class ConversationList.Model {
+    internal ListStore store = new ListStore(typeof(Geary.App.Conversation));
+    internal Geary.App.ConversationMonitor monitor { get; set; }
+
+    internal Model (Geary.App.ConversationMonitor monitor) {
+        this.monitor = monitor;
+        foreach (Geary.App.Conversation convo in monitor.read_only_view) {
+            insert(convo);
+        }
+
+        monitor.conversations_added.connect(on_conversations_added);
+        monitor.conversation_appended.connect(on_conversation_updated);
+        monitor.conversation_trimmed.connect(on_conversation_updated);
+        monitor.conversations_removed.connect(on_conversations_removed);
+        monitor.scan_started.connect(on_scan_started);
+        monitor.scan_completed.connect(on_scan_completed);
+    }
+
+    ~Model() {
+        this.monitor.conversations_added.disconnect(on_conversations_added);
+        this.monitor.conversation_appended.disconnect(on_conversation_updated);
+        this.monitor.conversation_trimmed.disconnect(on_conversation_updated);
+        this.monitor.conversations_removed.disconnect(on_conversations_removed);
+        this.monitor.scan_started.disconnect(on_scan_started);
+        this.monitor.scan_completed.disconnect(on_scan_completed);
+    }
+
+    /**
+     * Informs observers that batch of updates is complete.
+     *
+     * GTK's ListModel interface reports updates as additions and subtractions
+     * at a specific index, meaning the results of a scan can require several
+     * invocations of items_changed. This signal allows consumers to know when
+     * those invocations have stopped.
+     */
+    internal signal void update_complete();
+
+    private static int compare(Object a, Object b) {
+        return Util.Email.compare_conversation_descending(a as Geary.App.Conversation, b as 
Geary.App.Conversation);
+    }
+
+    private void insert(Geary.App.Conversation convo)  {
+        store.insert_sorted(convo, compare);
+    }
+
+    // ------------------------
+    //  Scanning and load_more
+    // ------------------------
+    private bool scanning = false;
+
+    private void on_scan_started(Geary.App.ConversationMonitor source) {
+        scanning = true;
+    }
+    private void on_scan_completed(Geary.App.ConversationMonitor source) {
+        scanning = false;
+        update_complete();
+    }
+
+    public bool load_more(int amount) {
+        if (scanning) {
+            return false;
+        }
+
+        this.monitor.min_window_count += amount;
+        return true;
+    }
+
+
+    // Monitor Lifecycle handles
+    private void on_conversations_added(Gee.Collection<Geary.App.Conversation> conversations) {
+        debug("Adding %d conversations.", conversations.size);
+        int added = 0;
+        foreach (Geary.App.Conversation conversation in conversations) {
+            if (upsert_conversation(conversation)) {
+                added++;
+            }
+        }
+        debug("Added %d/%d conversations.", added, conversations.size);
+    }
+
+    private void on_conversations_removed(Gee.Collection<Geary.App.Conversation> conversations) {
+        debug("Removing %d conversations.", conversations.size);
+        int removed = 0;
+        foreach (Geary.App.Conversation conversation in conversations) {
+            if (remove_conversation(conversation)) {
+                removed++;
+            }
+        }
+        debug("Removed %d/%d conversations.", removed, conversations.size);
+    }
+
+    private void on_conversation_updated(Geary.App.ConversationMonitor sender, Geary.App.Conversation convo, 
Gee.Collection<Geary.Email> emails) {
+        upsert_conversation(convo);
+    }
+
+    // Monitor helpers
+    private bool upsert_conversation(Geary.App.Conversation convo) {
+        // The conversation may be bogus, if so don't do anything
+        Geary.Email? last_email = convo.get_latest_recv_email(Geary.App.Conversation.Location.ANYWHERE);
+
+        if (last_email == null) {
+            debug("Cannot add conversation: last email is null");
+            return false;
+        }
+
+        remove_conversation(convo);
+        insert(convo);
+
+        return true;
+    }
+
+    private bool remove_conversation(Geary.App.Conversation conversation) {
+        uint index;
+        if (store.find(conversation, out index)) {
+            store.remove(index);
+            return true;
+        }
+
+        return false;
+    }
+
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]