[geary/wip/778276-better-flag-updates: 13/19] Fire folders_contents_altered when we alter folder contents.



commit 261dce5131ef51994a39ae4b9858ea92e8a56f20
Author: Michael James Gratton <mike vee net>
Date:   Tue Nov 28 10:12:41 2017 +1100

    Fire folders_contents_altered when we alter folder contents.
    
    Ensuring f-c-a is fired means that the background sync will pick up the
    changes from the operations after they happen, rather than when the next
    folder refresh happens.
    
    * src/engine/imap-engine/imap-engine-generic-account.vala
      (Account::update_folders): Provide a convenience singleton version of
      ::update_folders to fire folders_contents_altered.
    
    * src/engine/imap-engine/imap-engine-generic-account.vala
      (RefreshFolderUnseen): Update cached status values for a folder and
      fire f-c-a signal, but only for folders that have changed.
    
    * src/engine/imap-engine/imap-engine-minimal-folder.vala
      (MinimalFolder::copy_email_async): Fire f-c-a signal after the op
      completes.
    
    * src/engine/imap-engine/imap-engine-revokable-move.vala (RevokableMove),
      src/engine/imap-engine/imap-engine-revokable-committed-move.vala
      (RevokableCommittedMove): Notify contents have changed when a move is
      revoked.

 .../imap-engine/imap-engine-generic-account.vala   |   34 +++++++++++--
 .../imap-engine/imap-engine-minimal-folder.vala    |   23 ++++++---
 .../imap-engine-revokable-committed-move.vala      |    3 +
 .../imap-engine/imap-engine-revokable-move.vala    |   52 +++++++++++++------
 .../imap-engine-send-replay-operation.vala         |   12 +++--
 5 files changed, 90 insertions(+), 34 deletions(-)
