From 3e264e2cd4d3765e4e8a07e3ead87d07748e8278 Mon Sep 17 00:00:00 2001 From: Michael Gratton Date: Tue, 9 Feb 2021 01:00:16 +1100 Subject: [PATCH] Geary.ImapEngine.GenericAccount: Call new account sync API as needed Call the appropriate methods on AccountSynchronizer when folders need to be refreshed or fully synced. Ensure all remote folders are fully sync'ed when a connection is first/re-established so that any changes made are also picked up on re-connect. --- .../imap-engine-generic-account.vala | 75 +++++++++++++------ 1 file changed, 52 insertions(+), 23 deletions(-) diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala b/src/engine/imap-engine/imap-engine-generic-account.vala index c3ae2603..7ead3011 100644 --- a/src/engine/imap-engine/imap-engine-generic-account.vala +++ b/src/engine/imap-engine/imap-engine-generic-account.vala @@ -43,6 +43,8 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { public ImapDB.Account local { get; private set; } public signal void old_messages_background_cleanup_request(GLib.Cancellable? cancellable); + /** The account's remote folder synchroniser. */ + internal AccountSynchronizer sync { get; private set; } private bool open = false; private Cancellable? open_cancellable = null; @@ -54,7 +56,6 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { new Gee.HashMap(); private AccountProcessor? processor; - private AccountSynchronizer sync; private TimeoutManager refresh_folder_timer; private Gee.Map> special_search_names = @@ -101,7 +102,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { this.refresh_folder_timer = new TimeoutManager.seconds( REFRESH_FOLDER_LIST_SEC, - () => { this.update_remote_folders(); } + () => { this.update_remote_folders(true); } ); this.background_progress = new ReentrantProgressMonitor(ACTIVITY); @@ -703,7 +704,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { } /** - * Fires appropriate signals for a single altered folder. + * Notifies the engine a folder's contents have been altered. * * This is functionally equivalent to {@link update_folders}. */ @@ -712,17 +713,17 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { new Gee.LinkedList(); folders.add(folder); debug("Folder updated: %s", folder.path.to_string()); - notify_folders_contents_altered(folders); + this.sync.folders_contents_altered(folders); } /** - * Fires appropriate signals for folders have been altered. + * Notifies the engine multiple folders' contents have been altered. * * This is functionally equivalent to {@link update_folder}. */ internal void update_folders(Gee.Collection folders) { if (!folders.is_empty) { - notify_folders_contents_altered(sort_by_path(folders)); + this.sync.folders_contents_altered(folders); } } @@ -924,20 +925,26 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { /** * Hooks up and queues an {@link UpdateRemoteFolders} operation. */ - private void update_remote_folders() { + private void update_remote_folders(bool already_connected) { this.refresh_folder_timer.reset(); - UpdateRemoteFolders op = new UpdateRemoteFolders( + var op = new UpdateRemoteFolders( this, + already_connected, get_supported_special_folders() ); op.completed.connect(() => { this.refresh_folder_timer.start(); }); - try { - queue_operation(op); - } catch (Error err) { - // oh well + if (this.imap.current_status == CONNECTED) { + try { + queue_operation(op); + } catch (GLib.Error err) { + debug("Failed to update queue for %s %s", + op.to_string(), err.message); + } + } else { + this.processor.dequeue(op); } } @@ -1115,7 +1122,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account { if (this.open) { if (this.imap.current_status == CONNECTED) { this.remote_ready_lock.blind_notify(); - update_remote_folders(); + update_remote_folders(false); } else { this.remote_ready_lock.reset(); this.refresh_folder_timer.reset(); @@ -1234,13 +1241,16 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation { private weak GenericAccount generic_account; + private bool already_connected; private Folder.SpecialUse[] specials; internal UpdateRemoteFolders(GenericAccount account, + bool already_connected, Folder.SpecialUse[] specials) { base(account); this.generic_account = account; + this.already_connected = already_connected; this.specials = specials; } @@ -1386,7 +1396,8 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation { // For folders to add, clone them and their properties // locally, then add to the account - ImapDB.Account local = ((GenericAccount) this.account).local; + var generic_account = (GenericAccount) this.account; + var local = generic_account.local; Gee.ArrayList to_build = new Gee.ArrayList(); foreach (Geary.Imap.Folder remote_folder in to_add) { try { @@ -1430,16 +1441,34 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation { ); } - // report all altered folders - if (altered_paths.size > 0) { - Gee.ArrayList altered = new Gee.ArrayList(); - foreach (Geary.FolderPath altered_path in altered_paths) { - if (existing_folders.has_key(altered_path)) - altered.add(existing_folders.get(altered_path)); - else - debug("Unable to report %s altered: no local representation", altered_path.to_string()); + if (this.already_connected) { + // Notify of updated folders only when already + // connected. This will cause them to get refreshed. + if (altered_paths.size > 0) { + Gee.ArrayList altered = new Gee.ArrayList(); + foreach (Geary.FolderPath altered_path in altered_paths) { + if (existing_folders.has_key(altered_path)) + altered.add(existing_folders.get(altered_path)); + else + debug("Unable to report %s altered: no local representation", altered_path.to_string()); + } + this.generic_account.update_folders(altered); + } + } else { + // Notify all remote folders after re-connecting so they + // get fully sync'ed + if (remote_folders.size > 0) { + var remotes = new Gee.ArrayList(); + foreach (var path in remote_folders.keys) { + if (existing_folders.has_key(path)) { + remotes.add(existing_folders.get(path)); + } else { + debug("Unable to report %s remote: no local representation", + path.to_string()); + } + } + this.generic_account.sync.folders_discovered(remotes); } - this.generic_account.update_folders(altered); } // Ensure each of the important special folders we need already exist