[geary/mjog/account-command-stacks: 3/25] Use Geary.FolderSupport.Archive when moving to archive special



commit a282dc546eaa982cf2e2592639359ccf7c5ca055
Author: Michael Gratton <mike vee net>
Date:   Thu Oct 24 12:46:33 2019 +1100

    Use Geary.FolderSupport.Archive when moving to archive special
    
    This is needed for services like e.g. Gmail where Archive isn't
    actually a folder, rather it's a lack of other labels.

 src/client/application/application-controller.vala | 237 +++++++++++++++++----
 src/client/components/main-window.vala             |  14 +-
 2 files changed, 196 insertions(+), 55 deletions(-)
---
diff --git a/src/client/application/application-controller.vala 
b/src/client/application/application-controller.vala
index 72ab4cbe..6036a609 100644
--- a/src/client/application/application-controller.vala
+++ b/src/client/application/application-controller.vala
@@ -653,65 +653,143 @@ public class Application.Controller : Geary.BaseObject {
         }
     }
 
-    public async void move_conversations_special(Geary.FolderSupport.Move source,
+    public async void move_conversations_special(Geary.Folder source,
                                                  Geary.SpecialFolderType destination,
                                                  Gee.Collection<Geary.App.Conversation> conversations)
         throws GLib.Error {
         AccountContext? context = this.accounts.get(source.account.information);
         if (context != null) {
-            Geary.Folder? dest = source.account.get_special_folder(destination);
-            if (dest == null) {
-                throw new Geary.EngineError.NOT_FOUND(
-                    "No folder found for: %s", destination.to_string()
+            Command? command = null;
+            Gee.Collection<Geary.EmailIdentifier> messages =
+                to_in_folder_email_ids(conversations);
+            /// Translators: Label for in-app notification. String
+            /// substitution is the name of the destination folder.
+            string undone_tooltip = ngettext(
+                "Conversation restored to %s",
+                "Conversations restored to %s",
+                messages.size
+            ).printf(source.get_display_name());
+
+            if (destination == ARCHIVE) {
+                Geary.FolderSupport.Archive? archive_source = (
+                    source as Geary.FolderSupport.Archive
                 );
-            }
-
-            yield context.commands.execute(
-                new MoveEmailCommand(
-                    source,
+                if (archive_source == null) {
+                    throw new Geary.EngineError.UNSUPPORTED(
+                        "Folder does not support archiving: %s",
+                        source.to_string()
+                    );
+                }
+                command = new ArchiveEmailCommand(
+                    archive_source,
+                    messages,
+                    /// Translators: Label for in-app notification.
+                    ngettext(
+                        "Conversation archived",
+                        "Conversations archived",
+                        messages.size
+                    ),
+                    undone_tooltip
+                );
+            } else {
+                Geary.FolderSupport.Move? move_source = (
+                    source as Geary.FolderSupport.Move
+                );
+                if (move_source == null) {
+                    throw new Geary.EngineError.UNSUPPORTED(
+                        "Folder does not support moving: %s",
+                        source.to_string()
+                    );
+                }
+                Geary.Folder? dest = source.account.get_special_folder(
+                    destination
+                );
+                if (dest == null) {
+                    throw new Geary.EngineError.NOT_FOUND(
+                        "No folder found for: %s", destination.to_string()
+                    );
+                }
+                command = new MoveEmailCommand(
+                    move_source,
                     dest,
-                    to_in_folder_email_ids(conversations),
-                    /// Translators: Label for in-app undo
+                    messages,
+                    /// Translators: Label for in-app
                     /// notification. String substitution is the name
                     /// of the destination folder.
                     ngettext(
                         "Conversation moved to %s",
                         "Conversations moved to %s",
-                        conversations.size
-                    ).printf(dest.get_display_name()),
-                    /// Translators: Label for in-app undo
-                    /// notification. String substitution is the name
-                    /// of the source folder.
-                    ngettext(
-                        "Conversation restored to %s",
-                        "Conversations restored to %s",
-                        conversations.size
-                    ).printf(source.get_display_name())
-                ),
-                context.cancellable
-            );
+                        messages.size
+                    ).printf(destination.get_display_name()),
+                    undone_tooltip
+                );
+            }
+
+            yield context.commands.execute(command, context.cancellable);
         }
     }
 
-    public async void move_messages_special(Geary.FolderSupport.Move source,
+    public async void move_messages_special(Geary.Folder source,
                                             Geary.SpecialFolderType destination,
                                             Gee.Collection<Geary.EmailIdentifier> messages)
         throws GLib.Error {
         AccountContext? context = this.accounts.get(source.account.information);
         if (context != null) {
-            Geary.Folder? dest = source.account.get_special_folder(destination);
-            if (dest == null) {
-                throw new Geary.EngineError.NOT_FOUND(
-                    "No folder found for: %s", destination.to_string()
+            Command? command = null;
+            /// Translators: Label for in-app notification. String
+            /// substitution is the name of the destination folder.
+            string undone_tooltip = ngettext(
+                "Message restored to %s",
+                "Messages restored to %s",
+                messages.size
+            ).printf(source.get_display_name());
+
+            if (destination == ARCHIVE) {
+                Geary.FolderSupport.Archive? archive_source = (
+                    source as Geary.FolderSupport.Archive
                 );
-            }
+                if (archive_source == null) {
+                    throw new Geary.EngineError.UNSUPPORTED(
+                        "Folder does not support archiving: %s",
+                        source.to_string()
+                    );
+                }
+                command = new ArchiveEmailCommand(
+                    archive_source,
+                    messages,
+                    /// Translators: Label for in-app notification.
+                    ngettext(
+                        "Message archived",
+                        "Messages archived",
+                        messages.size
+                    ),
+                    undone_tooltip
+                );
+            } else {
+                Geary.FolderSupport.Move? move_source = (
+                    source as Geary.FolderSupport.Move
+                );
+                if (move_source == null) {
+                    throw new Geary.EngineError.UNSUPPORTED(
+                        "Folder does not support moving: %s",
+                        source.to_string()
+                    );
+                }
 
-            yield context.commands.execute(
-                new MoveEmailCommand(
-                    source,
+                Geary.Folder? dest = source.account.get_special_folder(
+                    destination
+                );
+                if (dest == null) {
+                    throw new Geary.EngineError.NOT_FOUND(
+                        "No folder found for: %s", destination.to_string()
+                    );
+                }
+
+                command = new MoveEmailCommand(
+                    move_source,
                     dest,
                     messages,
-                    /// Translators: Label for in-app undo
+                    /// Translators: Label for in-app
                     /// notification. String substitution is the name
                     /// of the destination folder.
                     ngettext(
@@ -719,17 +797,11 @@ public class Application.Controller : Geary.BaseObject {
                         "Messages moved to %s",
                         messages.size
                     ).printf(destination.get_display_name()),
-                    /// Translators: Label for in-app undo
-                    /// notification. String substitution is the name
-                    /// of the source folder.
-                    ngettext(
-                        "Message restored to %s",
-                        "Messages restored to %s",
-                        messages.size
-                    ).printf(source.get_display_name())
-                ),
-                context.cancellable
-            );
+                    undone_tooltip
+                );
+            }
+
+            yield context.commands.execute(command, context.cancellable);
         }
     }
 
@@ -2565,6 +2637,79 @@ private class Application.MoveEmailCommand : EmailCommand, RevokableCommand {
 }
 
 
+private class Application.ArchiveEmailCommand : EmailCommand, RevokableCommand {
+
+
+    private Geary.FolderSupport.Archive source;
+    private Gee.Collection<Geary.EmailIdentifier> source_messages;
+
+    public ArchiveEmailCommand(Geary.FolderSupport.Archive source,
+                               Gee.Collection<Geary.EmailIdentifier> messages,
+                               string? executed_label = null,
+                               string? undone_label = null) {
+        this.source = source;
+        this.source_messages = messages;
+
+        this.executed_label = executed_label;
+        this.undone_label = undone_label;
+    }
+
+    internal override EmailCommand.StateChangePolicy folders_removed(
+        Gee.Collection<Geary.Folder> removed
+    ) {
+        EmailCommand.StateChangePolicy ret = IGNORE;
+        if (this.source in removed ||
+            Geary.traverse(removed).any(f => f.special_folder_type == ARCHIVE)) {
+            ret = REMOVE;
+        }
+        return ret;
+    }
+
+    internal override EmailCommand.StateChangePolicy email_removed(
+        Geary.Folder location,
+        Gee.Collection<Geary.EmailIdentifier> targets
+    ) {
+        EmailCommand.StateChangePolicy ret = IGNORE;
+        if (location == this.source) {
+            this.source_messages.remove_all(targets);
+            if (this.source_messages.is_empty) {
+                ret = REMOVE;
+            }
+        } else if (location.special_folder_type == ARCHIVE) {
+            // Don't actually know because of the revokable impl, so
+            // assume the worst
+            ret = REMOVE;
+        }
+        return ret;
+    }
+
+    protected override async Geary.Revokable
+        execute_impl(GLib.Cancellable cancellable)
+        throws GLib.Error {
+        bool open = false;
+        try {
+            yield this.source.open_async(
+                Geary.Folder.OpenFlags.NO_DELAY, cancellable
+            );
+            open = true;
+            return yield this.source.archive_email_async(
+                this.source_messages,
+                cancellable
+            );
+        } finally {
+            if (open) {
+                try {
+                    yield this.source.close_async(null);
+                } catch (GLib.Error err) {
+                    // ignored
+                }
+            }
+        }
+    }
+
+}
+
+
 private class Application.CopyEmailCommand : EmailCommand, Command {
 
 
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index cdeb3887..b1736ae7 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -1625,8 +1625,7 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
     }
 
     private void on_mark_as_spam_toggle() {
-        Geary.FolderSupport.Move? source =
-            this.selected_folder as Geary.FolderSupport.Move;
+        Geary.Folder? source = this.selected_folder;
         if (source != null) {
             Geary.SpecialFolderType destination =
                 (source.special_folder_type != SPAM)
@@ -1688,12 +1687,11 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
     }
 
     private void on_archive_conversation() {
-        Geary.FolderSupport.Move source =
-            this.selected_folder as Geary.FolderSupport.Move;
+        Geary.Folder source = this.selected_folder;
         if (source != null) {
             this.application.controller.move_conversations_special.begin(
                 source,
-                Geary.SpecialFolderType.ARCHIVE,
+                ARCHIVE,
                 this.conversation_list_view.get_selected_conversations(),
                 (obj, res) => {
                     try {
@@ -1707,8 +1705,7 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
     }
 
     private void on_trash_conversation() {
-        Geary.FolderSupport.Move source =
-            this.selected_folder as Geary.FolderSupport.Move;
+        Geary.Folder source = this.selected_folder;
         if (source != null) {
             this.application.controller.move_conversations_special.begin(
                 source,
@@ -1935,8 +1932,7 @@ public class MainWindow : Gtk.ApplicationWindow, Geary.BaseInterface {
     }
 
     private void on_trash_message(ConversationEmail target_view) {
-        Geary.FolderSupport.Move? source =
-            this.selected_folder as Geary.FolderSupport.Move;
+        Geary.Folder? source = this.selected_folder;
         if (source != null) {
             this.application.controller.move_messages_special.begin(
                 source,


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