[geary/mjog/598-sent-email-sound: 1/6] Application: Make Plugin.EmailStore impl usable by other cxts



commit f0c1dfe37517d7d3cae7e71805923a86034de3df
Author: Michael Gratton <mike vee net>
Date:   Sat Mar 21 09:06:05 2020 +1100

    Application: Make Plugin.EmailStore impl usable by other cxts
    
    Break out the plugin mail store implmeentation out of
    NotificationContext into its own EmailStoreFactory class, so it can be
    re-used by other plugin context types.

 po/POTFILES.in                                     |   1 +
 .../application-email-store-factory.vala           | 210 +++++++++++++++++++++
 .../application-notification-context.vala          | 167 +---------------
 .../application/application-plugin-manager.vala    |   6 +-
 src/client/meson.build                             |   1 +
 5 files changed, 227 insertions(+), 158 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index a1f9c866..d2494804 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -23,6 +23,7 @@ src/client/application/application-configuration.vala
 src/client/application/application-contact-store.vala
 src/client/application/application-contact.vala
 src/client/application/application-controller.vala
+src/client/application/application-email-store-factory.vala
 src/client/application/application-folder-context.vala
 src/client/application/application-folder-store-factory.vala
 src/client/application/application-main-window.vala
diff --git a/src/client/application/application-email-store-factory.vala 
b/src/client/application/application-email-store-factory.vala
new file mode 100644
index 00000000..2072fc68
--- /dev/null
+++ b/src/client/application/application-email-store-factory.vala
@@ -0,0 +1,210 @@
+/*
+ * Copyright © 2020 Michael Gratton <mike vee net>
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+/**
+ * A factory for constructing plugin email stores and objects.
+ *
+ * This class provides a common implementation that shares email
+ * objects between different plugin context instances.
+ */
+internal class Application.EmailStoreFactory : Geary.BaseObject {
+
+
+    private class EmailStoreImpl : Geary.BaseObject, Plugin.EmailStore {
+
+
+        private Client backing;
+
+
+        public EmailStoreImpl(Client backing) {
+            this.backing = backing;
+        }
+
+        public async Gee.Collection<Plugin.Email> get_email(
+            Gee.Collection<Plugin.EmailIdentifier> plugin_ids,
+            GLib.Cancellable? cancellable
+        ) throws GLib.Error {
+            var emails = new Gee.HashSet<Plugin.Email>();
+
+            // The email could theoretically come from any account, so
+            // group them by account up front. The common case will be
+            // only a single account, so optimise for that a bit.
+
+            var accounts = new Gee.HashMap<
+                Geary.AccountInformation,
+                    Gee.Set<Geary.EmailIdentifier>
+            >();
+            Geary.AccountInformation? current_account = null;
+            Gee.Set<Geary.EmailIdentifier>? engine_ids = null;
+            foreach (Plugin.EmailIdentifier plugin_id in plugin_ids) {
+                IdImpl? id_impl = plugin_id as IdImpl;
+                if (id_impl != null) {
+                    if (id_impl.account != current_account) {
+                        current_account = id_impl.account;
+                        engine_ids = accounts.get(current_account);
+                        if (engine_ids == null) {
+                            engine_ids = new Gee.HashSet<Geary.EmailIdentifier>();
+                            accounts.set(current_account, engine_ids);
+                        }
+                    }
+                    engine_ids.add(id_impl.backing);
+                }
+            }
+
+            foreach (var account in accounts.keys) {
+                AccountContext context =
+                    this.backing.controller.get_context_for_account(account);
+                Gee.Collection<Geary.Email> batch =
+                    yield context.emails.list_email_by_sparse_id_async(
+                        accounts.get(account),
+                        ENVELOPE,
+                        NONE,
+                        context.cancellable
+                    );
+                if (batch != null) {
+                    foreach (var email in batch) {
+                        emails.add(new EmailImpl(email, account));
+                    }
+                }
+            }
+
+            return emails;
+        }
+
+        internal void destroy() {
+            // noop
+        }
+
+    }
+
+
+    private class EmailImpl : Geary.BaseObject, Plugin.Email {
+
+
+        public Plugin.EmailIdentifier identifier {
+            get {
+                if (this._id == null) {
+                    this._id = new IdImpl(this.backing.id, this.account);
+                }
+                return this._id;
+            }
+        }
+        private IdImpl? _id = null;
+
+        public string subject {
+            get { return this._subject; }
+        }
+        string _subject;
+
+        internal Geary.Email backing;
+        // Remove this when EmailIdentifier is updated to include
+        // the account
+        internal Geary.AccountInformation account { get; private set; }
+
+
+        public EmailImpl(Geary.Email backing,
+                         Geary.AccountInformation account) {
+            this.backing = backing;
+            this.account = account;
+            Geary.RFC822.Subject? subject = this.backing.subject;
+            this._subject = subject != null ? subject.to_string() : "";
+        }
+
+        public Geary.RFC822.MailboxAddress? get_primary_originator() {
+            return Util.Email.get_primary_originator(this.backing);
+        }
+
+    }
+
+
+    private class IdImpl : Geary.BaseObject,
+        Gee.Hashable<Plugin.EmailIdentifier>, Plugin.EmailIdentifier {
+
+
+        internal Geary.EmailIdentifier backing { get; private set; }
+        // Remove this when EmailIdentifier is updated to include
+        // the account
+        internal Geary.AccountInformation account { get; private set; }
+
+
+        public IdImpl(Geary.EmailIdentifier backing,
+                      Geary.AccountInformation account) {
+            this.backing = backing;
+            this.account = account;
+        }
+
+        public GLib.Variant to_variant() {
+            return this.backing.to_variant();
+        }
+
+        public bool equal_to(Plugin.EmailIdentifier other) {
+            if (this == other) {
+                return true;
+            }
+            IdImpl? impl = other as IdImpl;
+            return (
+                impl != null &&
+                this.backing.equal_to(impl.backing) &&
+                this.account.equal_to(impl.account)
+            );
+        }
+
+        public uint hash() {
+            return this.backing.hash();
+        }
+
+    }
+
+
+    private Client application;
+    private Gee.Set<EmailStoreImpl> stores =
+        new Gee.HashSet<EmailStoreImpl>();
+
+
+    /**
+     * Constructs a new factory instance.
+     */
+    public EmailStoreFactory(Client application) throws GLib.Error {
+        this.application = application;
+    }
+
+    /** Clearing all state of the store. */
+    public void destroy() throws GLib.Error {
+        foreach (EmailStoreImpl store in this.stores) {
+            store.destroy();
+        }
+        this.stores.clear();
+    }
+
+    /** Constructs a new email store for use by plugin contexts. */
+    public Plugin.EmailStore new_email_store() {
+        var store = new EmailStoreImpl(this.application);
+        this.stores.add(store);
+        return store;
+    }
+
+    /** Destroys a folder store once is no longer required. */
+    public void destroy_email_store(Plugin.EmailStore plugin) {
+        EmailStoreImpl? impl = plugin as EmailStoreImpl;
+        if (impl != null) {
+            impl.destroy();
+            this.stores.remove(impl);
+        }
+    }
+
+    public Gee.Collection<Plugin.EmailIdentifier> to_plugin_ids(
+        Gee.Collection<Geary.EmailIdentifier> engine_ids,
+        Geary.AccountInformation account
+    ) {
+        var plugin_ids = new Gee.HashSet<Plugin.EmailIdentifier>();
+        foreach (var id in engine_ids) {
+            plugin_ids.add(new IdImpl(id, account));
+        }
+        return plugin_ids;
+    }
+
+}
diff --git a/src/client/application/application-notification-context.vala 
b/src/client/application/application-notification-context.vala
index 3c4c018a..1ff2e1c5 100644
--- a/src/client/application/application-notification-context.vala
+++ b/src/client/application/application-notification-context.vala
@@ -16,159 +16,6 @@ internal class Application.NotificationContext :
     private const Geary.Email.Field REQUIRED_FIELDS  = FLAGS;
 
 
