[geary/wip/713150-conversations: 20/20] Fix scrollbar detection & client-API loop for loading more when necessary
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713150-conversations: 20/20] Fix scrollbar detection & client-API loop for loading more when necessary
- Date: Wed, 18 Mar 2015 01:15:44 +0000 (UTC)
commit 9619493b6a8bbaf174a52f14299bbec8a94d01bf
Author: Jim Nelson <jim yorba org>
Date: Tue Mar 17 18:12:01 2015 -0700
Fix scrollbar detection & client-API loop for loading more when necessary
src/client/application/geary-controller.vala | 32 +++++++++++---
src/client/components/main-window.vala | 20 ++++++++-
.../conversation-list/conversation-list-store.vala | 2 +-
src/engine/app/app-conversation-monitor.vala | 45 +++++++++++++++----
4 files changed, 80 insertions(+), 19 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 85a37bc..aa3923e 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -58,7 +58,7 @@ public class GearyController : Geary.BaseObject {
public const string PROP_CURRENT_CONVERSATION ="current-conversations";
public const int MIN_CONVERSATION_COUNT = 50;
- public const int LOAD_MORE_CONVERSATION_COUNT = 20;
+ public const int LOAD_MORE_CONVERSATION_COUNT = 10;
private const string DELETE_MESSAGE_TOOLTIP_SINGLE = _("Delete conversation (Shift+Delete)");
private const string DELETE_MESSAGE_TOOLTIP_MULTIPLE = _("Delete conversations (Shift+Delete)");
@@ -206,6 +206,7 @@ public class GearyController : Geary.BaseObject {
main_window.conversation_list_view.load_more.connect(on_load_more);
main_window.conversation_list_view.mark_conversations.connect(on_mark_conversations);
main_window.conversation_list_view.visible_conversations_changed.connect(on_visible_conversations_changed);
+ main_window.conversation_list_height_changed.connect(on_check_conversation_list_scrollbars);
main_window.folder_list.folder_selected.connect(on_folder_selected);
main_window.folder_list.copy_conversation.connect(on_copy_conversation);
main_window.folder_list.move_conversation.connect(on_move_conversation);
@@ -282,6 +283,7 @@ public class GearyController : Geary.BaseObject {
main_window.conversation_list_view.load_more.disconnect(on_load_more);
main_window.conversation_list_view.mark_conversations.disconnect(on_mark_conversations);
main_window.conversation_list_view.visible_conversations_changed.disconnect(on_visible_conversations_changed);
+ main_window.conversation_list_height_changed.disconnect(on_check_conversation_list_scrollbars);
main_window.folder_list.folder_selected.disconnect(on_folder_selected);
main_window.folder_list.copy_conversation.disconnect(on_copy_conversation);
main_window.folder_list.move_conversation.disconnect(on_move_conversation);
@@ -1453,8 +1455,12 @@ public class GearyController : Geary.BaseObject {
}
current_conversations.scan_error.connect(on_scan_error);
- current_conversations.scan_completed.connect(on_scan_completed);
- current_conversations.scan_completed.connect(on_conversation_count_changed);
+ current_conversations.scan_completed.connect((conversations_added) => {
+ if (conversations_added) {
+ on_check_conversation_list_scrollbars();
+ on_conversation_count_changed();
+ }
+ });
current_conversations.conversations_added.connect(on_conversation_count_changed);
current_conversations.conversation_removed.connect(on_conversation_count_changed);
current_conversations.conversation_removed.connect(on_conversation_removed);
@@ -1471,7 +1477,7 @@ public class GearyController : Geary.BaseObject {
debug("Scan error: %s", err.message);
}
- private void on_scan_completed() {
+ private void on_check_conversation_list_scrollbars() {
if (scrollbar_check_id != 0)
Source.remove(scrollbar_check_id);
@@ -1483,6 +1489,9 @@ public class GearyController : Geary.BaseObject {
// all code paths lead to this SourceFunc being removed when completed
scrollbar_check_id = 0;
+ if (current_conversations == null)
+ return false;
+
// Done scanning. Check if we have enough messages to fill the conversation list; if not,
// trigger a load_more();
if (main_window.conversation_list_has_scrollbar())
@@ -1492,6 +1501,8 @@ public class GearyController : Geary.BaseObject {
current_conversations.get_conversation_count(), current_conversations.min_window_count,
current_folder.to_string());
+ // expand the ConversationMonitor window to include more messages until a scrollbar becomes
+ // present
on_load_more();
return false;
@@ -1535,8 +1546,17 @@ public class GearyController : Geary.BaseObject {
}
private void on_load_more() {
- debug("on_load_more");
- current_conversations.min_window_count += LOAD_MORE_CONVERSATION_COUNT;
+ if (current_conversations == null || current_conversations.all_mail_loaded)
+ return;
+
+ int orig = current_conversations.min_window_count;
+
+ // It's possible for the conversation count to be any value above or below the min_window_count,
+ // so ensure *some* increase happens to trigger loading more conversations
+ current_conversations.min_window_count =
+ current_conversations.get_conversation_count() + LOAD_MORE_CONVERSATION_COUNT;
+ if (current_conversations.min_window_count <= orig)
+ current_conversations.min_window_count = orig + LOAD_MORE_CONVERSATION_COUNT;
}
private void on_select_folder_completed(Object? source, AsyncResult result) {
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index 2f83f26..f2f5a1b 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -35,6 +35,10 @@ public class MainWindow : Gtk.ApplicationWindow {
private Geary.ProgressMonitor? conversation_monitor_progress = null;
private Geary.ProgressMonitor? folder_progress = null;
private Geary.Folder? current_folder = null;
+ private int conversation_list_height = -1;
+ private int conversation_list_width = -1;
+
+ public signal void conversation_list_height_changed();
public MainWindow(GearyApplication application) {
Object(application: application);
@@ -97,6 +101,17 @@ public class MainWindow : Gtk.ApplicationWindow {
set_styling();
create_layout();
on_change_orientation();
+
+ // can only set this up after create_layout
+ conversation_list_scrolled.size_allocate.connect((alloc) => {
+ if (conversation_list_width == alloc.width && conversation_list_height == alloc.height)
+ return;
+
+ conversation_list_width = alloc.width;
+ conversation_list_height = alloc.height;
+
+ conversation_list_height_changed();
+ });
}
public override void show_all() {
@@ -271,8 +286,9 @@ public class MainWindow : Gtk.ApplicationWindow {
// Returns true when there's a conversation list scrollbar visible, i.e. the list is tall
// enough to need one. Otherwise returns false.
public bool conversation_list_has_scrollbar() {
- Gtk.Scrollbar? scrollbar = conversation_list_scrolled.get_vscrollbar() as Gtk.Scrollbar;
- return scrollbar != null && scrollbar.get_visible();
+ Gtk.Adjustment vadj = conversation_list_scrolled.vadjustment;
+
+ return (vadj.upper - vadj.lower) > vadj.page_size;
}
private bool on_key_press_event(Gdk.EventKey event) {
diff --git a/src/client/conversation-list/conversation-list-store.vala
b/src/client/conversation-list/conversation-list-store.vala
index eca2ced..92cd6ae 100644
--- a/src/client/conversation-list/conversation-list-store.vala
+++ b/src/client/conversation-list/conversation-list-store.vala
@@ -411,7 +411,7 @@ public class ConversationListStore : Gtk.ListStore {
return true;
}
- private void on_scan_completed(Geary.App.ConversationMonitor sender) {
+ private void on_scan_completed(Geary.App.ConversationMonitor sender, bool conversations_added) {
refresh_previews_async.begin(sender);
loading_local_only = false;
}
diff --git a/src/engine/app/app-conversation-monitor.vala b/src/engine/app/app-conversation-monitor.vala
index c708e65..ebc779c 100644
--- a/src/engine/app/app-conversation-monitor.vala
+++ b/src/engine/app/app-conversation-monitor.vala
@@ -76,7 +76,9 @@ public class Geary.App.ConversationMonitor : BaseObject {
}
public Geary.Folder folder { get; private set; }
+
public bool is_monitoring { get; private set; default = false; }
+
public int min_window_count { get { return _min_window_count; }
set {
if (_min_window_count == value)
@@ -87,6 +89,11 @@ public class Geary.App.ConversationMonitor : BaseObject {
}
}
+ /**
+ * Indicates that all mail in the primary { link folder} has been loaded.
+ */
+ public bool all_mail_loaded { get; private set; default = false; }
+
public Geary.ProgressMonitor progress_monitor { get { return operation_queue.progress_monitor; } }
private Geary.Email.Field required_fields;
@@ -150,9 +157,9 @@ public class Geary.App.ConversationMonitor : BaseObject {
/**
* "scan-completed" is fired when the scan of the email has finished.
*/
- public virtual signal void scan_completed() {
- Logging.debug(Logging.Flag.CONVERSATIONS, "[%s] ConversationMonitor::scan_completed",
- folder.to_string());
+ public virtual signal void scan_completed(bool conversations_added) {
+ Logging.debug(Logging.Flag.CONVERSATIONS, "[%s] ConversationMonitor::scan_completed
conversations_added=%s",
+ folder.to_string(), conversations_added.to_string());
}
/**
@@ -258,8 +265,8 @@ public class Geary.App.ConversationMonitor : BaseObject {
scan_error(err);
}
- protected virtual void notify_scan_completed() {
- scan_completed();
+ protected virtual void notify_scan_completed(bool conversations_added) {
+ scan_completed(conversations_added);
}
protected virtual void notify_conversations_added(Gee.Collection<Conversation> conversations) {
@@ -434,6 +441,8 @@ public class Geary.App.ConversationMonitor : BaseObject {
// later when locally-available)
private async void load_by_id_async(Geary.EmailIdentifier? initial_id, int count, Email.Field fields,
Geary.Folder.ListFlags flags, Cancellable? cancellable) {
+ int start_conversations = get_conversation_count();
+
notify_scan_started();
try {
yield process_email_async(folder.path,
@@ -442,13 +451,15 @@ public class Geary.App.ConversationMonitor : BaseObject {
} catch (Error err) {
notify_scan_error(err);
} finally {
- notify_scan_completed();
+ notify_scan_completed(start_conversations < get_conversation_count());
}
}
// See note at load_by_id_async for how Email.Field should be treated by caller
private async void load_by_sparse_id(Gee.Collection<Geary.EmailIdentifier> ids, Email.Field fields,
Geary.Folder.ListFlags flags, Cancellable? cancellable) {
+ int start_conversations = get_conversation_count();
+
notify_scan_started();
try {
yield process_email_async(folder.path,
@@ -457,7 +468,7 @@ public class Geary.App.ConversationMonitor : BaseObject {
} catch (Error err) {
notify_scan_error(err);
} finally {
- notify_scan_completed();
+ notify_scan_completed(start_conversations < get_conversation_count());
}
}
@@ -629,10 +640,14 @@ public class Geary.App.ConversationMonitor : BaseObject {
}
private void on_folder_email_appended(Gee.Collection<Geary.EmailIdentifier> appended_ids) {
+ all_mail_loaded = false;
+
operation_queue.add(new AppendOperation(this, appended_ids));
}
private void on_folder_email_inserted(Gee.Collection<Geary.EmailIdentifier> inserted_ids) {
+ all_mail_loaded = false;
+
operation_queue.add(new FillWindowOperation(this, true));
}
@@ -782,8 +797,11 @@ public class Geary.App.ConversationMonitor : BaseObject {
if (!is_insert && min_window_count <= conversations.size)
return;
- if (primary_email_id_to_conversation.size >= folder.properties.email_total)
+ if (primary_email_id_to_conversation.size >= folder.properties.email_total) {
+ all_mail_loaded = true;
+
return;
+ }
int initial_message_count = get_email_count();
@@ -851,11 +869,18 @@ public class Geary.App.ConversationMonitor : BaseObject {
if (reschedule && expected_more_email)
reschedule = initial_message_count != get_email_count();
+ // as stated in third condition, possible for email_total to be incorrect, so use both to
+ // check if all mail has been loaded
+ if (folder.properties.email_total <= primary_email_id_to_conversation.size)
+ all_mail_loaded = true;
+ else if (expected_more_email && initial_message_count == get_email_count())
+ all_mail_loaded = true;
+
if (reschedule)
operation_queue.add(new FillWindowOperation(this, false));
- debug("fill_window_async: loaded from %s, email_count=%d primary_ids.size=%d folder emails=%d
conversations.size=%d rescheduled=%s",
- low_id != null ? low_id.to_string() : "(null)", get_email_count(),
primary_email_id_to_conversation.size,
+ debug("fill_window_async: loaded from %s, email_count=%d min_window_count=%d primary_ids.size=%d
folder.email_total=%d conversations.size=%d rescheduled=%s",
+ low_id != null ? low_id.to_string() : "(null)", get_email_count(), min_window_count,
primary_email_id_to_conversation.size,
folder.properties.email_total, conversations.size, reschedule.to_string());
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]