[geary/wip/730682-refine-convo-list] Implement decent preview loading.



commit 86ab45c5d35e4c3b4ca25a003e6fd473bad4d3a9
Author: Michael James Gratton <mike vee net>
Date:   Tue Dec 12 10:00:19 2017 +1100

    Implement decent preview loading.
    
    * src/client/conversation-list/preview-loader.vala (PreviewLoader): Batch
      up preview loads so they can happen in a single database/remote
      call. Add a timer so that single loads still happen.

 .../conversation-list/conversation-list-item.vala  |   24 ++++--
 src/client/conversation-list/preview-loader.vala   |   84 ++++++++++++++------
 2 files changed, 75 insertions(+), 33 deletions(-)
---
diff --git a/src/client/conversation-list/conversation-list-item.vala 
b/src/client/conversation-list/conversation-list-item.vala
index b07afc2..6504aa5 100644
--- a/src/client/conversation-list/conversation-list-item.vala
+++ b/src/client/conversation-list/conversation-list-item.vala
@@ -97,19 +97,19 @@ public class ConversationListItem : Gtk.Grid {
     private Geary.App.Conversation conversation;
     private Gee.List<Geary.RFC822.MailboxAddress> account_addresses;
     private bool use_to;
-    private PreviewLoader preview_loader;
+    private PreviewLoader previews;
     private Cancellable preview_cancellable = new Cancellable();
     private Configuration config;
 
     public ConversationListItem(Geary.App.Conversation conversation,
                                 Gee.List<Geary.RFC822.MailboxAddress> account_addresses,
                                 bool use_to,
-                                PreviewLoader preview_loader,
+                                PreviewLoader previews,
                                 Configuration config) {
         this.conversation = conversation;
         this.account_addresses = account_addresses;
         this.use_to = use_to;
-        this.preview_loader = preview_loader;
+        this.previews = previews;
         this.config = config;
 
         this.conversation.appended.connect(() => {
@@ -180,15 +180,15 @@ public class ConversationListItem : Gtk.Grid {
             }
             this.subject.set_tooltip_text(tooltip_text);
 
-
             if (this.config.display_preview) {
-                this.preview_loader.load.begin(
+                this.previews.request.begin(
                     preview_message,
                     this.preview_cancellable,
                     (obj, ret) => {
-                        string? preview_text = this.preview_loader.load.end(ret);
-                        if (preview_text != null) {
-                            this.preview.set_text(preview_text);
+                        Geary.Email? updated = this.previews.request.end(ret);
+                        if (updated != null &&
+                            !this.preview_cancellable.is_cancelled()) {
+                            set_preview_text(updated);
                         }
                     });
                 this.preview.show();
@@ -267,4 +267,12 @@ public class ConversationListItem : Gtk.Grid {
         return builder.str;
     }
 
+    private void set_preview_text(Geary.Email preview_message) {
+        this.preview.set_text(
+            Geary.String.reduce_whitespace(
+                preview_message.get_preview_as_string()
+            )
+        );
+    }
+
 }
diff --git a/src/client/conversation-list/preview-loader.vala 
b/src/client/conversation-list/preview-loader.vala
index 9b0a698..65f6354 100644
--- a/src/client/conversation-list/preview-loader.vala
+++ b/src/client/conversation-list/preview-loader.vala
@@ -31,7 +31,20 @@ public class PreviewLoader : Geary.BaseObject {
     }
 
 
+    private class LoadSet {
+
+        public Gee.Map<Geary.EmailIdentifier,Geary.Email?> to_load =
+            new Gee.HashMap<Geary.EmailIdentifier,Geary.Email?>();
+        public Geary.Nonblocking.Semaphore loaded =
+            new Geary.Nonblocking.Semaphore();
+
+    }
+
+
+
+    private LoadSet next_set = new LoadSet();
     private Geary.App.EmailStore email_store;
+    private Geary.TimeoutManager load_timer;
     private Cancellable cancellable;
     private bool loading_local_only = true;
 
@@ -39,42 +52,63 @@ public class PreviewLoader : Geary.BaseObject {
     public PreviewLoader(Geary.App.EmailStore email_store, Cancellable cancellable) {
         this.email_store = email_store;
         this.cancellable = cancellable;
+
+        this.load_timer = new Geary.TimeoutManager.seconds(
+            1, () => { this.do_load.begin(); }
+        );
     }
 
     public void load_remote() {
         this.loading_local_only = false;
+        this.do_load.begin();
     }
 
-    public async string? load(Geary.Email target, Cancellable load_cancellable) {
-        this.progress.notify_start();
-        Gee.Collection<Geary.EmailIdentifier> pending = new Gee.HashSet<Geary.EmailIdentifier>();
-        pending.add(target.id);
-
-        Geary.Folder.ListFlags flags = (this.loading_local_only)
-            ? Geary.Folder.ListFlags.LOCAL_ONLY
-            : Geary.Folder.ListFlags.NONE;
-
-        Gee.Collection<Geary.Email>? emails = null;
+    public async Geary.Email request(Geary.Email target, Cancellable load_cancellable) {
+        LoadSet this_set = this.next_set;
+        this_set.to_load.set(target.id, null);
+        this.load_timer.start();
         try {
-            emails = yield email_store.list_email_by_sparse_id_async(
-                pending, ConversationListStore.WITH_PREVIEW_FIELDS, flags, this.cancellable
-            );
+            yield this_set.loaded.wait_async(load_cancellable);
         } catch (Error err) {
-            // Ignore NOT_FOUND, as that's entirely possible when waiting for the remote to open
-            if (!(err is Geary.EngineError.NOT_FOUND))
-                debug("Unable to fetch preview: %s", err.message);
+            // Oh well
         }
+        return this_set.to_load.get(target.id);
+    }
 
-        Geary.Email? loaded = null;
-        if (emails != null) {
-            loaded = Geary.Collection.get_first(emails);
-        }
-        string? preview = null;
-        if (loaded != null && !load_cancellable.is_cancelled()) {
-            preview = Geary.String.reduce_whitespace(loaded.get_preview_as_string());
+    private async void do_load() {
+        LoadSet this_set = this.next_set;
+        this.next_set = new LoadSet();
+        this.load_timer.reset();
+
+        if (!this_set.to_load.is_empty) {
+            Geary.Folder.ListFlags flags = (this.loading_local_only)
+                ? Geary.Folder.ListFlags.LOCAL_ONLY
+                : Geary.Folder.ListFlags.NONE;
+
+            Gee.Collection<Geary.Email>? emails = null;
+            try {
+                emails = yield email_store.list_email_by_sparse_id_async(
+                    this_set.to_load.keys,
+                    REQUIRED_FIELDS,
+                    flags,
+                    this.cancellable
+                );
+            } catch (Error err) {
+                // Ignore NOT_FOUND, as that's entirely possible when
+                // waiting for the remote to open
+                if (!(err is Geary.EngineError.NOT_FOUND))
+                    debug("Unable to fetch preview: %s", err.message);
+            }
+
+            if (emails != null) {
+                foreach (Geary.Email email in emails) {
+                    this_set.to_load.set(email.id, email);
+                }
+            }
+
+            this_set.loaded.blind_notify();
+            this.progress.notify_finish();
         }
-        this.progress.notify_finish();
-        return preview;
     }
 
 }


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