diff --git a/src/engine/imap-db/imap-db-account.vala b/src/engine/imap-db/imap-db-account.vala index 33581b4a..37c22505 100644 --- a/src/engine/imap-db/imap-db-account.vala +++ b/src/engine/imap-db/imap-db-account.vala @@ -433,158 +433,7 @@ private class Geary.ImapDB.Account : BaseObject { return Db.TransactionOutcome.COMMIT; }, cancellable); } - - /** - * Only updates folder's STATUS message count, attributes, recent, and unseen; UIDVALIDITY and UIDNEXT - * updated when the folder is SELECT/EXAMINED (see update_folder_select_examine_async()) unless - * update_uid_info is true. - */ - public async void update_folder_status_async(Geary.Imap.Folder imap_folder, bool update_uid_info, - bool respect_marked_for_remove, Cancellable? cancellable) throws Error { - check_open(); - - Geary.Imap.FolderProperties properties = imap_folder.properties; - Geary.FolderPath path = imap_folder.path; - - // adjust for marked remove, but don't write these adjustments to the database -- they're - // only reflected in memory via the properties - int adjust_unseen = 0; - int adjust_total = 0; - - yield db.exec_transaction_async(Db.TransactionType.RW, (cx) => { - int64 parent_id; - if (!do_fetch_parent_id(cx, path, true, out parent_id, cancellable)) { - debug("Unable to find parent ID of %s to update properties", path.to_string()); - - return Db.TransactionOutcome.ROLLBACK; - } - - int64 folder_id; - if (!do_fetch_folder_id(cx, path, false, out folder_id, cancellable)) - folder_id = Db.INVALID_ROWID; - - if (respect_marked_for_remove && folder_id != Db.INVALID_ROWID) { - Db.Statement stmt = cx.prepare(""" - SELECT flags - FROM MessageTable - WHERE id IN ( - SELECT message_id - FROM MessageLocationTable - WHERE folder_id = ? AND remove_marker = ? - ) - """); - stmt.bind_rowid(0, folder_id); - stmt.bind_bool(1, true); - - Db.Result results = stmt.exec(cancellable); - while (!results.finished) { - adjust_total++; - - Imap.EmailFlags flags = new Imap.EmailFlags(Imap.MessageFlags.deserialize( - results.string_at(0))); - if (flags.contains(EmailFlags.UNREAD)) - adjust_unseen++; - - results.next(cancellable); - } - } - - Db.Statement stmt; - if (parent_id != Db.INVALID_ROWID) { - stmt = cx.prepare( - "UPDATE FolderTable SET attributes=?, unread_count=? WHERE parent_id=? AND name=?"); - stmt.bind_string(0, properties.attrs.serialize()); - stmt.bind_int(1, properties.email_unread); - stmt.bind_rowid(2, parent_id); - stmt.bind_string(3, path.basename); - } else { - stmt = cx.prepare( - "UPDATE FolderTable SET attributes=?, unread_count=? WHERE parent_id IS NULL AND name=?"); - stmt.bind_string(0, properties.attrs.serialize()); - stmt.bind_int(1, properties.email_unread); - stmt.bind_string(2, path.basename); - } - - stmt.exec(cancellable); - - if (update_uid_info) - do_update_uid_info(cx, properties, parent_id, path, cancellable); - - if (properties.status_messages >= 0) { - do_update_last_seen_status_total(cx, parent_id, path.basename, properties.status_messages, - cancellable); - } - - return Db.TransactionOutcome.COMMIT; - }, cancellable); - - // update appropriate properties in the local folder - ImapDB.Folder? db_folder = get_local_folder(path); - if (db_folder != null) { - Imap.FolderProperties local_properties = db_folder.get_properties(); - - local_properties.set_status_unseen(Numeric.int_floor(properties.unseen - adjust_unseen, 0)); - local_properties.recent = properties.recent; - local_properties.attrs = properties.attrs; - - if (update_uid_info) { - local_properties.uid_validity = properties.uid_validity; - local_properties.uid_next = properties.uid_next; - } - - // only update STATUS MESSAGES count if previously set, but use this count as the - // "authoritative" value until another SELECT/EXAMINE or MESSAGES response - if (properties.status_messages >= 0) { - local_properties.set_status_message_count( - Numeric.int_floor(properties.status_messages - adjust_total, 0), true); - } - } - } - - /** - * Updates folder's SELECT/EXAMINE message count, UIDVALIDITY, UIDNEXT, unseen, and recent. - * See also update_folder_status_async(). - */ - public async void update_folder_select_examine_async(Geary.Imap.Folder imap_folder, Cancellable? cancellable) - throws Error { - check_open(); - - Geary.Imap.FolderProperties properties = imap_folder.properties; - Geary.FolderPath path = imap_folder.path; - - yield db.exec_transaction_async(Db.TransactionType.RW, (cx) => { - int64 parent_id; - if (!do_fetch_parent_id(cx, path, true, out parent_id, cancellable)) { - debug("Unable to find parent ID of %s to update properties", path.to_string()); - - return Db.TransactionOutcome.ROLLBACK; - } - - do_update_uid_info(cx, properties, parent_id, path, cancellable); - - if (properties.select_examine_messages >= 0) { - do_update_last_seen_select_examine_total(cx, parent_id, path.basename, - properties.select_examine_messages, cancellable); - } - - return Db.TransactionOutcome.COMMIT; - }, cancellable); - - // update appropriate properties in the local folder - ImapDB.Folder? db_folder = get_local_folder(path); - if (db_folder != null) { - Imap.FolderProperties local_properties = db_folder.get_properties(); - - local_properties.set_status_unseen(properties.unseen); - local_properties.recent = properties.recent; - local_properties.uid_validity = properties.uid_validity; - local_properties.uid_next = properties.uid_next; - - if (properties.select_examine_messages >= 0) - local_properties.set_select_examine_message_count(properties.select_examine_messages); - } - } - + private void initialize_contacts(Cancellable? cancellable = null) throws Error { check_open(); @@ -1736,7 +1585,7 @@ private class Geary.ImapDB.Account : BaseObject { // If the FolderPath has no parent, returns true and folder_id will be set to Db.INVALID_ROWID. // If cannot create path or there is a logical problem traversing it, returns false with folder_id // set to Db.INVALID_ROWID. - private bool do_fetch_folder_id(Db.Connection cx, Geary.FolderPath path, bool create, out int64 folder_id, + internal bool do_fetch_folder_id(Db.Connection cx, Geary.FolderPath path, bool create, out int64 folder_id, Cancellable? cancellable) throws Error { int length = path.get_path_length(); if (length < 0) @@ -1795,7 +1644,7 @@ private class Geary.ImapDB.Account : BaseObject { } // See do_fetch_folder_id() for return semantics. - private bool do_fetch_parent_id(Db.Connection cx, Geary.FolderPath path, bool create, out int64 parent_id, + internal bool do_fetch_parent_id(Db.Connection cx, Geary.FolderPath path, bool create, out int64 parent_id, Cancellable? cancellable = null) throws Error { if (path.is_root()) { parent_id = Db.INVALID_ROWID; @@ -1931,63 +1780,6 @@ private class Geary.ImapDB.Account : BaseObject { return (parent_path == null ? null : parent_path.get_child(name)); } - // For SELECT/EXAMINE responses, not STATUS responses - private void do_update_last_seen_select_examine_total(Db.Connection cx, int64 parent_id, string name, int total, - Cancellable? cancellable) throws Error { - do_update_total(cx, parent_id, name, "last_seen_total", total, cancellable); - } - - // For STATUS responses, not SELECT/EXAMINE responses - private void do_update_last_seen_status_total(Db.Connection cx, int64 parent_id, string name, - int total, Cancellable? cancellable) throws Error { - do_update_total(cx, parent_id, name, "last_seen_status_total", total, cancellable); - } - - private void do_update_total(Db.Connection cx, int64 parent_id, string name, string colname, - int total, Cancellable? cancellable) throws Error { - Db.Statement stmt; - if (parent_id != Db.INVALID_ROWID) { - stmt = cx.prepare( - "UPDATE FolderTable SET %s=? WHERE parent_id=? AND name=?".printf(colname)); - stmt.bind_int(0, Numeric.int_floor(total, 0)); - stmt.bind_rowid(1, parent_id); - stmt.bind_string(2, name); - } else { - stmt = cx.prepare( - "UPDATE FolderTable SET %s=? WHERE parent_id IS NULL AND name=?".printf(colname)); - stmt.bind_int(0, Numeric.int_floor(total, 0)); - stmt.bind_string(1, name); - } - - stmt.exec(cancellable); - } - - private void do_update_uid_info(Db.Connection cx, Imap.FolderProperties properties, - int64 parent_id, FolderPath path, Cancellable? cancellable) throws Error { - int64 uid_validity = (properties.uid_validity != null) ? properties.uid_validity.value - : Imap.UIDValidity.INVALID; - int64 uid_next = (properties.uid_next != null) ? properties.uid_next.value - : Imap.UID.INVALID; - - Db.Statement stmt; - if (parent_id != Db.INVALID_ROWID) { - stmt = cx.prepare( - "UPDATE FolderTable SET uid_validity=?, uid_next=? WHERE parent_id=? AND name=?"); - stmt.bind_int64(0, uid_validity); - stmt.bind_int64(1, uid_next); - stmt.bind_rowid(2, parent_id); - stmt.bind_string(3, path.basename); - } else { - stmt = cx.prepare( - "UPDATE FolderTable SET uid_validity=?, uid_next=? WHERE parent_id IS NULL AND name=?"); - stmt.bind_int64(0, uid_validity); - stmt.bind_int64(1, uid_next); - stmt.bind_string(2, path.basename); - } - - stmt.exec(cancellable); - } - private int do_get_email_count(Db.Connection cx, Cancellable? cancellable) throws Error { Db.Statement stmt = cx.prepare( diff --git a/src/engine/imap-db/imap-db-folder.vala b/src/engine/imap-db/imap-db-folder.vala index 6a7fe5e5..56651f62 100644 --- a/src/engine/imap-db/imap-db-folder.vala +++ b/src/engine/imap-db/imap-db-folder.vala @@ -89,7 +89,7 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics { private string account_owner_email; private int64 folder_id; private Geary.Imap.FolderProperties properties; - + /** * Fired after one or more emails have been fetched with all Fields, and * saved locally. @@ -101,11 +101,13 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics { * change the unread count for other folders that contain the email. */ public signal void unread_updated(Gee.Map unread_status); - - internal Folder(ImapDB.Database db, Geary.FolderPath path, ContactStore contact_store, - string account_owner_email, int64 folder_id, Geary.Imap.FolderProperties properties) { - assert(folder_id != Db.INVALID_ROWID); - + + internal Folder(ImapDB.Database db, + Geary.FolderPath path, + ContactStore contact_store, + string account_owner_email, + int64 folder_id, + Geary.Imap.FolderProperties properties) { this.db = db; this.path = path; this.contact_store = contact_store; @@ -114,7 +116,7 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics { this.folder_id = folder_id; this.properties = properties; } - + public unowned Geary.FolderPath get_path() { return path; } @@ -137,46 +139,138 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics { return count; } - - // Updates both the FolderProperties and the value in the local store. - public async void update_remote_status_message_count(int count, Cancellable? cancellable) throws Error { - if (count < 0) - return; - - yield db.exec_transaction_async(Db.TransactionType.RW, (cx) => { + + /** + * Updates folder's STATUS message count, attributes, recent, and unseen. + * + * UIDVALIDITY and UIDNEXT updated when the folder is + * SELECT/EXAMINED (see update_folder_select_examine_async()) + * unless update_uid_info is true. + */ + public async void update_folder_status(Geary.Imap.FolderProperties remote_properties, + bool update_uid_info, + bool respect_marked_for_remove, + Cancellable? cancellable) + throws Error { + // adjust for marked remove, but don't write these adjustments to the database -- they're + // only reflected in memory via the properties + int adjust_unseen = 0; + int adjust_total = 0; + + yield this.db.exec_transaction_async(Db.TransactionType.RW, (cx) => { + if (respect_marked_for_remove) { + Db.Statement stmt = cx.prepare(""" + SELECT flags + FROM MessageTable + WHERE id IN ( + SELECT message_id + FROM MessageLocationTable + WHERE folder_id = ? AND remove_marker = ? + ) + """); + stmt.bind_rowid(0, folder_id); + stmt.bind_bool(1, true); + + Db.Result results = stmt.exec(cancellable); + while (!results.finished) { + adjust_total++; + + Imap.EmailFlags flags = new Imap.EmailFlags(Imap.MessageFlags.deserialize( + results.string_at(0))); + if (flags.contains(EmailFlags.UNREAD)) + adjust_unseen++; + + results.next(cancellable); + } + } + Db.Statement stmt = cx.prepare( - "UPDATE FolderTable SET last_seen_status_total=? WHERE id=?"); - stmt.bind_int(0, Numeric.int_floor(count, 0)); - stmt.bind_rowid(1, folder_id); - + "UPDATE FolderTable SET attributes=?, unread_count=? WHERE id=?"); + stmt.bind_string(0, remote_properties.attrs.serialize()); + stmt.bind_int(1, remote_properties.email_unread); + stmt.bind_rowid(2, this.folder_id); stmt.exec(cancellable); - + + if (update_uid_info) + do_update_uid_info(cx, remote_properties, cancellable); + + if (remote_properties.status_messages >= 0) { + do_update_last_seen_status_total( + cx, remote_properties.status_messages, cancellable + ); + } + return Db.TransactionOutcome.COMMIT; }, cancellable); - - properties.set_status_message_count(count, false); + + // update appropriate local properties + this.properties.set_status_unseen( + Numeric.int_floor(remote_properties.unseen - adjust_unseen, 0) + ); + this.properties.recent = remote_properties.recent; + this.properties.attrs = remote_properties.attrs; + + if (update_uid_info) { + this.properties.uid_validity = remote_properties.uid_validity; + this.properties.uid_next = remote_properties.uid_next; + } + + // only update STATUS MESSAGES count if previously set, but use this count as the + // "authoritative" value until another SELECT/EXAMINE or MESSAGES response + if (remote_properties.status_messages >= 0) { + this.properties.set_status_message_count( + Numeric.int_floor(remote_properties.status_messages - adjust_total, 0), + true + ); + } } - + + /** + * Updates folder's SELECT/EXAMINE message count, UIDVALIDITY, UIDNEXT, unseen, and recent. + * See also update_folder_status_async(). + */ + public async void update_folder_select_examine(Geary.Imap.FolderProperties remote_properties, + Cancellable? cancellable) + throws Error { + yield this.db.exec_transaction_async(Db.TransactionType.RW, (cx) => { + do_update_uid_info(cx, remote_properties, cancellable); + + if (remote_properties.select_examine_messages >= 0) { + do_update_last_seen_select_examine_total( + cx, remote_properties.select_examine_messages, cancellable + ); + } + + return Db.TransactionOutcome.COMMIT; + }, cancellable); + + // update appropriate local properties + this.properties.set_status_unseen(remote_properties.unseen); + this.properties.recent = remote_properties.recent; + this.properties.uid_validity = remote_properties.uid_validity; + this.properties.uid_next = remote_properties.uid_next; + + if (remote_properties.select_examine_messages >= 0) { + this.properties.set_select_examine_message_count( + remote_properties.select_examine_messages + ); + } + } + // Updates both the FolderProperties and the value in the local store. Must be called while // open. public async void update_remote_selected_message_count(int count, Cancellable? cancellable) throws Error { if (count < 0) return; - + yield db.exec_transaction_async(Db.TransactionType.RW, (cx) => { - Db.Statement stmt = cx.prepare( - "UPDATE FolderTable SET last_seen_total=? WHERE id=?"); - stmt.bind_int(0, Numeric.int_floor(count, 0)); - stmt.bind_rowid(1, folder_id); - - stmt.exec(cancellable); - + do_update_last_seen_select_examine_total(cx, count, cancellable); return Db.TransactionOutcome.COMMIT; }, cancellable); - + properties.set_select_examine_message_count(count); } - + public async Imap.StatusData fetch_status_data(ListFlags flags, Cancellable? cancellable) throws Error { Imap.StatusData? status_data = null; yield db.exec_transaction_async(Db.TransactionType.RO, (cx) => { @@ -2421,5 +2515,49 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics { return 0; } -} + // For SELECT/EXAMINE responses, not STATUS responses + private void do_update_last_seen_select_examine_total(Db.Connection cx, + int total, + Cancellable? cancellable) + throws Error { + Db.Statement stmt = cx.prepare( + "UPDATE FolderTable SET last_seen_total=? WHERE id=?" + ); + stmt.bind_int(0, Numeric.int_floor(total, 0)); + stmt.bind_rowid(1, this.folder_id); + stmt.exec(cancellable); + } + + // For STATUS responses, not SELECT/EXAMINE responses + private void do_update_last_seen_status_total(Db.Connection cx, + int total, + Cancellable? cancellable) + throws Error { + Db.Statement stmt = cx.prepare( + "UPDATE FolderTable SET last_seen_status_total=? WHERE id=?"); + stmt.bind_int(0, Numeric.int_floor(total, 0)); + stmt.bind_rowid(1, this.folder_id); + stmt.exec(cancellable); + } + + private void do_update_uid_info(Db.Connection cx, + Imap.FolderProperties remote_properties, + Cancellable? cancellable) + throws Error { + int64 uid_validity = (remote_properties.uid_validity != null) + ? remote_properties.uid_validity.value + : Imap.UIDValidity.INVALID; + int64 uid_next = (remote_properties.uid_next != null) + ? remote_properties.uid_next.value + : Imap.UID.INVALID; + + Db.Statement stmt = cx.prepare( + "UPDATE FolderTable SET uid_validity=?, uid_next=? WHERE id=?"); + stmt.bind_int64(0, uid_validity); + stmt.bind_int64(1, uid_next); + stmt.bind_rowid(2, this.folder_id); + stmt.exec(cancellable); + } + +} diff --git a/src/engine/imap-engine/gmail/imap-engine-gmail-account.vala b/src/engine/imap-engine/gmail/imap-engine-gmail-account.vala index f4cafded..bdebdedc 100644 --- a/src/engine/imap-engine/gmail/imap-engine-gmail-account.vala +++ b/src/engine/imap-engine/gmail/imap-engine-gmail-account.vala @@ -49,20 +49,21 @@ private class Geary.ImapEngine.GmailAccount : Geary.ImapEngine.GenericAccount { switch (special_folder_type) { case SpecialFolderType.ALL_MAIL: - return new GmailAllMailFolder(this, this.remote, this.local, local_folder, + return new GmailAllMailFolder(this, this.remote, local_folder, special_folder_type); case SpecialFolderType.DRAFTS: - return new GmailDraftsFolder(this, this.remote, this.local, local_folder, + return new GmailDraftsFolder(this, this.remote, local_folder, special_folder_type); case SpecialFolderType.SPAM: case SpecialFolderType.TRASH: - return new GmailSpamTrashFolder(this, this.remote, this.local, local_folder, + return new GmailSpamTrashFolder(this, this.remote, local_folder, special_folder_type); default: - return new GmailFolder(this, this.remote, this.local, local_folder, special_folder_type); + return new GmailFolder(this, this.remote, local_folder, + special_folder_type); } } diff --git a/src/engine/imap-engine/gmail/imap-engine-gmail-all-mail-folder.vala b/src/engine/imap-engine/gmail/imap-engine-gmail-all-mail-folder.vala index 612c55fd..9f9fb8be 100644 --- a/src/engine/imap-engine/gmail/imap-engine-gmail-all-mail-folder.vala +++ b/src/engine/imap-engine/gmail/imap-engine-gmail-all-mail-folder.vala @@ -9,9 +9,9 @@ */ private class Geary.ImapEngine.GmailAllMailFolder : MinimalFolder, FolderSupport.Remove { - public GmailAllMailFolder(GmailAccount account, Imap.Account remote, ImapDB.Account local, + public GmailAllMailFolder(GmailAccount account, Imap.Account remote, ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { - base (account, remote, local, local_folder, special_folder_type); + base (account, remote, local_folder, special_folder_type); } public async void remove_email_async(Gee.List email_ids, diff --git a/src/engine/imap-engine/gmail/imap-engine-gmail-drafts-folder.vala b/src/engine/imap-engine/gmail/imap-engine-gmail-drafts-folder.vala index 897bf64a..7b56ab91 100644 --- a/src/engine/imap-engine/gmail/imap-engine-gmail-drafts-folder.vala +++ b/src/engine/imap-engine/gmail/imap-engine-gmail-drafts-folder.vala @@ -11,9 +11,9 @@ private class Geary.ImapEngine.GmailDraftsFolder : MinimalFolder, FolderSupport.Create, FolderSupport.Remove { - public GmailDraftsFolder(GmailAccount account, Imap.Account remote, ImapDB.Account local, + public GmailDraftsFolder(GmailAccount account, Imap.Account remote, ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { - base (account, remote, local, local_folder, special_folder_type); + base (account, remote, local_folder, special_folder_type); } public new async Geary.EmailIdentifier? create_email_async( diff --git a/src/engine/imap-engine/gmail/imap-engine-gmail-folder.vala b/src/engine/imap-engine/gmail/imap-engine-gmail-folder.vala index 2579e297..cca2e00b 100644 --- a/src/engine/imap-engine/gmail/imap-engine-gmail-folder.vala +++ b/src/engine/imap-engine/gmail/imap-engine-gmail-folder.vala @@ -6,9 +6,9 @@ private class Geary.ImapEngine.GmailFolder : MinimalFolder, FolderSupport.Archive, FolderSupport.Create, FolderSupport.Remove { - public GmailFolder(GmailAccount account, Imap.Account remote, ImapDB.Account local, + public GmailFolder(GmailAccount account, Imap.Account remote, ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { - base (account, remote, local, local_folder, special_folder_type); + base (account, remote, local_folder, special_folder_type); } public new async Geary.EmailIdentifier? create_email_async( diff --git a/src/engine/imap-engine/gmail/imap-engine-gmail-spam-trash-folder.vala b/src/engine/imap-engine/gmail/imap-engine-gmail-spam-trash-folder.vala index e450c0cf..ec8461fb 100644 --- a/src/engine/imap-engine/gmail/imap-engine-gmail-spam-trash-folder.vala +++ b/src/engine/imap-engine/gmail/imap-engine-gmail-spam-trash-folder.vala @@ -11,18 +11,17 @@ private class Geary.ImapEngine.GmailSpamTrashFolder : MinimalFolder, FolderSupport.Remove, FolderSupport.Empty { - public GmailSpamTrashFolder(GmailAccount account, Imap.Account remote, ImapDB.Account local, + public GmailSpamTrashFolder(GmailAccount account, Imap.Account remote, ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { - base (account, remote, local, local_folder, special_folder_type); + base (account, remote, local_folder, special_folder_type); } - + public async void remove_email_async(Gee.List email_ids, Cancellable? cancellable = null) throws Error { yield expunge_email_async(email_ids, cancellable); } - + public async void empty_folder_async(Cancellable? cancellable = null) throws Error { yield expunge_all_async(cancellable); } } - diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala b/src/engine/imap-engine/imap-engine-generic-account.vala index 38bd71dd..a48ecd97 100644 --- a/src/engine/imap-engine/imap-engine-generic-account.vala +++ b/src/engine/imap-engine/imap-engine-generic-account.vala @@ -974,7 +974,9 @@ internal class Geary.ImapEngine.UpdateRemoteFolders : AccountOperation { // always update, openable or not; have the folder update the UID info the next time // it's opened try { - yield this.local.update_folder_status_async(remote_folder, false, false, cancellable); + yield minimal_folder.local_folder.update_folder_status( + remote_folder.properties, false, false, cancellable + ); } catch (Error update_error) { debug("Unable to update local folder %s with remote properties: %s", remote_folder.to_string(), update_error.message); @@ -1084,35 +1086,36 @@ internal class Geary.ImapEngine.RefreshFolderUnseen : FolderOperation { private weak Imap.Account remote; - private weak ImapDB.Account local; internal RefreshFolderUnseen(MinimalFolder folder, GenericAccount account, - Imap.Account remote, - ImapDB.Account local) { + Imap.Account remote) { base(account, folder); this.remote = remote; - this.local = local; } public override async void execute(Cancellable cancellable) throws Error { if (this.folder.get_open_state() == Geary.Folder.OpenState.CLOSED) { - Imap.Folder remote_folder = yield remote.fetch_folder_cached_async( + Imap.Folder remote_folder = yield this.remote.fetch_folder_cached_async( folder.path, true, cancellable ); + // Although this is called when the folder is closed, we // can safely use local_folder since we are only using its // properties, and the properties were loaded when the // folder was first instantiated. + ImapDB.Folder local_folder = ((MinimalFolder) this.folder).local_folder; + if (remote_folder.properties.have_contents_changed( - ((MinimalFolder) this.folder).local_folder.get_properties(), + local_folder.get_properties(), this.folder.to_string())) { - yield local.update_folder_status_async( - remote_folder, false, true, cancellable + + yield local_folder.update_folder_status( + remote_folder.properties, false, true, cancellable ); ((GenericAccount) this.account).update_folder(this.folder); diff --git a/src/engine/imap-engine/imap-engine-generic-folder.vala b/src/engine/imap-engine/imap-engine-generic-folder.vala index 889d9bf1..cd59b9bf 100644 --- a/src/engine/imap-engine/imap-engine-generic-folder.vala +++ b/src/engine/imap-engine/imap-engine-generic-folder.vala @@ -10,9 +10,9 @@ private class Geary.ImapEngine.GenericFolder : MinimalFolder, Geary.FolderSupport.Create, Geary.FolderSupport.Empty { - public GenericFolder(GenericAccount account, Imap.Account remote, ImapDB.Account local, + public GenericFolder(GenericAccount account, Imap.Account remote, ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { - base (account, remote, local, local_folder, special_folder_type); + base (account, remote, local_folder, special_folder_type); } public async Geary.Revokable? archive_email_async(Gee.List email_ids, diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala b/src/engine/imap-engine/imap-engine-minimal-folder.vala index ca9b4639..4037c769 100644 --- a/src/engine/imap-engine/imap-engine-minimal-folder.vala +++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala @@ -64,7 +64,6 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport private Geary.AggregatedFolderProperties _properties = new Geary.AggregatedFolderProperties( false, false); private Imap.Account remote; - private ImapDB.Account local; private Folder.OpenFlags open_flags = OpenFlags.NONE; private int open_count = 0; private bool remote_opened = false; @@ -105,14 +104,15 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport internal signal void report_problem(Geary.ProblemReport problem); - public MinimalFolder(GenericAccount account, Imap.Account remote, ImapDB.Account local, - ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { + public MinimalFolder(GenericAccount account, + Imap.Account remote, + ImapDB.Folder local_folder, + SpecialFolderType special_folder_type) { this._account = account; this.remote = remote; this.remote_open_timer = new TimeoutManager.seconds( FORCE_OPEN_REMOTE_TIMEOUT_SEC, () => { start_open_remote(); } ); - this.local = local; this.local_folder = local_folder; this.local_folder.email_complete.connect(on_email_complete); @@ -701,8 +701,10 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport // inconsistencies if (yield normalize_folders(opening_folder, cancellable)) { // update flags, properties, etc. - yield local.update_folder_select_examine_async(opening_folder, cancellable); - + yield local_folder.update_folder_select_examine( + opening_folder.properties, cancellable + ); + // signals opening_folder.appended.connect(on_remote_appended); opening_folder.updated.connect(on_remote_updated); @@ -1524,7 +1526,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport // We queue an account operation since the folder itself is // closed and hence does not have a connection to use for it. RefreshFolderUnseen op = new RefreshFolderUnseen( - this, this._account, this.remote, this.local + this, this._account, this.remote ); try { this._account.queue_operation(op); diff --git a/src/engine/imap-engine/other/imap-engine-other-account.vala b/src/engine/imap-engine/other/imap-engine-other-account.vala index fb3467b8..829ce2dd 100644 --- a/src/engine/imap-engine/other/imap-engine-other-account.vala +++ b/src/engine/imap-engine/other/imap-engine-other-account.vala @@ -18,6 +18,6 @@ private class Geary.ImapEngine.OtherAccount : Geary.ImapEngine.GenericAccount { else type = local_folder.get_properties().attrs.get_special_folder_type(); - return new OtherFolder(this, this.remote, this.local, local_folder, type); + return new OtherFolder(this, this.remote, local_folder, type); } } diff --git a/src/engine/imap-engine/other/imap-engine-other-folder.vala b/src/engine/imap-engine/other/imap-engine-other-folder.vala index e966603a..77d84ddf 100644 --- a/src/engine/imap-engine/other/imap-engine-other-folder.vala +++ b/src/engine/imap-engine/other/imap-engine-other-folder.vala @@ -5,9 +5,9 @@ */ private class Geary.ImapEngine.OtherFolder : GenericFolder { - public OtherFolder(OtherAccount account, Imap.Account remote, ImapDB.Account local, + public OtherFolder(OtherAccount account, Imap.Account remote, ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { - base (account, remote, local, local_folder, special_folder_type); + base (account, remote, local_folder, special_folder_type); } } diff --git a/src/engine/imap-engine/outlook/imap-engine-outlook-account.vala b/src/engine/imap-engine/outlook/imap-engine-outlook-account.vala index 86024504..6d68a002 100644 --- a/src/engine/imap-engine/outlook/imap-engine-outlook-account.vala +++ b/src/engine/imap-engine/outlook/imap-engine-outlook-account.vala @@ -46,9 +46,9 @@ private class Geary.ImapEngine.OutlookAccount : Geary.ImapEngine.GenericAccount special_folder_type = local_folder.get_properties().attrs.get_special_folder_type(); if (special_folder_type == Geary.SpecialFolderType.DRAFTS) - return new OutlookDraftsFolder(this, this.remote, this.local, local_folder, special_folder_type); + return new OutlookDraftsFolder(this, this.remote, local_folder, special_folder_type); - return new OutlookFolder(this, this.remote, this.local, local_folder, special_folder_type); + return new OutlookFolder(this, this.remote, local_folder, special_folder_type); } } diff --git a/src/engine/imap-engine/outlook/imap-engine-outlook-drafts-folder.vala b/src/engine/imap-engine/outlook/imap-engine-outlook-drafts-folder.vala index 14a21e37..32186641 100644 --- a/src/engine/imap-engine/outlook/imap-engine-outlook-drafts-folder.vala +++ b/src/engine/imap-engine/outlook/imap-engine-outlook-drafts-folder.vala @@ -12,8 +12,8 @@ * saved at all. */ private class Geary.ImapEngine.OutlookDraftsFolder : MinimalFolder { - public OutlookDraftsFolder(OutlookAccount account, Imap.Account remote, ImapDB.Account local, + public OutlookDraftsFolder(OutlookAccount account, Imap.Account remote, ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { - base (account, remote, local, local_folder, special_folder_type); + base (account, remote, local_folder, special_folder_type); } } diff --git a/src/engine/imap-engine/outlook/imap-engine-outlook-folder.vala b/src/engine/imap-engine/outlook/imap-engine-outlook-folder.vala index 7e5dc2e6..4131fe8c 100644 --- a/src/engine/imap-engine/outlook/imap-engine-outlook-folder.vala +++ b/src/engine/imap-engine/outlook/imap-engine-outlook-folder.vala @@ -5,9 +5,8 @@ */ private class Geary.ImapEngine.OutlookFolder : GenericFolder { - public OutlookFolder(OutlookAccount account, Imap.Account remote, ImapDB.Account local, + public OutlookFolder(OutlookAccount account, Imap.Account remote, ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { - base (account, remote, local, local_folder, special_folder_type); + base (account, remote, local_folder, special_folder_type); } } - diff --git a/src/engine/imap-engine/yahoo/imap-engine-yahoo-account.vala b/src/engine/imap-engine/yahoo/imap-engine-yahoo-account.vala index 4ce20a38..d7fd9592 100644 --- a/src/engine/imap-engine/yahoo/imap-engine-yahoo-account.vala +++ b/src/engine/imap-engine/yahoo/imap-engine-yahoo-account.vala @@ -42,6 +42,6 @@ private class Geary.ImapEngine.YahooAccount : Geary.ImapEngine.GenericAccount { Geary.FolderPath path = local_folder.get_path(); SpecialFolderType special_folder_type = special_map.has_key(path) ? special_map.get(path) : Geary.SpecialFolderType.NONE; - return new YahooFolder(this, this.remote, this.local, local_folder, special_folder_type); + return new YahooFolder(this, this.remote, local_folder, special_folder_type); } } diff --git a/src/engine/imap-engine/yahoo/imap-engine-yahoo-folder.vala b/src/engine/imap-engine/yahoo/imap-engine-yahoo-folder.vala index 0a08ae35..5663faf6 100644 --- a/src/engine/imap-engine/yahoo/imap-engine-yahoo-folder.vala +++ b/src/engine/imap-engine/yahoo/imap-engine-yahoo-folder.vala @@ -5,9 +5,8 @@ */ private class Geary.ImapEngine.YahooFolder : GenericFolder { - public YahooFolder(YahooAccount account, Imap.Account remote, ImapDB.Account local, + public YahooFolder(YahooAccount account, Imap.Account remote, ImapDB.Folder local_folder, SpecialFolderType special_folder_type) { - base (account, remote, local, local_folder, special_folder_type); + base (account, remote, local_folder, special_folder_type); } } -