[geary/wip/713150-conversations] Fix archive bug
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713150-conversations] Fix archive bug
- Date: Fri, 6 Mar 2015 23:59:36 +0000 (UTC)
commit 14dd09595ef9e13c527b819e3dc8bb0f5dc5f5ec
Author: Jim Nelson <jim yorba org>
Date: Fri Mar 6 15:35:29 2015 -0800
Fix archive bug
This also cleans up how paths are added/removed from conversations
as well as how conversations were being (not) dropped internally
src/engine/app/app-conversation-monitor.vala | 67 ++++++++++++++++----------
src/engine/app/app-conversation.vala | 58 ++++++----------------
src/engine/imap-db/imap-db-account.vala | 11 ++--
3 files changed, 64 insertions(+), 72 deletions(-)
---
diff --git a/src/engine/app/app-conversation-monitor.vala b/src/engine/app/app-conversation-monitor.vala
index 463ad5f..8308e9d 100644
--- a/src/engine/app/app-conversation-monitor.vala
+++ b/src/engine/app/app-conversation-monitor.vala
@@ -339,26 +339,14 @@ public class Geary.App.ConversationMonitor : BaseObject {
operation_queue.add(new ReseedOperation(this, "already opened"));
operation_queue.add(new FillWindowOperation(this, false));
- folder.email_appended.connect(on_folder_email_appended);
- folder.email_inserted.connect(on_folder_email_inserted);
- folder.email_removed.connect(on_folder_email_removed);
- folder.opened.connect(on_folder_opened);
- folder.account.email_flags_changed.connect(on_account_email_flags_changed);
- folder.account.email_locally_complete.connect(on_account_email_locally_complete);
- folder.account.email_removed.connect(on_account_email_removed);
+ connect_to_folder();
try {
yield folder.open_async(open_flags, cancellable);
} catch (Error err) {
is_monitoring = false;
- folder.email_appended.disconnect(on_folder_email_appended);
- folder.email_inserted.disconnect(on_folder_email_inserted);
- folder.email_removed.disconnect(on_folder_email_removed);
- folder.opened.disconnect(on_folder_opened);
- folder.account.email_flags_changed.disconnect(on_account_email_flags_changed);
- folder.account.email_locally_complete.disconnect(on_account_email_locally_complete);
- folder.account.email_removed.disconnect(on_account_email_removed);
+ disconnect_from_folder();
throw err;
}
@@ -397,13 +385,7 @@ public class Geary.App.ConversationMonitor : BaseObject {
// set now to prevent reentrancy during yield or signal
is_monitoring = false;
- folder.email_appended.disconnect(on_folder_email_appended);
- folder.email_inserted.disconnect(on_folder_email_inserted);
- folder.email_removed.disconnect(on_folder_email_removed);
- folder.opened.disconnect(on_folder_opened);
- folder.account.email_flags_changed.disconnect(on_account_email_flags_changed);
- folder.account.email_locally_complete.disconnect(on_account_email_locally_complete);
- folder.account.email_removed.disconnect(on_account_email_removed);
+ disconnect_from_folder();
bool closing = false;
Error? close_err = null;
@@ -437,6 +419,32 @@ public class Geary.App.ConversationMonitor : BaseObject {
primary_email_id_to_conversation.clear();
}
+ private void connect_to_folder() {
+ folder.email_appended.connect(on_folder_email_appended);
+ folder.email_inserted.connect(on_folder_email_inserted);
+ folder.email_removed.connect(on_folder_email_removed);
+ folder.opened.connect(on_folder_opened);
+ folder.account.email_flags_changed.connect(on_account_email_flags_changed);
+ folder.account.email_locally_complete.connect(on_account_email_added);
+ folder.account.email_appended.connect(on_account_email_added);
+ folder.account.email_discovered.connect(on_account_email_added);
+ folder.account.email_inserted.connect(on_account_email_added);
+ folder.account.email_removed.connect(on_account_email_removed);
+ }
+
+ private void disconnect_from_folder() {
+ folder.email_appended.disconnect(on_folder_email_appended);
+ folder.email_inserted.disconnect(on_folder_email_inserted);
+ folder.email_removed.disconnect(on_folder_email_removed);
+ folder.opened.disconnect(on_folder_opened);
+ folder.account.email_flags_changed.disconnect(on_account_email_flags_changed);
+ folder.account.email_locally_complete.disconnect(on_account_email_added);
+ folder.account.email_appended.disconnect(on_account_email_added);
+ folder.account.email_discovered.disconnect(on_account_email_added);
+ folder.account.email_inserted.disconnect(on_account_email_added);
+ folder.account.email_removed.disconnect(on_account_email_removed);
+ }
+
// By passing required_fields, this forces the email to be downloaded (if not already) at the
// potential expense of loading it twice; use Email.Field.NONE to only load the email identifiers
// and potentially not be able to load the email due to unavailability (but will be loaded
@@ -650,14 +658,17 @@ public class Geary.App.ConversationMonitor : BaseObject {
operation_queue.add(new FillWindowOperation(this, false));
}
- private void on_account_email_locally_complete(Folder folder, Gee.Collection<EmailIdentifier>
complete_ids) {
+ private void on_account_email_added(Folder folder, Gee.Collection<EmailIdentifier> added_ids) {
if (!folder.path.equal_to(this.folder.path))
- operation_queue.add(new ExternalAppendOperation(this, folder, complete_ids));
+ operation_queue.add(new ExternalAppendOperation(this, folder, added_ids));
}
private void on_account_email_removed(Folder folder, Gee.Collection<EmailIdentifier> removed_ids) {
- if (!folder.path.equal_to(this.folder.path))
- operation_queue.add(new ExternalRemoveOperation(this, folder, removed_ids));
+ if (folder.path.equal_to(this.folder.path))
+ return;
+
+ operation_queue.add(new ExternalRemoveOperation(this, folder, removed_ids));
+ operation_queue.add(new FillWindowOperation(this, false));
}
internal async void append_emails_async(Gee.Collection<Geary.EmailIdentifier> appended_ids) {
@@ -699,7 +710,13 @@ public class Geary.App.ConversationMonitor : BaseObject {
// could have been trimmed earlier in the loop
trimmed_conversations.remove_all(conversation);
+ // strip Conversation from local storage and lookup tables
conversations.remove(conversation);
+ foreach (EmailIdentifier id in conversation.get_email_ids()) {
+ primary_email_id_to_conversation.unset(id);
+ all_email_id_to_conversation.unset(id);
+ }
+
removed_conversations.add(conversation);
} else if (fully_removed && email != null) {
// since the email was fully removed from conversation, report as trimmed
diff --git a/src/engine/app/app-conversation.vala b/src/engine/app/app-conversation.vala
index 5b7bf20..661a6e6 100644
--- a/src/engine/app/app-conversation.vala
+++ b/src/engine/app/app-conversation.vala
@@ -40,8 +40,6 @@ public class Geary.App.Conversation : BaseObject {
private static int next_convnum = 0;
- private Gee.HashMultiSet<RFC822.MessageID> message_ids = new Gee.HashMultiSet<RFC822.MessageID>();
-
private int convnum;
private weak Geary.App.ConversationMonitor? owner;
private Gee.HashMap<EmailIdentifier, Email> emails = new Gee.HashMap<EmailIdentifier, Email>();
@@ -81,8 +79,6 @@ public class Geary.App.Conversation : BaseObject {
this.owner = owner;
owner.email_flags_changed.connect(on_email_flags_changed);
- owner.folder.account.email_discovered.connect(on_email_discovered);
- owner.folder.account.email_removed.connect(on_email_removed);
}
~Conversation() {
@@ -90,11 +86,10 @@ public class Geary.App.Conversation : BaseObject {
}
internal void clear_owner() {
- if (owner != null) {
- owner.email_flags_changed.disconnect(on_email_flags_changed);
- owner.folder.account.email_discovered.disconnect(on_email_discovered);
- owner.folder.account.email_removed.disconnect(on_email_removed);
- }
+ if (owner == null)
+ return;
+
+ owner.email_flags_changed.disconnect(on_email_flags_changed);
owner = null;
}
@@ -107,7 +102,8 @@ public class Geary.App.Conversation : BaseObject {
}
/**
- * Returns the number of { link Email}s in the conversation in the specified { link FolderPath}.
+ * Returns true if any { link Email}s in the { link Conversation} are known to be in the
+ * specified { link FolderPath}.
*/
public bool any_in_folder_path(Geary.FolderPath path) {
foreach (EmailIdentifier email_id in path_map.get_keys()) {
@@ -187,16 +183,6 @@ public class Geary.App.Conversation : BaseObject {
}
/**
- * Return all Message IDs associated with the conversation.
- */
- public Gee.Collection<RFC822.MessageID> get_message_ids() {
- // Turn into a HashSet first, so we don't return duplicates.
- Gee.HashSet<RFC822.MessageID> ids = new Gee.HashSet<RFC822.MessageID>();
- ids.add_all(message_ids);
- return ids;
- }
-
- /**
* Returns the email associated with the EmailIdentifier, if present in this conversation.
*/
public Geary.Email? get_email_by_id(EmailIdentifier id) {
@@ -223,8 +209,13 @@ public class Geary.App.Conversation : BaseObject {
*
* known_paths should contain all the known FolderPaths this email is contained in.
* Conversation will monitor Account for additions and removals as they occur.
+ *
+ * Paths are always added, whether or not the email was already present.
*/
internal bool add(Email email, Gee.Collection<Geary.FolderPath> known_paths) {
+ foreach (Geary.FolderPath path in known_paths)
+ path_map.set(email.id, path);
+
if (emails.has_key(email.id))
return false;
@@ -234,19 +225,16 @@ public class Geary.App.Conversation : BaseObject {
recv_date_ascending.add(email);
recv_date_descending.add(email);
- Gee.Set<RFC822.MessageID>? ancestors = email.get_ancestors();
- if (ancestors != null)
- message_ids.add_all(ancestors);
-
- foreach (Geary.FolderPath path in known_paths)
- path_map.set(email.id, path);
-
appended(email);
return true;
}
- // Returns whether the email was completely removed from the conversation
+ /**
+ * Removes the paths from the email's known paths in the conversation.
+ *
+ * Returns true if the email is fully removed from the conversation.
+ */
internal bool remove(Email email, Geary.FolderPath path) {
path_map.remove(email.id, path);
if (path_map.get(email.id).size != 0)
@@ -365,20 +353,6 @@ public class Geary.App.Conversation : BaseObject {
email_flags_changed(email);
}
- private void on_email_discovered(Geary.Folder folder, Gee.Collection<Geary.EmailIdentifier> ids) {
- // only add to the internal map if a part of this Conversation
- foreach (Geary.EmailIdentifier id in ids) {
- if (emails.has_key(id))
- path_map.set(id, folder.path);
- }
- }
-
- private void on_email_removed(Geary.Folder folder, Gee.Collection<Geary.EmailIdentifier> ids) {
- // To be forgiving, simply remove id without checking if it's a part of this Conversation
- foreach (Geary.EmailIdentifier id in ids)
- path_map.remove(id, folder.path);
- }
-
public string to_string() {
return "[#%d] (%d emails)".printf(convnum, emails.size);
}
diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala
index ce61ad8..6fa7a4c 100644
--- a/src/engine/imap-db/imap-db-account.vala
+++ b/src/engine/imap-db/imap-db-account.vala
@@ -661,7 +661,7 @@ private class Geary.ImapDB.Account : BaseObject {
while (!result.finished) {
Email? email;
Gee.Collection<FolderPath?>? known_paths;
- do_fetch_message(cx, result.int64_at(0), requested_fields, search_predicate,
+ do_fetch_message(cx, result.int64_at(0), requested_fields, false, search_predicate,
out email, out known_paths, cancellable);
if (email != null) {
assert(known_paths != null);
@@ -710,8 +710,8 @@ private class Geary.ImapDB.Account : BaseObject {
Email? email;
Gee.Collection<FolderPath?>? known_paths;
try {
- do_fetch_message(cx, associated_id.message_id, required_fields, search_predicate,
- out email, out known_paths, cancellable);
+ do_fetch_message(cx, associated_id.message_id, required_fields, false,
+ search_predicate, out email, out known_paths, cancellable);
} catch (Error err) {
if (err is EngineError.NOT_FOUND)
continue;
@@ -736,7 +736,7 @@ private class Geary.ImapDB.Account : BaseObject {
}
private void do_fetch_message(Db.Connection cx, int64 message_id, Email.Field required_fields,
- Geary.Account.EmailSearchPredicate? search_predicate, out Email? email,
+ bool include_removed, Geary.Account.EmailSearchPredicate? search_predicate, out Email? email,
out Gee.Collection<FolderPath?>? known_paths, Cancellable? cancellable) throws Error {
Email.Field actual_fields;
MessageRow row = ImapDB.Folder.do_fetch_message_row(cx, message_id, required_fields,
@@ -745,7 +745,8 @@ private class Geary.ImapDB.Account : BaseObject {
email = row.to_email(new Geary.ImapDB.EmailIdentifier(message_id, null));
ImapDB.Folder.do_add_attachments(cx, email, message_id, cancellable);
- Gee.Set<Geary.FolderPath>? folders = do_find_email_folders(cx, message_id, true, cancellable);
+ Gee.Set<Geary.FolderPath>? folders = do_find_email_folders(cx, message_id, include_removed,
+ cancellable);
known_paths = new Gee.HashSet<FolderPath?>();
if (folders == null)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]