[geary/wip/789924-network-transition-redux: 6/11] Remove remote_count and get_remote_counts from MinimalFolder.



commit 77911e992fcf0db83cca0ae779417eb0571ef476
Author: Michael James Gratton <mike vee net>
Date:   Fri Feb 2 22:19:07 2018 +1030

    Remove remote_count and get_remote_counts from MinimalFolder.
    
    These duplicate state already stored and available from the local and
    remote session's folder properties, and the get_remote_counts method
    duplicates the preference ordering of SELECT over STATUS data in
    Imap.FolderProperties.
    
    * src/engine/imap-engine/imap-engine-minimal-folder.vala (MinimalFolder):
      Remove remote_count property and get_remote_counts method. Add
      is_remote_available since one use of the former was to determine if
      a remote session is present. Update all uses of remote_count to use the
      remote session's folder properties instead. Make remote session and
      properties available early when establishing a remote session so
      append/remove/etc handlers can actually access its properties.
    
    * src/engine/imap/api/imap-folder-session.vala (SessionObject): Make
      appended signal report the number of appended messages istead of the
      new folder total, so MinimalFolder's handler knows without needing to
      keep the old remote_count around, and since the total is available from
      the session's folder properties anyway. Remove the total param from the
      removed signal, for the same reason.

 .../imap-engine/imap-engine-minimal-folder.vala    |  129 +++++++++-----------
 .../imap-engine-abstract-list-email.vala           |   46 ++++----
 .../replay-ops/imap-engine-empty-folder.vala       |   11 +-
 .../replay-ops/imap-engine-move-email-commit.vala  |   12 +-
 .../replay-ops/imap-engine-move-email-prepare.vala |    7 +-
 .../replay-ops/imap-engine-move-email-revoke.vala  |    9 +-
 .../replay-ops/imap-engine-remove-email.vala       |   15 +--
 .../replay-ops/imap-engine-replay-append.vala      |    8 +-
 .../replay-ops/imap-engine-replay-removal.vala     |    9 +-
 src/engine/imap/api/imap-folder-session.vala       |   20 ++--
 10 files changed, 127 insertions(+), 139 deletions(-)
---
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala 
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index b9e0f86..b51c55b 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -61,8 +61,24 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
         }
     }
 
-    internal ImapDB.Folder local_folder  { get; private set; }
-    internal int remote_count { get; private set; default = -1; }
+    /** The IMAP database representation of the folder. */
+    internal ImapDB.Folder local_folder { get; private set; }
+
+    /**
+     * Determines if a remote session is currently available.
+     *
+     * If this property is //true//, then a subsequent call to {@link
+     * wait_for_remote_async} or {@link claim_remote_session} should
+     * return immediately without error.
+     */
+    internal bool is_remote_available {
+        get {
+            return (
+                this.remote_wait_semaphore.can_pass &&
+                this.remote_wait_semaphore.result
+            );
+        }
+    }
 
     internal ReplayQueue replay_queue { get; private set; }
     internal EmailPrefetcher email_prefetcher { get; private set; }
@@ -194,23 +210,6 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
            : Geary.Folder.OpenState.LOCAL;
     }
 
