[geary/wip/219-unbreak-sroll-vector-expansion: 3/3] Fix FillWindowOperation not expanding vector when at end of it
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/219-unbreak-sroll-vector-expansion: 3/3] Fix FillWindowOperation not expanding vector when at end of it
- Date: Wed, 20 Feb 2019 09:25:53 +0000 (UTC)
commit 2b2f99d117ed5fdd109b4bf9aa4b480acdbc8ff6
Author: Michael Gratton <mike vee net>
Date: Wed Feb 20 20:00:20 2019 +1100
Fix FillWindowOperation not expanding vector when at end of it
This ensure that if a call to MinimalFolder.list_email_by_id() includes
a non-null initial_id, that its UID is always looked up. This fixes a
bug where if it is called with an initial ID, going newest to oldest,
and the id is the earliest email in the vector, no expansion will take
place.
This was occurring when scrolling the conversation list to the bottom,
and the ConversationMonitor had already reached the bottom of the
vector, so the fill op was trying to expand it. Since the last message
in the vector was given as the initial_id, but the fill op does not set
INCLUDE_ID, the UID for that email was never found. That caused the
vector expansion to use the end of the vector as the upper UID instead
of the this email at the start of the vector, and hence the lower UID
of the expansion was usually after the start of the vector, since
there's usally more messages in the vector than the fill op was
requesting. Thus no vector expansion actually took place, since the
lower and upper bounds were already included within the vector, and
hence no new messages were loaded by the fill op.
Fixes #219
.../replay-ops/imap-engine-list-email-by-id.vala | 100 ++++++++++-----------
1 file changed, 48 insertions(+), 52 deletions(-)
---
diff --git a/src/engine/imap-engine/replay-ops/imap-engine-list-email-by-id.vala
b/src/engine/imap-engine/replay-ops/imap-engine-list-email-by-id.vala
index 22987fb7..b14625af 100644
--- a/src/engine/imap-engine/replay-ops/imap-engine-list-email-by-id.vala
+++ b/src/engine/imap-engine/replay-ops/imap-engine-list-email-by-id.vala
@@ -17,54 +17,55 @@ private class Geary.ImapEngine.ListEmailByID : Geary.ImapEngine.AbstractListEmai
this.initial_id = initial_id;
this.count = count;
}
-
+
public override async ReplayOperation.Status replay_local_async() throws Error {
if (flags.is_force_update())
return ReplayOperation.Status.CONTINUE;
-
- // get everything from local store, even partial matches, that fit range
- ImapDB.Folder.ListFlags list_flags = ImapDB.Folder.ListFlags.from_folder_flags(flags);
- list_flags |= ImapDB.Folder.ListFlags.PARTIAL_OK;
- Gee.List<Geary.Email>? list = yield owner.local_folder.list_email_by_id_async(initial_id,
- count, required_fields, list_flags, cancellable);
-
- // walk list, breaking out unfulfilled items from fulfilled items
+
+ // Fetch the initial ID to a) make sure it exists, and b) so
+ // its UID is available when expanding the vector
+ if (this.initial_id != null) {
+ Email email = yield owner.local_folder.fetch_email_async(
+ this.initial_id,
+ // Only need the id here
+ Email.Field.NONE,
+ ImapDB.Folder.ListFlags.NONE,
+ cancellable
+ );
+ this.initial_uid = ((ImapDB.EmailIdentifier) email.id).uid;
+ }
+
+ // List all locally known, desired email that fits the list
+ // range. Include partial matches so there's potentially less
+ // to fetch from the remote if not all are fulfilled.
+ ImapDB.Folder.ListFlags local_flags = (
+ ImapDB.Folder.ListFlags.from_folder_flags(flags) |
+ ImapDB.Folder.ListFlags.PARTIAL_OK
+ );
+ Gee.List<Geary.Email>? list =
+ yield owner.local_folder.list_email_by_id_async(
+ initial_id,
+ count,
+ required_fields,
+ local_flags,
+ cancellable
+ );
+
+ // Break out unfulfilled email from fulfilled ones
Gee.ArrayList<Geary.Email> fulfilled = new Gee.ArrayList<Geary.Email>();
if (list != null) {
foreach (Geary.Email email in list) {
- Imap.UID uid = ((ImapDB.EmailIdentifier) email.id).uid;
-
- // if INCLUDING_ID, then find the initial UID for the initial_id (if specified)
- if (flags.is_including_id()) {
- if (initial_id != null && email.id.equal_to(initial_id))
- initial_uid = uid;
+ if (email.fields.fulfills(required_fields)) {
+ fulfilled.add(email);
} else {
- // !INCLUDING_ID, so find the earliest UID (for oldest-to-newest) or latest
- // UID (newest-to-oldest)
- if (flags.is_oldest_to_newest()) {
- if (initial_uid == null || uid.compare_to(initial_uid) < 0)
- initial_uid = uid;
- } else {
- // newest-to-oldest
- if (initial_uid == null || uid.compare_to(initial_uid) > 0)
- initial_uid = uid;
- }
+ Imap.UID uid = ((ImapDB.EmailIdentifier) email.id).uid;
+ add_unfulfilled_fields(
+ uid, required_fields.clear(email.fields)
+ );
}
-
- if (email.fields.fulfills(required_fields))
- fulfilled.add(email);
- else
- add_unfulfilled_fields(uid, required_fields.clear(email.fields));
}
}
- if (this.flags.is_including_id() && this.initial_uid == null) {
- throw new EngineError.NOT_FOUND(
- "Initial id not found in local set: %s",
- this.initial_id.to_string()
- );
- }
-
// report fulfilled items
fulfilled_count = fulfilled.size;
if (fulfilled_count > 0)
@@ -103,26 +104,21 @@ private class Geary.ImapEngine.ListEmailByID : Geary.ImapEngine.AbstractListEmai
bool expansion_required = false;
if (!(yield is_fully_expanded_async(remote))) {
if (flags.is_oldest_to_newest()) {
- if (initial_id != null) {
- // expand vector if not initial_id not discovered
- expansion_required = (initial_uid == null);
- } else {
- // initial_id == null, expansion required if not fully already
- expansion_required = true;
- }
+ // Expansion is required since there are
+ // unfulfilled email within the vector.
+ expansion_required = true;
} else {
// newest-to-oldest
if (count == int.MAX) {
- // if infinite count, expansion required if not already
+ // Infinite count, expand to fill in all
+ // unfulfilled or not-yet-found email.
expansion_required = true;
- } else if (initial_id != null) {
- // finite count, expansion required if initial not found *or* not enough
- // items were pulled in
- expansion_required = (initial_uid == null) || (fulfilled_count + get_unfulfilled_count()
< count);
} else {
- // initial_id == null
- // finite count, expansion required if not enough found
- expansion_required = (fulfilled_count + get_unfulfilled_count() < count);
+ // Finite count, expansion required only if not
+ // enough items were pulled in, in total.
+ expansion_required = (
+ fulfilled_count + get_unfulfilled_count() < count
+ );
}
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]