---
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index ad3e44d..7635ad2 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -532,7 +532,22 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
     }
 
     /**
+     * Fires appropriate signals for a single altered folder.
+     *
+     * This is functionally equivalent to {@link update_folders}.
+     */
+    internal void update_folder(Geary.Folder folder) {
+        Gee.Collection<Geary.Folder> folders =
+            new Gee.LinkedList<Geary.Folder>();
+        folders.add(folder);
+        debug("Contents altered!");
+        notify_folders_contents_altered(folders);
+    }
+
+    /**
      * Fires appropriate signals for folders have been altered.
+     *
+     * This is functionally equivalent to {@link update_folder}.
      */
     internal void update_folders(Gee.Collection<Geary.Folder> folders) {
         if (!folders.is_empty) {
@@ -1051,15 +1066,18 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation {
 internal class Geary.ImapEngine.RefreshFolderUnseen : AccountOperation {
 
 
-    private weak Geary.Folder folder;
+    private weak MinimalFolder folder;
+    private weak GenericAccount account;
     private weak Imap.Account remote;
     private weak ImapDB.Account local;
 
 
-    internal RefreshFolderUnseen(Geary.Folder folder,
+    internal RefreshFolderUnseen(MinimalFolder folder,
+                                 GenericAccount account,
                                  Imap.Account remote,
                                  ImapDB.Account local) {
         this.folder = folder;
+        this.account = account;
         this.remote = remote;
         this.local = local;
     }
@@ -1083,9 +1101,15 @@ internal class Geary.ImapEngine.RefreshFolderUnseen : AccountOperation {
                 cancellable
             );
 
-            yield local.update_folder_status_async(
-                remote_folder, false, true, cancellable
-            );
+            if (remote_folder.properties.have_contents_changed(
+                    this.folder.local_folder.get_properties(),
+                    this.folder.to_string())) {
+                yield local.update_folder_status_async(
+                    remote_folder, false, true, cancellable
+                );
+
+                this.account.update_folder(this.folder);
+            }
         }
     }
 
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala 
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index c1fbc40..b79ff83 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -1428,16 +1428,20 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
         
         yield mark.wait_for_ready_async(cancellable);
     }
-    
+
     public virtual async void copy_email_async(Gee.List<Geary.EmailIdentifier> to_copy,
-        Geary.FolderPath destination, Cancellable? cancellable = null) throws Error {
+                                               Geary.FolderPath destination,
+                                               Cancellable? cancellable = null)
+        throws Error {
+        Geary.Folder target = yield this._account.fetch_folder_async(destination);
         yield copy_email_uids_async(to_copy, destination, cancellable);
+        this._account.update_folder(target);
     }
-    
+
     /**
      * Returns the destination folder's UIDs for the copied messages.
      */
-    public async Gee.Set<Imap.UID>? copy_email_uids_async(Gee.List<Geary.EmailIdentifier> to_copy,
+    protected async Gee.Set<Imap.UID>? copy_email_uids_async(Gee.List<Geary.EmailIdentifier> to_copy,
         Geary.FolderPath destination, Cancellable? cancellable = null) throws Error {
         check_open("copy_email_uids_async");
         check_ids("copy_email_uids_async", to_copy);
@@ -1471,10 +1475,13 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
         
         if (prepare.prepared_for_move == null || prepare.prepared_for_move.size == 0)
             return null;
-        
-        return new RevokableMove(_account, this, destination, prepare.prepared_for_move);
+
+        Geary.Folder target = yield this._account.fetch_folder_async(destination);
+        return new RevokableMove(
+            _account, this, target, prepare.prepared_for_move
+        );
     }
-    
+
     public void schedule_op(ReplayOperation op) throws Error {
         check_open("schedule_op");
         
@@ -1604,7 +1611,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
         // We queue an account operation since the folder itself is
         // closed and hence does not have a connection to use for it.
         RefreshFolderUnseen op = new RefreshFolderUnseen(
-            this, this.remote, this.local
+            this, this._account, this.remote, this.local
         );
         try {
             this._account.queue_operation(op);
diff --git a/src/engine/imap-engine/imap-engine-revokable-committed-move.vala 
b/src/engine/imap-engine/imap-engine-revokable-committed-move.vala
index 3ac60dc..0f3f24a 100644
--- a/src/engine/imap-engine/imap-engine-revokable-committed-move.vala
+++ b/src/engine/imap-engine/imap-engine-revokable-committed-move.vala
@@ -42,6 +42,9 @@ private class Geary.ImapEngine.RevokableCommittedMove : Revokable {
             }
             
             notify_revoked();
+
+            Geary.Folder target = yield this.account.fetch_folder_async(this.destination);
+            this.account.update_folder(target);
         } finally {
             if (detached_destination != null) {
                 try {
diff --git a/src/engine/imap-engine/imap-engine-revokable-move.vala 
b/src/engine/imap-engine/imap-engine-revokable-move.vala
index 594697b..a637be0 100644
--- a/src/engine/imap-engine/imap-engine-revokable-move.vala
+++ b/src/engine/imap-engine/imap-engine-revokable-move.vala
@@ -17,11 +17,11 @@ private class Geary.ImapEngine.RevokableMove : Revokable {
     private const int COMMIT_TIMEOUT_SEC = 60;
     
     private GenericAccount account;
-    private ImapEngine.MinimalFolder source;
-    private FolderPath destination;
+    private MinimalFolder source;
+    private Geary.Folder destination;
     private Gee.Set<ImapDB.EmailIdentifier> move_ids;
     
-    public RevokableMove(GenericAccount account, ImapEngine.MinimalFolder source, FolderPath destination,
+    public RevokableMove(GenericAccount account, MinimalFolder source, Geary.Folder destination,
         Gee.Set<ImapDB.EmailIdentifier> move_ids) {
         base (COMMIT_TIMEOUT_SEC);
         
@@ -48,7 +48,7 @@ private class Geary.ImapEngine.RevokableMove : Revokable {
                 source.path.to_string(), destination.to_string());
             
             try {
-                source.schedule_op(new MoveEmailCommit(source, move_ids, destination, null));
+                source.schedule_op(new MoveEmailCommit(source, move_ids, destination.path, null));
             } catch (Error err) {
                 debug("Move from %s to %s failed: %s", source.path.to_string(), destination.to_string(),
                     err.message);
@@ -58,26 +58,34 @@ private class Geary.ImapEngine.RevokableMove : Revokable {
                 source.path.to_string(), source.get_open_state().to_string());
         }
     }
-    
+
     protected override async void internal_revoke_async(Cancellable? cancellable) throws Error {
         try {
-            yield source.exec_op_async(new MoveEmailRevoke(source, move_ids, cancellable),
-                cancellable);
-            
+            MoveEmailRevoke op = new MoveEmailRevoke(
+                source, move_ids, cancellable
+            );
+            yield source.exec_op_async(op, cancellable);
+
             // valid must still be true before firing
             notify_revoked();
+
+            yield op.wait_for_ready_async(cancellable);
+            this.account.update_folder(this.destination);
         } finally {
             set_invalid();
         }
     }
-    
+
     protected override async void internal_commit_async(Cancellable? cancellable) throws Error {
         try {
-            MoveEmailCommit op = new MoveEmailCommit(source, move_ids, destination, cancellable);
+            MoveEmailCommit op = new MoveEmailCommit(source, move_ids, destination.path, cancellable);
             yield source.exec_op_async(op, cancellable);
-            
+
             // valid must still be true before firing
-            notify_committed(new RevokableCommittedMove(account, source.path, destination, 
op.destination_uids));
+            notify_committed(new RevokableCommittedMove(account, source.path, destination.path, 
op.destination_uids));
+
+            yield op.wait_for_ready_async(cancellable);
+            this.account.update_folder(this.destination);
         } finally {
             set_invalid();
         }
@@ -87,7 +95,7 @@ private class Geary.ImapEngine.RevokableMove : Revokable {
         // look for either of the folders going away
         if (unavailable != null) {
             foreach (Folder folder in unavailable) {
-                if (folder.path.equal_to(source.path) || folder.path.equal_to(destination)) {
+                if (folder.path.equal_to(source.path) || folder.path.equal_to(destination.path)) {
                     set_invalid();
                     
                     break;
@@ -107,13 +115,23 @@ private class Geary.ImapEngine.RevokableMove : Revokable {
         if (move_ids.size <= 0)
             set_invalid();
     }
-    
+
     private void on_source_closing(Gee.List<ReplayOperation> final_ops) {
         if (!valid)
             return;
-        
-        final_ops.add(new MoveEmailCommit(source, move_ids, destination, null));
+
+        MoveEmailCommit op = new MoveEmailCommit(
+            source, move_ids, destination.path, null
+        );
+        final_ops.add(op);
         set_invalid();
+        op.wait_for_ready_async.begin(null, (obj, res) => {
+                try {
+                    op.wait_for_ready_async.end(res);
+                    this.account.update_folder(this.destination);
+                } catch (Error err) {
+                    // Oh well
+                }
+            });
     }
 }
-
diff --git a/src/engine/imap-engine/imap-engine-send-replay-operation.vala 
b/src/engine/imap-engine/imap-engine-send-replay-operation.vala
index 90d9d9c..d3f6bc3 100644
--- a/src/engine/imap-engine/imap-engine-send-replay-operation.vala
+++ b/src/engine/imap-engine/imap-engine-send-replay-operation.vala
@@ -4,21 +4,25 @@
  * (version 2.1 or later).  See the COPYING file in this distribution.
  */
 
+
+/**
+ * A replay operation for a user-initiated operation.
+ */
 private abstract class Geary.ImapEngine.SendReplayOperation : Geary.ImapEngine.ReplayOperation {
     protected SendReplayOperation(string name, ReplayOperation.OnError on_remote_error = OnError.THROW) {
         base (name, ReplayOperation.Scope.LOCAL_AND_REMOTE, on_remote_error);
     }
-    
+
     protected SendReplayOperation.only_local(string name, ReplayOperation.OnError on_remote_error = 
OnError.THROW) {
         base (name, ReplayOperation.Scope.LOCAL_ONLY, on_remote_error);
     }
-    
+
     protected SendReplayOperation.only_remote(string name, ReplayOperation.OnError on_remote_error = 
OnError.THROW) {
         base (name, ReplayOperation.Scope.REMOTE_ONLY, on_remote_error);
     }
-    
+
     public override void notify_remote_removed_position(Imap.SequenceNumber removed) {
         // we've worked very hard to keep positional addressing out of the SendReplayOperations
     }
-}
 
+}


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