[geary/mjog/invert-folder-class-hierarchy] engine: Fix loading conversations with many partial emails



commit fc6979159b5000e5f22ba41d76885ce39fd0eaef
Author: Michael Gratton <mike vee net>
Date:   Sun Mar 7 09:59:33 2021 +1100

    engine: Fix loading conversations with many partial emails
    
    When loading email by range, `ConversationMonitor` must load more when
    partials are encountered so as to be able to satisfy the requested
    number of emails to load - otherwise `FillOperation` won't be able to
    determine when to continue loading email to fill the window.

 src/engine/app/app-conversation-monitor.vala | 54 +++++++++++++++++-----------
 1 file changed, 33 insertions(+), 21 deletions(-)
---
diff --git a/src/engine/app/app-conversation-monitor.vala b/src/engine/app/app-conversation-monitor.vala
index 9780586b2..f264c9250 100644
--- a/src/engine/app/app-conversation-monitor.vala
+++ b/src/engine/app/app-conversation-monitor.vala
@@ -482,7 +482,7 @@ public class Geary.App.ConversationMonitor : BaseObject, Logging.Source {
     }
 
     /** Loads messages from the base folder into the window. */
-    internal async int load_by_id_async(EmailIdentifier? initial_id,
+    internal async int load_by_id_async(EmailIdentifier? initial,
                                         int count,
                                         Folder.ListFlags flags = Folder.ListFlags.NONE)
         throws GLib.Error {
@@ -491,29 +491,41 @@ public class Geary.App.ConversationMonitor : BaseObject, Logging.Source {
         int load_count = 0;
         GLib.Error? scan_error = null;
         try {
-            Gee.Collection<Geary.Email> emails =
-                yield this.base_folder.list_email_range_by_id(
-                    initial_id,
-                    count,
-                    this.required_fields,
-                    flags | INCLUDING_PARTIAL,
-                    this.operation_cancellable
-                );
+            // Need to potentially run the query multiple times since
+            // if any partial emails are loaded, there will be less
+            // than expected.
+            var complete = Email.new_identifier_based_set();
+            var next = initial;
+            while (complete.size < count) {
+                Gee.List<Geary.Email> loaded =
+                    yield this.base_folder.list_email_range_by_id(
+                        next,
+                        count - complete.size,
+                        this.required_fields,
+                        flags | INCLUDING_PARTIAL,
+                        this.operation_cancellable
+                    );
+                if (!loaded.is_empty) {
+                    next = loaded[loaded.size - 1].id;
+                }
 
-            var i = emails.iterator();
-            while (i.next()) {
-                var email = i.get();
-                if (this.required_fields in email.fields) {
-                    this.window.add(email.id);
-                } else {
-                    this.incomplete.add(email.id);
-                    i.remove();
+                foreach (var email in loaded) {
+                    if (this.required_fields in email.fields) {
+                        complete.add(email);
+                        this.window.add(email.id);
+                    } else {
+                        this.incomplete.add(email.id);
+                    }
+                }
+
+                if (loaded.size < count) {
+                    break;
                 }
             }
 
-            if (!emails.is_empty) {
-                load_count = emails.size;
-                yield process_email_async(emails, ProcessJobContext());
+            if (!complete.is_empty) {
+                load_count = complete.size;
+                yield process_email_async(complete, ProcessJobContext());
             }
         } catch (GLib.Error err) {
             scan_error = err;
@@ -529,7 +541,7 @@ public class Geary.App.ConversationMonitor : BaseObject, Logging.Source {
     }
 
     /** Loads messages from the base folder into the window. */
-        internal async void load_by_sparse_id(
+    internal async void load_by_sparse_id(
             Gee.Collection<EmailIdentifier> ids
         ) throws GLib.Error {
         notify_scan_started();


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