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.
This commit is contained in:
parent
3202a9c018
commit
f0c1dfe375
5 changed files with 227 additions and 158 deletions
|
|
@ -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
|
||||
|
|
|
|||
210
src/client/application/application-email-store-factory.vala
Normal file
210
src/client/application/application-email-store-factory.vala
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue