[geary/wip/713150-conversations] Implement conversation merge



commit 3987324e1fd665d68e749a3607bf1ed022408384
Author: Jim Nelson <jim yorba org>
Date:   Fri Feb 27 14:14:14 2015 -0800

    Implement conversation merge

 src/CMakeLists.txt                                 |    1 -
 src/engine/app/app-conversation-monitor.vala       |   41 ++-
 src/engine/app/app-conversation.vala               |    7 +
 .../conversation-monitor/app-conversation-set.vala |  422 --------------------
 .../app-external-remove-operation.vala             |    2 +-
 .../conversation-monitor/app-remove-operation.vala |    2 +-
 6 files changed, 45 insertions(+), 430 deletions(-)
---
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index aabd3b4..6212a2a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -53,7 +53,6 @@ engine/app/app-email-store.vala
 engine/app/conversation-monitor/app-append-operation.vala
 engine/app/conversation-monitor/app-conversation-operation-queue.vala
 engine/app/conversation-monitor/app-conversation-operation.vala
-engine/app/conversation-monitor/app-conversation-set.vala
 engine/app/conversation-monitor/app-external-append-operation.vala
 engine/app/conversation-monitor/app-external-remove-operation.vala
 engine/app/conversation-monitor/app-fill-window-operation.vala
diff --git a/src/engine/app/app-conversation-monitor.vala b/src/engine/app/app-conversation-monitor.vala
index 2092389..a0c8885 100644
--- a/src/engine/app/app-conversation-monitor.vala
+++ b/src/engine/app/app-conversation-monitor.vala
@@ -538,7 +538,6 @@ public class Geary.App.ConversationMonitor : BaseObject {
             break;
             
             default:
-                // TODO
                 conversation = merge_conversations(existing);
             break;
         }
@@ -576,10 +575,42 @@ public class Geary.App.ConversationMonitor : BaseObject {
         }
     }
     
-    // TODO
+    // This happens when emails with partial histories (REFERENCES) arrive out-of-order and their
+    // relationship is not known until after conversations have been created ... although rare, it
+    // does happen and needs to be dealt with
     private Conversation merge_conversations(Gee.Set<Conversation> conversations) {
-        breakpoint();
-        return new Conversation(this);
+        assert(conversations.size > 1);
+        
+        // Find the largest conversation and merge the others into it
+        Conversation largest = traverse<Conversation>(conversations)
+            .to_tree_set((ca, cb) => ca.get_count() - cb.get_count())
+            .last();
+        
+        Gee.HashSet<EmailIdentifier> in_folder_ids = new Gee.HashSet<EmailIdentifier>();
+        foreach (Conversation conversation in conversations) {
+            // skip destination conversation
+            if (conversation == largest)
+                continue;
+            
+            foreach (EmailIdentifier id in conversation.get_email_ids()) {
+                Email? email = conversation.get_email_by_id(id);
+                if (email == null)
+                    continue;
+                
+                Gee.Collection<FolderPath>? paths = conversation.get_known_paths_for_id(id);
+                if (paths == null)
+                    paths = new Gee.ArrayList<FolderPath>();
+                
+                largest.add(email, paths);
+                
+                if (primary_email_id_to_conversation.has_key(id))
+                    in_folder_ids.add(id);
+            }
+        }
+        
+        remove_emails(folder.path, in_folder_ids);
+        
+        return largest;
     }
     
     private void on_folder_email_appended(Gee.Collection<Geary.EmailIdentifier> appended_ids) {
@@ -612,7 +643,7 @@ public class Geary.App.ConversationMonitor : BaseObject {
         yield load_by_sparse_id(appended_ids, required_fields, Geary.Folder.ListFlags.NONE, null);
     }
     
-    internal async void remove_emails_async(FolderPath path, Gee.Collection<EmailIdentifier> removed_ids) {
+    internal void remove_emails(FolderPath path, Gee.Collection<EmailIdentifier> removed_ids) {
         debug("%d messages(s) removed from %s, trimming/removing conversations in %s...", removed_ids.size,
             path.to_string(), folder.to_string());
         
diff --git a/src/engine/app/app-conversation.vala b/src/engine/app/app-conversation.vala
index 7dc16a9..5b7bf20 100644
--- a/src/engine/app/app-conversation.vala
+++ b/src/engine/app/app-conversation.vala
@@ -204,6 +204,13 @@ public class Geary.App.Conversation : BaseObject {
     }
     
     /**
+     * Returns the known { link FolderPath}s for the { link EmailIdentifier}.
+     */
+    public Gee.Collection<Geary.FolderPath>? get_known_paths_for_id(Geary.EmailIdentifier id) {
+        return path_map.get(id);
+    }
+    
+    /**
      * Returns all EmailIdentifiers in the conversation, unsorted.
      */
     public Gee.Collection<Geary.EmailIdentifier> get_email_ids() {
diff --git a/src/engine/app/conversation-monitor/app-external-remove-operation.vala 
b/src/engine/app/conversation-monitor/app-external-remove-operation.vala
index 9002715..6b31545 100644
--- a/src/engine/app/conversation-monitor/app-external-remove-operation.vala
+++ b/src/engine/app/conversation-monitor/app-external-remove-operation.vala
@@ -17,6 +17,6 @@ private class Geary.App.ExternalRemoveOperation : ConversationOperation {
     }
     
     public override async void execute_async() {
-        yield monitor.remove_emails_async(path, removed_ids);
+        monitor.remove_emails(path, removed_ids);
     }
 }
diff --git a/src/engine/app/conversation-monitor/app-remove-operation.vala 
b/src/engine/app/conversation-monitor/app-remove-operation.vala
index 217c620..11e7fe8 100644
--- a/src/engine/app/conversation-monitor/app-remove-operation.vala
+++ b/src/engine/app/conversation-monitor/app-remove-operation.vala
@@ -13,6 +13,6 @@ private class Geary.App.RemoveOperation : ConversationOperation {
     }
     
     public override async void execute_async() {
-        yield monitor.remove_emails_async(monitor.folder.path, removed_ids);
+        monitor.remove_emails(monitor.folder.path, removed_ids);
     }
 }


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