engine: Mark all email UIDs in remote replay

Local replay and remote replay were marking email based on email identifier.

Works locally, but remotely we need to work on all email UIDs.

Fix #364
This commit is contained in:
Cédric Bellegarde 2022-09-09 13:34:12 +02:00
parent ee4af55239
commit 8348f2ef19
2 changed files with 34 additions and 3 deletions

View file

@ -1122,6 +1122,18 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
unread_updated(unread_status);
}
internal async Gee.List<Imap.UID>? get_email_uids_async(
Gee.Collection<EmailIdentifier> ids, Cancellable? cancellable) throws Error {
Gee.List<Imap.UID> uids = null;
yield db.exec_transaction_async(Db.TransactionType.RO, (cx, cancellable) => {
uids = do_get_email_uids(cx, ids, cancellable);
return Db.TransactionOutcome.SUCCESS;
}, cancellable);
return uids;
}
internal async Gee.Map<ImapDB.EmailIdentifier, Geary.EmailFlags>? get_email_flags_async(
Gee.Collection<EmailIdentifier> ids, Cancellable? cancellable) throws Error {
Gee.Map<EmailIdentifier, Geary.EmailFlags>? map = null;
@ -1882,6 +1894,21 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
return builder.str;
}
private Gee.List<Imap.UID>? do_get_email_uids(Db.Connection cx,
Gee.Collection<ImapDB.EmailIdentifier> ids, Cancellable? cancellable) throws Error {
Gee.List<LocationIdentifier>? locs = do_get_locations_for_ids(cx, ids, ListFlags.NONE,
cancellable);
if (locs == null)
return null;
Gee.List<Imap.UID> uids = new Gee.ArrayList<Imap.UID>();
foreach (LocationIdentifier location in locs) {
uids.insert(0, location.uid);
}
return (uids.size > 0) ? uids : null;
}
private Gee.Map<ImapDB.EmailIdentifier, Geary.EmailFlags>? do_get_email_flags(Db.Connection cx,
Gee.Collection<ImapDB.EmailIdentifier> ids, Cancellable? cancellable) throws Error {
Gee.List<LocationIdentifier>? locs = do_get_locations_for_ids(cx, ids, ListFlags.NONE,

View file

@ -7,6 +7,7 @@
private class Geary.ImapEngine.MarkEmail : Geary.ImapEngine.SendReplayOperation {
private MinimalFolder engine;
private Gee.List<ImapDB.EmailIdentifier> to_mark = new Gee.ArrayList<ImapDB.EmailIdentifier>();
private Gee.List<Imap.UID> to_mark_uids = new Gee.ArrayList<Imap.UID>();
private Geary.EmailFlags? flags_to_add;
private Geary.EmailFlags? flags_to_remove;
private Gee.Map<ImapDB.EmailIdentifier, Geary.EmailFlags>? original_flags = null;
@ -48,6 +49,10 @@ private class Geary.ImapEngine.MarkEmail : Geary.ImapEngine.SendReplayOperation
yield engine.local_folder.mark_email_async(original_flags.keys, flags_to_add, flags_to_remove,
cancellable);
// We can't rely on email identifier for remote replay
// An email identifier id can match multiple uids
to_mark_uids = yield engine.local_folder.get_email_uids_async(to_mark, cancellable);
// Notify using flags from DB.
Gee.Map<EmailIdentifier, Geary.EmailFlags>? map = yield engine.local_folder.get_email_flags_async(
original_flags.keys, cancellable);
@ -60,9 +65,8 @@ private class Geary.ImapEngine.MarkEmail : Geary.ImapEngine.SendReplayOperation
public override async void replay_remote_async(Imap.FolderSession remote)
throws GLib.Error {
// potentially empty due to writebehind operation
if (original_flags.size > 0) {
Gee.List<Imap.MessageSet> msg_sets = Imap.MessageSet.uid_sparse(
ImapDB.EmailIdentifier.to_uids(original_flags.keys));
if (to_mark_uids.size > 0) {
Gee.List<Imap.MessageSet> msg_sets = Imap.MessageSet.uid_sparse(to_mark_uids);
yield remote.mark_email_async(
msg_sets, flags_to_add, flags_to_remove, cancellable
);