Geary.Folder: Add new contains_identifiers method

Add new public method that allows API clients to query whether a folder
contains a specific set of email ids. Add implementation to all
derived classes.
This commit is contained in:
Michael Gratton 2020-08-05 14:07:43 +10:00 committed by Michael James Gratton
parent 77b1683c42
commit 910228093c
7 changed files with 135 additions and 0 deletions

View file

@ -141,6 +141,18 @@ public class Plugin.MailMergeFolder : Geary.AbstractLocalFolder {
);
}
/** {@inheritDoc} */
public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
Gee.Collection<Geary.EmailIdentifier> ids,
GLib.Cancellable? cancellable = null)
throws GLib.Error {
return Geary.traverse(
ids
).filter(
(id) => this.map.has_key(id)
).to_hash_set();
}
public override async Geary.Email
fetch_email_async(Geary.EmailIdentifier id,
Geary.Email.Field required_fields,

View file

@ -626,6 +626,20 @@ public abstract class Geary.Folder : BaseObject, Logging.Source {
public abstract async void synchronise_remote(GLib.Cancellable? cancellable)
throws GLib.Error;
/**
* Determines the email identifiers that are contained in the folder.
*
* The returned collection will be a subset of the given input
* collection that contains an input identifier only if that
* identifier belongs to an email contained by the folder.
*
* The Folder must be opened prior to attempting this operation.
*/
public abstract async Gee.Collection<EmailIdentifier> contains_identifiers(
Gee.Collection<EmailIdentifier> ids,
GLib.Cancellable? cancellable = null)
throws GLib.Error;
/**
* List a number of contiguous emails in the folder's vector.
*

View file

@ -213,6 +213,18 @@ public class Geary.App.SearchFolder :
return results;
}
/** {@inheritDoc} */
public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
Gee.Collection<Geary.EmailIdentifier> ids,
GLib.Cancellable? cancellable = null)
throws GLib.Error {
return Geary.traverse(
ids
).filter(
(id) => this.id_map.has_key(id)
).to_hash_set();
}
public override async Gee.List<Email>? list_email_by_id_async(
EmailIdentifier? initial_id,
int count,

View file

@ -341,6 +341,55 @@ private class Geary.ImapDB.Folder : BaseObject, Geary.ReferenceSemantics {
return results;
}
/** Returns a subset of the given ids that are in this folder. */
public async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
Gee.Collection<Geary.EmailIdentifier> ids,
GLib.Cancellable? cancellable = null)
throws GLib.Error {
var contained_ids = new Gee.HashMap<int64?,EmailIdentifier>(
Collection.int64_hash_func,
Collection.int64_equal_func
);
if (!ids.is_empty) {
var valid_ids = new Gee.HashMap<int64?,EmailIdentifier>(
Collection.int64_hash_func,
Collection.int64_equal_func
);
yield db.exec_transaction_async(
RO,
(cx, cancellable) => {
var sql = new StringBuilder("""
SELECT message_id
FROM MessageLocationTable
WHERE message_id IN (
""");
foreach (var id in ids) {
var id_impl = id as EmailIdentifier;
if (id_impl != null) {
sql.append(id_impl.message_id.to_string());
valid_ids.set(id_impl.message_id, id_impl);
}
}
sql.append(") AND folder_id=? AND remove_marker<>?");
Db.Statement stmt = cx.prepare(sql.str);
stmt.bind_rowid(0, this.folder_id);
stmt.bind_bool(0, false);
Db.Result results = stmt.exec(cancellable);
while (!results.finished) {
var message_id = results.int64_at(0);
contained_ids.set(message_id, valid_ids.get(message_id));
results.next(cancellable);
}
return COMMIT;
},
cancellable
);
}
return contained_ids.values;
}
public async Gee.List<Geary.Email>? list_email_by_id_async(ImapDB.EmailIdentifier? initial_id,
int count, Geary.Email.Field required_fields, ListFlags flags, Cancellable? cancellable)
throws Error {

View file

@ -1201,6 +1201,15 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
this.replay_queue.schedule_server_notification(op);
}
/** {@inheritDoc} */
public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
Gee.Collection<Geary.EmailIdentifier> ids,
GLib.Cancellable? cancellable = null)
throws GLib.Error {
check_open("contains_identifiers");
return yield this.local_folder.contains_identifiers(ids, cancellable);
}
//
// list email variants
//

View file

@ -210,6 +210,34 @@ public class Geary.Outbox.Folder :
}
}
/** {@inheritDoc} */
public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
Gee.Collection<Geary.EmailIdentifier> ids,
GLib.Cancellable? cancellable = null)
throws GLib.Error {
check_open();
var contains = new Gee.HashSet<Geary.EmailIdentifier>();
yield db.exec_transaction_async(
RO,
(cx, cancellable) => {
foreach (Geary.EmailIdentifier id in ids) {
var outbox_id = id as EmailIdentifier;
if (outbox_id != null) {
var row = do_fetch_row_by_ordering(
cx, outbox_id.ordering, cancellable
);
if (row != null) {
contains.add(id);
}
}
}
return DONE;
},
cancellable
);
return contains;
}
public override async Gee.List<Email>?
list_email_by_id_async(Geary.EmailIdentifier? _initial_id,
int count,

View file

@ -85,6 +85,17 @@ public class Mock.Folder : Geary.Folder,
void_call("synchronise_remote", { cancellable });
}
public override async Gee.Collection<Geary.EmailIdentifier> contains_identifiers(
Gee.Collection<Geary.EmailIdentifier> ids,
GLib.Cancellable? cancellable = null)
throws GLib.Error {
return yield object_call_async<Gee.Collection<Geary.EmailIdentifier>>(
"contains_identifiers",
{ids, cancellable},
new Gee.LinkedList<Geary.EmailIdentifier>()
);
}
public override async Gee.List<Geary.Email>?
list_email_by_id_async(Geary.EmailIdentifier? initial_id,
int count,