-    // Returns the synchronized remote count (-1 if not opened) and the last seen remote count (stored
-    // locally, -1 if not available)
-    //
-    // Return value is the remote_count, unless the remote is unopened, in which case it's the
-    // last_seen_remote_count (which may also be -1).
-    //
-    // remote_count, last_seen_remote_count, and returned value do not reflect any notion of
-    // messages marked for removal
-    internal int get_remote_counts(out int remote_count, out int last_seen_remote_count) {
-        remote_count = this.remote_count;
-        last_seen_remote_count = local_folder.get_properties().select_examine_messages;
-        if (last_seen_remote_count < 0)
-            last_seen_remote_count = local_folder.get_properties().status_messages;
-
-        return (remote_count >= 0) ? remote_count : last_seen_remote_count;
-    }
-
     /** {@inheritDoc} */
     public override async bool open_async(Geary.Folder.OpenFlags open_flags, Cancellable? cancellable = null)
         throws Error {
@@ -245,9 +244,10 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
         this.email_prefetcher.open();
 
         // notify about the local open
-        int local_count = 0;
-        get_remote_counts(null, out local_count);
-        notify_opened(Geary.Folder.OpenState.LOCAL, local_count);
+        notify_opened(
+            Geary.Folder.OpenState.LOCAL,
+            this.local_folder.get_properties().email_total
+        );
 
         // Unless NO_DELAY is set, do NOT open the remote side here; wait for the ReplayQueue to
         // require a remote connection or wait_for_remote_async() to be called ... this allows for
@@ -677,7 +677,6 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
 
         Imap.FolderSession session = this.remote_session;
         this.remote_session = null;
-        this.remote_count = -1;
 
         if (session != null) {
             session.appended.disconnect(on_remote_appended);
@@ -866,14 +865,6 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
 
         // Phase 2: Update local state based on the remote session
 
-        // Signals need to be hooked up before normalisation so that
-        // notifications of state changes are not lost when that is
-        // running.
-        session.appended.connect(on_remote_appended);
-        session.updated.connect(on_remote_updated);
-        session.removed.connect(on_remote_removed);
-        session.disconnected.connect(on_remote_disconnected);
-
         try {
             yield normalize_folders(session, cancellable);
         } catch (Error err) {
@@ -904,6 +895,17 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
             return;
         }
 
+        this._properties.add(session.folder.properties);
+        this.remote_session = session;
+
+        // Signals need to be hooked after the remote session is in
+        // place so they can access the remote session's folder
+        // properties.
+        session.appended.connect(on_remote_appended);
+        session.updated.connect(on_remote_updated);
+        session.removed.connect(on_remote_removed);
+        session.disconnected.connect(on_remote_disconnected);
+
         try {
             yield local_folder.update_folder_select_examine(
                 session.folder.properties, cancellable
@@ -926,15 +928,13 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
             return;
         }
 
-        this._properties.add(session.folder.properties);
-        this.remote_count = session.folder.properties.email_total;
-
-        // Phase 3: Move in place and notify waiters
-
-        this.remote_session = session;
+        // Phase 3: Notify tasks waiting for the connection
 
         // notify any subscribers with similar information
-        notify_opened(Geary.Folder.OpenState.BOTH, this.remote_count);
+        notify_opened(
+            Geary.Folder.OpenState.BOTH,
+            session.folder.properties.email_total
+        );
 
         // notify any threads of execution waiting for the remote
         // folder to open that the result of that operation is ready
@@ -974,27 +974,21 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
     private void on_email_complete(Gee.Collection<Geary.EmailIdentifier> email_ids) {
         notify_email_locally_complete(email_ids);
     }
-    
-    private void on_remote_appended(int reported_remote_count) {
-        debug("%s on_remote_appended: remote_count=%d reported_remote_count=%d", to_string(), remote_count,
-            reported_remote_count);
-        
-        if (reported_remote_count < 0)
-            return;
-        
+
+    private void on_remote_appended(int appended) {
+        int remote_count = this.remote_session.folder.properties.email_total;
+        debug("%s on_remote_appended: remote_count=%d appended=%d",
+              to_string(), remote_count, appended);
+
         // from the new remote total and the old remote total, glean the SequenceNumbers of the
         // new email(s)
         Gee.List<Imap.SequenceNumber> positions = new Gee.ArrayList<Imap.SequenceNumber>();
-        for (int pos = remote_count + 1; pos <= reported_remote_count; pos++)
+        for (int pos = remote_count - appended + 1; pos <= remote_count; pos++)
             positions.add(new Imap.SequenceNumber(pos));
 
-        // store the remote count NOW, as further appended messages could arrive before the
-        // ReplayAppend executes
-        this.remote_count = reported_remote_count;
-
         if (positions.size > 0) {
             ReplayAppend op = new ReplayAppend(
-                this, reported_remote_count, positions, this.open_cancellable
+                this, remote_count, positions, this.open_cancellable
             );
             op.email_appended.connect(notify_email_appended);
             op.email_locally_appended.connect(notify_email_locally_appended);
@@ -1004,35 +998,24 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
     }
 
     private void on_remote_updated(Imap.SequenceNumber position, Imap.FetchedData data) {
+        int remote_count = this.remote_session.folder.properties.email_total;
         debug("%s on_remote_updated: remote_count=%d position=%s", to_string(),
-              this.remote_count, position.to_string());
+              remote_count, position.to_string());
 
         this.replay_queue.schedule_server_notification(
-            new ReplayUpdate(this, this.remote_count, position, data)
+            new ReplayUpdate(this, remote_count, position, data)
         );
     }
 
-    private void on_remote_removed(Imap.SequenceNumber position, int reported_remote_count) {
-        debug("%s on_remote_removed: remote_count=%d position=%s reported_remote_count=%d", to_string(),
-            remote_count, position.to_string(), reported_remote_count);
-        
-        if (reported_remote_count < 0)
-            return;
-        
+    private void on_remote_removed(Imap.SequenceNumber position) {
+        int remote_count = this.remote_session.folder.properties.email_total;
+        debug("%s on_remote_removed: remote_count=%d position=%s",
+              to_string(), remote_count, position.to_string());
+
         // notify of removal to all pending replay operations
         replay_queue.notify_remote_removed_position(position);
-        
-        // update remote count NOW, as further appended and removed messages can arrive before
-        // ReplayRemoval executes
-        //
-        // something to note at this point: the ExpungeEmail operation marks messages as removed,
-        // then signals they're removed and reports an adjusted count in its replay_local_async().
-        // remote_count is *not* updated, which is why it's safe to do that here without worry.
-        // similarly, signals are only fired here if marked, so the same EmailIdentifier isn't
-        // reported twice
-        this.remote_count = reported_remote_count;
-
-        ReplayRemoval op = new ReplayRemoval(this, reported_remote_count, position);
+
+        ReplayRemoval op = new ReplayRemoval(this, remote_count, position);
         op.email_removed.connect(notify_email_removed);
         op.marked_email_removed.connect(notify_marked_email_removed);
         op.email_count_changed.connect(notify_email_count_changed);
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala
index c6aa149..271c441 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-abstract-list-email.vala
@@ -214,20 +214,26 @@ private abstract class Geary.ImapEngine.AbstractListEmail : Geary.ImapEngine.Sen
      * Determines if the owning folder's vector is fully expanded.
      */
     protected async Trillian is_fully_expanded_async() throws Error {
-        int remote_count;
-        owner.get_remote_counts(out remote_count, null);
-        
-        // if unknown (unconnected), say so
-        if (remote_count < 0)
-            return Trillian.UNKNOWN;
-        
-        // include marked for removed in the count in case this is being called while a removal
-        // is in process, in which case don't want to expand vector this moment because the
-        // vector is in flux
-        int local_count_with_marked = yield owner.local_folder.get_email_count_async(
-            ImapDB.Folder.ListFlags.INCLUDE_MARKED_FOR_REMOVE, cancellable);
-        
-        return Trillian.from_boolean(local_count_with_marked >= remote_count);
+        Trillian is_fully_expanded = Trillian.UNKNOWN;
+        if (this.owner.is_remote_available) {
+            Imap.FolderSession remote =
+                yield this.owner.claim_remote_session(this.cancellable);
+            int remote_count = remote.folder.properties.email_total;
+
+            // include marked for removed in the count in case this is
+            // being called while a removal is in process, in which
+            // case don't want to expand vector this moment because
+            // the vector is in flux
+            int local_count_with_marked =
+                yield owner.local_folder.get_email_count_async(
+                    ImapDB.Folder.ListFlags.INCLUDE_MARKED_FOR_REMOVE, cancellable
+                );
+
+            is_fully_expanded = Trillian.from_boolean(
+                local_count_with_marked >= remote_count
+            );
+        }
+        return is_fully_expanded;
     }
 
     /**
@@ -246,18 +252,16 @@ private abstract class Geary.ImapEngine.AbstractListEmail : Geary.ImapEngine.Sen
      */
     protected async Gee.Set<Imap.UID>? expand_vector_async(Imap.UID? initial_uid, int count) throws Error {
         debug("%s: expanding vector...", owner.to_string());
-        // watch out for situations where the entire folder is represented locally (i.e. no
-        // expansion necessary)
-        int remote_count = owner.get_remote_counts(null, null);
-        if (remote_count <= 0)
-            return null;
+        Imap.FolderSession remote =
+            yield this.owner.claim_remote_session(cancellable);
+        int remote_count = remote.folder.properties.email_total;
 
         // include marked for removed in the count in case this is being called while a removal
         // is in process, in which case don't want to expand vector this moment because the
         // vector is in flux
         int local_count = yield owner.local_folder.get_email_count_async(
             ImapDB.Folder.ListFlags.INCLUDE_MARKED_FOR_REMOVE, cancellable);
-        
+
         // watch out for attempts to expand vector when it's expanded as far as it will go
         if (local_count >= remote_count)
             return null;
@@ -270,8 +274,6 @@ private abstract class Geary.ImapEngine.AbstractListEmail : Geary.ImapEngine.Sen
         int64 high_pos = -1;
         int64 initial_pos = -1;
 
-        Imap.FolderSession remote =
-            yield this.owner.claim_remote_session(cancellable);
         if (initial_uid != null) {
             Gee.Map<Imap.UID, Imap.SequenceNumber>? map =
             yield remote.uid_to_position_async(
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-empty-folder.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-empty-folder.vala
index e64e1d0..e2133df 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-empty-folder.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-empty-folder.vala
@@ -24,14 +24,13 @@ private class Geary.ImapEngine.EmptyFolder : Geary.ImapEngine.SendReplayOperatio
     
     public override void notify_remote_removed_ids(Gee.Collection<ImapDB.EmailIdentifier> ids) {
     }
-    
+
     public override async ReplayOperation.Status replay_local_async() throws Error {
-        original_count = engine.get_remote_counts(null, null);
-        
+        this.original_count = this.engine.properties.email_total;
         // because this value is only used for reporting count changes, offer best-possible service
-        if (original_count < 0)
-            original_count = 0;
-        
+        if (this.original_count < 0)
+            this.original_count = 0;
+
         // mark everything in the folder as removed
         removed_ids = yield engine.local_folder.mark_removed_async(null, true, cancellable);
         
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-move-email-commit.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-move-email-commit.vala
index 57947ab..651a8de 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-move-email-commit.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-move-email-commit.vala
@@ -84,15 +84,17 @@ private class Geary.ImapEngine.MoveEmailCommit : Geary.ImapEngine.SendReplayOper
     public override async void backout_local_async() throws Error {
         if (to_move.size == 0)
             return;
-        
+
         yield engine.local_folder.mark_removed_async(to_move, false, cancellable);
-        
-        int count = engine.get_remote_counts(null, null);
-        
+
+        int count = this.engine.properties.email_total;
+        if (count < 0) {
+            count = 0;
+        }
         engine.replay_notify_email_inserted(to_move);
         engine.replay_notify_email_count_changed(count + to_move.size, Folder.CountChangeReason.INSERTED);
     }
-    
+
     public override string describe_state() {
         return "%d email IDs to %s".printf(to_move.size, destination.to_string());
     }
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-move-email-prepare.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-move-email-prepare.vala
index 4b4dde4..a6d7942 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-move-email-prepare.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-move-email-prepare.vala
@@ -36,13 +36,12 @@ private class Geary.ImapEngine.MoveEmailPrepare : Geary.ImapEngine.SendReplayOpe
     public override async ReplayOperation.Status replay_local_async() throws Error {
         if (to_move.size <= 0)
             return ReplayOperation.Status.COMPLETED;
-        
-        int count = engine.get_remote_counts(null, null);
-        
+
+        int count = this.engine.properties.email_total;
         // as this value is only used for reporting, offer best-possible service
         if (count < 0)
             count = to_move.size;
-        
+
         prepared_for_move = yield engine.local_folder.mark_removed_async(to_move, true, cancellable);
         if (prepared_for_move == null || prepared_for_move.size == 0)
             return ReplayOperation.Status.COMPLETED;
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-move-email-revoke.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-move-email-revoke.vala
index b9a010d..7526d55 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-move-email-revoke.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-move-email-revoke.vala
@@ -35,9 +35,12 @@ private class Geary.ImapEngine.MoveEmailRevoke : Geary.ImapEngine.SendReplayOper
             to_revoke, false, cancellable);
         if (revoked == null || revoked.size == 0)
             return ReplayOperation.Status.COMPLETED;
-        
-        int count = engine.get_remote_counts(null, null);
-        
+
+        int count = this.engine.properties.email_total;
+        if (count < 0) {
+            count = 0;
+        }
+
         engine.replay_notify_email_inserted(revoked);
         engine.replay_notify_email_count_changed(count + revoked.size,
             Geary.Folder.CountChangeReason.INSERTED);
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-remove-email.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-remove-email.vala
index acc60aa..47b3417 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-remove-email.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-remove-email.vala
@@ -28,17 +28,14 @@ private class Geary.ImapEngine.RemoveEmail : Geary.ImapEngine.SendReplayOperatio
     
     public override async ReplayOperation.Status replay_local_async() throws Error {
         // if performing a full expunge, need to move on to replay_remote_async() for that
-        if (to_remove.size <= 0)
+        if (this.to_remove.size <= 0)
             return ReplayOperation.Status.COMPLETED;
-        
-        int remote_count;
-        int last_seen_remote_count;
-        original_count = engine.get_remote_counts(out remote_count, out last_seen_remote_count);
-        
+
+        this.original_count = this.engine.properties.email_total;
         // because this value is only used for reporting count changes, offer best-possible service
-        if (original_count < 0)
-            original_count = to_remove.size;
-        
+        if (this.original_count < 0)
+            this.original_count = this.to_remove.size;
+
         removed_ids = yield engine.local_folder.mark_removed_async(to_remove, true, cancellable);
         if (removed_ids == null || removed_ids.size == 0)
             return ReplayOperation.Status.COMPLETED;
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-replay-append.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-replay-append.vala
index 6091052..02055b6 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-replay-append.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-replay-append.vala
@@ -87,8 +87,8 @@ private class Geary.ImapEngine.ReplayAppend : Geary.ImapEngine.ReplayOperation {
             positions_builder.append_printf("%s ", remote_position.to_string());
         positions_builder.append(")");
 
-        debug("%s do_replay_appended_message: current remote_count=%d this.remote_count=%d 
this.positions=%s",
-            to_string(), remote_count, this.remote_count, positions_builder.str);
+        debug("%s do_replay_appended_message: this.remote_count=%d this.positions=%s",
+            to_string(), this.remote_count, positions_builder.str);
 
         Gee.HashSet<Geary.EmailIdentifier> created = new Gee.HashSet<Geary.EmailIdentifier>();
         Gee.HashSet<Geary.EmailIdentifier> appended = new Gee.HashSet<Geary.EmailIdentifier>();
@@ -141,8 +141,8 @@ private class Geary.ImapEngine.ReplayAppend : Geary.ImapEngine.ReplayOperation {
 
         email_count_changed(this.remote_count, Folder.CountChangeReason.APPENDED);
 
-        debug("%s do_replay_appended_message: completed, current remote_count=%d this.remote_count=%d",
-            to_string(), remote_count, this.remote_count);
+        debug("%s do_replay_appended_message: completed, this.remote_count=%d",
+              to_string(), this.remote_count);
     }
 
 }
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-replay-removal.vala 
b/src/engine/imap-engine/replay-ops/imap-engine-replay-removal.vala
index 55891a3..b90598e 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-replay-removal.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-replay-removal.vala
@@ -47,9 +47,8 @@ private class Geary.ImapEngine.ReplayRemoval : Geary.ImapEngine.ReplayOperation
     }
 
     public override async ReplayOperation.Status replay_remote_async() throws Error {
-        debug("%s: ReplayRemoval current remote_count=%d this.position=%s reported_remote_count=%d",
-              this.owner.to_string(), this.owner.remote_count,
-              this.position.value.to_string(), this.remote_count);
+        debug("%s: ReplayRemoval this.position=%s reported_remote_count=%d",
+              this.owner.to_string(), this.position.value.to_string(), this.remote_count);
 
         if (this.position.is_valid()) {
             yield do_replay_removed_message();
@@ -151,9 +150,9 @@ private class Geary.ImapEngine.ReplayRemoval : Geary.ImapEngine.ReplayOperation
             );
         }
 
-        debug("%s ReplayRemoval: completed, current remote_count=%d "
+        debug("%s ReplayRemoval: completed, "
             + "(this.remote_count=%d local_count=%d starting local_count=%d this.position=%ld 
local_position=%ld marked=%s)",
-              this.owner.to_string(), this.owner.remote_count,
+              this.owner.to_string(),
               this.remote_count, new_local_count, local_count,
               this.position.value, local_position, marked.to_string());
     }
diff --git a/src/engine/imap/api/imap-folder-session.vala b/src/engine/imap/api/imap-folder-session.vala
index 3093ec3..06f7a13 100644
--- a/src/engine/imap/api/imap-folder-session.vala
+++ b/src/engine/imap/api/imap-folder-session.vala
@@ -78,7 +78,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
     /**
      * Fabricated from the IMAP signals and state obtained at open_async().
      */
-    public signal void appended(int total);
+    public signal void appended(int count);
 
     /**
      * Fabricated from the IMAP signals and state obtained at open_async().
@@ -88,7 +88,7 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
     /**
      * Fabricated from the IMAP signals and state obtained at open_async().
      */
-    public signal void removed(SequenceNumber pos, int total);
+    public signal void removed(SequenceNumber pos);
 
 
     public async FolderSession(string account_id,
@@ -173,19 +173,23 @@ private class Geary.Imap.FolderSession : Geary.Imap.SessionObject {
         this.folder.properties.set_select_examine_message_count(total);
 
         exists(total);
-        if (old_total < total)
-            appended(total);
+        if (old_total >= 0 && old_total < total) {
+            appended(total - old_total);
+        }
     }
 
     private void on_expunge(SequenceNumber pos) {
         debug("%s EXPUNGE %s", to_string(), pos.to_string());
 
-        this.folder.properties.set_select_examine_message_count(
-            this.folder.properties.select_examine_messages - 1
-        );
+        int old_total = this.folder.properties.select_examine_messages;
+        if (old_total > 0) {
+            this.folder.properties.set_select_examine_message_count(
+                old_total - 1
+            );
+        }
 
         expunge(pos);
-        removed(pos, this.folder.properties.select_examine_messages);
+        removed(pos);
     }
 
     private void on_fetch(FetchedData data) {


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