[geary/wip/unread-status-714865] WIP



commit f63757cac4c8b930e61dc5731918be20dfb0ce9a
Author: Charles Lindsay <chaz yorba org>
Date:   Wed Feb 19 18:18:42 2014 -0800

    WIP

 .../imap-engine/imap-engine-generic-account.vala   |   66 ++++++++++++++++++++
 src/engine/imap/api/imap-account.vala              |   28 ++++++++
 2 files changed, 94 insertions(+), 0 deletions(-)
---
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index cd3b24c..0b764c1 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -6,6 +6,7 @@
 
 private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
     private const int REFRESH_FOLDER_LIST_SEC = 4 * 60;
+    private const int REFRESH_UNSEEN_SEC = 1;
     
     private static Geary.FolderPath? outbox_path = null;
     private static Geary.FolderPath? search_path = null;
@@ -16,6 +17,7 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
     private Gee.HashMap<FolderPath, MinimalFolder> folder_map = new Gee.HashMap<
         FolderPath, MinimalFolder>();
     private Gee.HashMap<FolderPath, Folder> local_only = new Gee.HashMap<FolderPath, Folder>();
+    private uint refresh_unseen_timeout_id = 0;
     private uint refresh_folder_timeout_id = 0;
     private bool in_refresh_enumerate = false;
     private Cancellable refresh_cancellable = new Cancellable();
@@ -68,6 +70,27 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
         }
     }
     
+    protected override void notify_email_appended(Geary.Folder folder, Gee.Collection<Geary.EmailIdentifier> 
ids) {
+        base.notify_email_appended(folder, ids);
+        reschedule_unseen_update();
+    }
+    
+    protected override void notify_email_inserted(Geary.Folder folder, Gee.Collection<Geary.EmailIdentifier> 
ids) {
+        base.notify_email_inserted(folder, ids);
+        reschedule_unseen_update();
+    }
+    
+    protected override void notify_email_removed(Geary.Folder folder, Gee.Collection<Geary.EmailIdentifier> 
ids) {
+        base.notify_email_removed(folder, ids);
+        reschedule_unseen_update();
+    }
+    
+    protected override void notify_email_flags_changed(Geary.Folder folder,
+        Gee.Map<Geary.EmailIdentifier, Geary.EmailFlags> flag_map) {
+        base.notify_email_flags_changed(folder, flag_map);
+        reschedule_unseen_update();
+    }
+    
     private void check_open() throws EngineError {
         if (!open)
             throw new EngineError.OPEN_REQUIRED("Account %s not opened", to_string());
@@ -261,6 +284,49 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.AbstractAccount {
         return all_folders;
     }
     
+    private void reschedule_unseen_update() {
+        if (refresh_unseen_timeout_id != 0) {
+            Source.remove(refresh_unseen_timeout_id);
+            refresh_unseen_timeout_id = 0;
+        }
+        
+        refresh_unseen_timeout_id = Timeout.add_seconds(REFRESH_UNSEEN_SEC, on_refresh_unseen);
+    }
+    
+    private bool on_refresh_unseen() {
+        // TODO: prevent recursion?
+        
+        // TODO: cancellable?
+        refresh_unseen_async.begin(null, on_refresh_unseen_completed);
+        
+        refresh_unseen_timeout_id = 0;
+        return false;
+    }
+    
+    private void on_refresh_unseen_completed(Object? source, AsyncResult result) {
+        try {
+            refresh_unseen_async.end(result);
+        } catch (Error e) {
+            debug("Error refreshing unseen counts: %s", e.message);
+        }
+    }
+    
+    private async void refresh_unseen_async(Cancellable? cancellable) throws Error {
+        debug("Refreshing unseen counts");
+        
+        Gee.Map<FolderPath, int> unseen_counts = yield remote.fetch_all_unseen_async(cancellable);
+        foreach (FolderPath path in unseen_counts.keys) {
+            if (!folder_map.has_key(path)) {
+                debug("Unknown folder path %s returned from unseen counts", path.to_string());
+                continue;
+            }
+            
+            MinimalFolder folder = folder_map.get(path);
+            folder.remote_folder.properties.set_status_unseen(unseen_counts.get(path));
+            yield local.update_folder_status_async(folder.remote_folder, false, cancellable);
+        }
+    }
+    
     private void reschedule_folder_refresh(bool immediate) {
         if (in_refresh_enumerate)
             return;
diff --git a/src/engine/imap/api/imap-account.vala b/src/engine/imap/api/imap-account.vala
index 090e582..8bb306e 100644
--- a/src/engine/imap/api/imap-account.vala
+++ b/src/engine/imap/api/imap-account.vala
@@ -224,6 +224,34 @@ private class Geary.Imap.Account : BaseObject {
         }
     }
     
+    public async Gee.Map<FolderPath, int> fetch_all_unseen_async(Cancellable? cancellable) throws Error {
+        Gee.HashMap<MailboxSpecifier, FolderPath> paths = new Gee.HashMap<MailboxSpecifier, FolderPath>();
+        foreach (FolderPath p in folders.keys) {
+            try {
+                paths.set(new MailboxSpecifier.from_folder_path(p, null), p);
+            } catch (Error e) {
+                debug("Error converting folder path %s to mailbox specifier: %s", p.to_string(), e.message);
+            }
+        }
+        
+        Gee.ArrayList<StatusCommand> commands = Geary.traverse<MailboxSpecifier>(paths.keys)
+            .map<StatusCommand>(m => new StatusCommand(m, { StatusDataType.UNSEEN }))
+            .to_array_list();
+        Gee.ArrayList<StatusData> status_results = new Gee.ArrayList<StatusData>();
+        Gee.Map<Command, StatusResponse> responses = yield send_multiple_async(commands,
+            null, status_results, cancellable);
+        
+        // TODO: check responses?
+        (void) responses;
+        
+        Gee.HashMap<FolderPath, int> unseen_counts = new Gee.HashMap<FolderPath, int>();
+        foreach (StatusData data in status_results) {
+            assert(paths.has_key(data.mailbox));
+            unseen_counts.set(paths.get(data.mailbox), data.unseen);
+        }
+        return unseen_counts;
+    }
+    
     public async Gee.List<Imap.Folder>? list_child_folders_async(FolderPath? parent, Cancellable? 
cancellable)
         throws Error {
         check_open();


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