-    private class EmailStoreImpl : Geary.BaseObject, Plugin.EmailStore {
-
-
-        private class EmailImpl : Geary.BaseObject, Plugin.Email {
-
-
-            public Plugin.EmailIdentifier identifier {
-                get {
-                    if (this._id == null) {
-                        this._id = new IdImpl(this.backing.id, this.account);
-                    }
-                    return this._id;
-                }
-            }
-            private IdImpl? _id = null;
-
-            public string subject {
-                get { return this._subject; }
-            }
-            string _subject;
-
-            internal Geary.Email backing;
-            // Remove this when EmailIdentifier is updated to include
-            // the account
-            internal Geary.AccountInformation account { get; private set; }
-
-
-            public EmailImpl(Geary.Email backing,
-                             Geary.AccountInformation account) {
-                this.backing = backing;
-                this.account = account;
-                Geary.RFC822.Subject? subject = this.backing.subject;
-                this._subject = subject != null ? subject.to_string() : "";
-            }
-
-            public Geary.RFC822.MailboxAddress? get_primary_originator() {
-                return Util.Email.get_primary_originator(this.backing);
-            }
-
-        }
-
-
-        private class IdImpl : Geary.BaseObject,
-            Gee.Hashable<Plugin.EmailIdentifier>, Plugin.EmailIdentifier {
-
-
-            internal Geary.EmailIdentifier backing { get; private set; }
-            // Remove this when EmailIdentifier is updated to include
-            // the account
-            internal Geary.AccountInformation account { get; private set; }
-
-
-            public IdImpl(Geary.EmailIdentifier backing,
-                          Geary.AccountInformation account) {
-                this.backing = backing;
-                this.account = account;
-            }
-
-            public GLib.Variant to_variant() {
-                return this.backing.to_variant();
-            }
-
-            public bool equal_to(Plugin.EmailIdentifier other) {
-                if (this == other) {
-                    return true;
-                }
-                IdImpl? impl = other as IdImpl;
-                return (
-                    impl != null &&
-                    this.backing.equal_to(impl.backing) &&
-                    this.account.equal_to(impl.account)
-                );
-            }
-
-            public uint hash() {
-                return this.backing.hash();
-            }
-
-        }
-
-
-        private Client backing;
-
-
-        public EmailStoreImpl(Client backing) {
-            this.backing = backing;
-        }
-
-        public async Gee.Collection<Plugin.Email> get_email(
-            Gee.Collection<Plugin.EmailIdentifier> plugin_ids,
-            GLib.Cancellable? cancellable
-        ) throws GLib.Error {
-            var emails = new Gee.HashSet<Plugin.Email>();
-
-            // The email could theoretically come from any account, so
-            // group them by account up front. The common case will be
-            // only a single account, so optimise for that a bit.
-
-            var accounts = new Gee.HashMap<
-                Geary.AccountInformation,
-                    Gee.Set<Geary.EmailIdentifier>
-            >();
-            Geary.AccountInformation? current_account = null;
-            Gee.Set<Geary.EmailIdentifier>? engine_ids = null;
-            foreach (Plugin.EmailIdentifier plugin_id in plugin_ids) {
-                IdImpl? id_impl = plugin_id as IdImpl;
-                if (id_impl != null) {
-                    if (id_impl.account != current_account) {
-                        current_account = id_impl.account;
-                        engine_ids = accounts.get(current_account);
-                        if (engine_ids == null) {
-                            engine_ids = new Gee.HashSet<Geary.EmailIdentifier>();
-                            accounts.set(current_account, engine_ids);
-                        }
-                    }
-                    engine_ids.add(id_impl.backing);
-                }
-            }
-
-            foreach (var account in accounts.keys) {
-                AccountContext context =
-                    this.backing.controller.get_context_for_account(account);
-                Gee.Collection<Geary.Email> batch =
-                    yield context.emails.list_email_by_sparse_id_async(
-                        accounts.get(account),
-                        ENVELOPE,
-                        NONE,
-                        context.cancellable
-                    );
-                if (batch != null) {
-                    foreach (var email in batch) {
-                        emails.add(new EmailImpl(email, account));
-                    }
-                }
-            }
-
-            return emails;
-        }
-
-        internal Gee.Collection<Plugin.EmailIdentifier> get_plugin_ids(
-            Gee.Collection<Geary.EmailIdentifier> engine_ids,
-            Geary.AccountInformation account
-        ) {
-            var plugin_ids = new Gee.HashSet<Plugin.EmailIdentifier>();
-            foreach (var id in engine_ids) {
-                plugin_ids.add(new IdImpl(id, account));
-            }
-            return plugin_ids;
-        }
-
-    }
-
-
     private class ContactStoreImpl : Geary.BaseObject, Plugin.ContactStore {
 
 
@@ -221,15 +68,18 @@ internal class Application.NotificationContext :
     private unowned Client application;
     private FolderStoreFactory folders_factory;
     private Plugin.FolderStore folders;
-    private EmailStoreImpl email;
+    private EmailStoreFactory email_factory;
+    private Plugin.EmailStore email;
 
 
     internal NotificationContext(Client application,
-                                 FolderStoreFactory folders_factory) {
+                                 FolderStoreFactory folders_factory,
+                                 EmailStoreFactory email_factory) {
         this.application = application;
         this.folders_factory = folders_factory;
         this.folders = folders_factory.new_folder_store();
-        this.email = new EmailStoreImpl(application);
+        this.email_factory = email_factory;
+        this.email = email_factory.new_email_store();
     }
 
     public async Plugin.EmailStore get_email()
@@ -353,6 +203,7 @@ internal class Application.NotificationContext :
         foreach (Geary.Folder monitored in this.folder_information.keys.to_array()) {
             remove_folder(monitored);
         }
+        this.email_factory.destroy_email_store(this.email);
     }
 
     internal void clear_new_messages(Geary.Folder location,
@@ -414,7 +265,9 @@ internal class Application.NotificationContext :
             new_messages_arrived(
                 folder,
                 info.recent_ids.size,
-                this.email.get_plugin_ids(delta, info.folder.account.information)
+                this.email_factory.to_plugin_ids(
+                    delta, info.folder.account.information
+                )
             );
         } else {
             this._total_new_messages -= delta.size;
diff --git a/src/client/application/application-plugin-manager.vala 
b/src/client/application/application-plugin-manager.vala
index 84a30921..fd89c5d7 100644
--- a/src/client/application/application-plugin-manager.vala
+++ b/src/client/application/application-plugin-manager.vala
@@ -125,6 +125,7 @@ public class Application.PluginManager : GLib.Object {
     private string trusted_path;
 
     private FolderStoreFactory folders_factory;
+    private EmailStoreFactory email_factory;
 
     private Gee.Map<Peas.PluginInfo,PluginContext> plugin_set =
         new Gee.HashMap<Peas.PluginInfo,PluginContext>();
@@ -136,6 +137,7 @@ public class Application.PluginManager : GLib.Object {
         this.application = application;
         this.plugins = Peas.Engine.get_default();
         this.folders_factory = new FolderStoreFactory(application);
+        this.email_factory = new EmailStoreFactory(application);
 
         this.trusted_path = application.get_app_plugins_dir().get_path();
         this.plugins.add_search_path(trusted_path, null);
@@ -229,6 +231,7 @@ public class Application.PluginManager : GLib.Object {
         this.plugins.set_loaded_plugins(null);
         this.plugins.garbage_collect();
         this.folders_factory.destroy();
+        this.email_factory.destroy();
     }
 
     internal inline bool is_autoload(Peas.PluginInfo info) {
@@ -266,7 +269,8 @@ public class Application.PluginManager : GLib.Object {
             if (notification != null) {
                 var context = new NotificationContext(
                     this.application,
-                    this.folders_factory
+                    this.folders_factory,
+                    this.email_factory
                 );
                 this.notification_contexts.set(info, context);
                 notification.notifications = context;
diff --git a/src/client/meson.build b/src/client/meson.build
index 36962f3e..2f6b250d 100644
--- a/src/client/meson.build
+++ b/src/client/meson.build
@@ -10,6 +10,7 @@ geary_client_vala_sources = files(
   'application/application-contact-store.vala',
   'application/application-contact.vala',
   'application/application-controller.vala',
+  'application/application-email-store-factory.vala',
   'application/application-folder-context.vala',
   'application/application-folder-store-factory.vala',
   'application/application-main-window.vala',


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