[geary/wip/730682-refine-convo-list] Refine conversation selection process.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/730682-refine-convo-list] Refine conversation selection process.
- Date: Sun, 24 Dec 2017 08:11:06 +0000 (UTC)
commit 164486901613ffb8a2e38f4277978da0d90faea1
Author: Michael James Gratton <mike vee net>
Date: Sat Dec 23 16:54:56 2017 +1030
Refine conversation selection process.
* src/client/conversation-list/conversation-list.vala
(ConversationList): Add freeze_selection() and thaw_selection() methods
to prevent the user selecting any conversations and restoring the
previous selection, or nearest conversation. Use these when displaying
an inline composer or changing folders.
* src/client/application/geary-controller.vala (GearyController): Don't
clear the selected conversation when changing folders, only when the
user deselects it, so it doesn't flash loading needlessly.
* src/client/components/main-window.vala (MainWindow): Freeze the
conversation list when changing conversation list's model, so it
doesn't flash empty folder needlessly.
* src/client/conversation-viewer/conversation-viewer.vala
(ConversationViewer): Freeze the conversation list when displaying an
inline composer so the user can't select another conversation and we
needlessly need to prompt to discard the draft.
src/client/application/geary-controller.vala | 1 -
src/client/components/main-window.vala | 28 +++++---
.../conversation-list/conversation-list.vala | 76 ++++++++++++++++---
.../conversation-viewer/conversation-viewer.vala | 13 +---
4 files changed, 86 insertions(+), 32 deletions(-)
---
diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala
index 6d407b6..0b327dc 100644
--- a/src/client/application/geary-controller.vala
+++ b/src/client/application/geary-controller.vala
@@ -1216,7 +1216,6 @@ public class GearyController : Geary.BaseObject {
this.current_folder = null;
folder_selected(null);
} else if (folder != this.current_folder) {
- this.main_window.conversation_viewer.show_loading();
get_window_action(ACTION_FIND_IN_CONVERSATION).set_enabled(false);
enable_message_buttons(false);
diff --git a/src/client/components/main-window.vala b/src/client/components/main-window.vala
index 28a3e65..e6993a5 100644
--- a/src/client/components/main-window.vala
+++ b/src/client/components/main-window.vala
@@ -275,6 +275,7 @@ public class MainWindow : Gtk.ApplicationWindow {
}
private void on_conversation_monitor_changed() {
+ this.conversation_list.freeze_selection();
ConversationListModel? old_model = this.conversation_list.model;
if (old_model != null) {
this.progress_monitor.remove(old_model.monitor.progress_monitor);
@@ -284,6 +285,7 @@ public class MainWindow : Gtk.ApplicationWindow {
old_monitor.scan_error.disconnect(on_scan_error);
old_monitor.seed_completed.disconnect(on_seed_completed);
old_monitor.seed_completed.disconnect(on_conversation_count_changed);
+ old_monitor.seed_completed.disconnect(on_initial_conversation_load);
old_monitor.scan_completed.disconnect(on_conversation_count_changed);
old_monitor.conversations_added.disconnect(on_conversation_count_changed);
old_monitor.conversations_removed.disconnect(on_conversation_count_changed);
@@ -301,10 +303,12 @@ public class MainWindow : Gtk.ApplicationWindow {
new_monitor.scan_error.connect(on_scan_error);
new_monitor.seed_completed.connect(on_seed_completed);
new_monitor.seed_completed.connect(on_conversation_count_changed);
+ new_monitor.seed_completed.connect(on_initial_conversation_load);
new_monitor.scan_completed.connect(on_conversation_count_changed);
new_monitor.conversations_added.connect(on_conversation_count_changed);
new_monitor.conversations_removed.connect(on_conversation_count_changed);
}
+ this.conversation_list.thaw_selection();
}
private void on_folder_selected(Geary.Folder? folder) {
@@ -477,6 +481,18 @@ public class MainWindow : Gtk.ApplicationWindow {
}
}
+ private void on_initial_conversation_load() {
+ // When not doing autoselect, we never get
+ // conversations_selected firing from the convo list, so we
+ // need to clear the convo viewer here
+ if (!this.application.config.autoselect) {
+ this.conversation_viewer.show_none_selected();
+ this.application.controller.enable_message_buttons(false);
+ }
+
+ this.conversation_list.model.monitor.seed_completed.disconnect(on_initial_conversation_load);
+ }
+
private void on_load_more() {
debug("on_load_more");
this.application.controller.current_conversations.min_window_count +=
GearyController.CONVERSATION_PAGE_SIZE;
@@ -496,8 +512,8 @@ public class MainWindow : Gtk.ApplicationWindow {
}
private void on_conversation_count_changed() {
- if (this.application.controller.current_conversations != null) {
- int count = this.application.controller.current_conversations.get_conversation_count();
+ if (this.conversation_list.model.monitor != null) {
+ int count = this.conversation_list.model.monitor.get_conversation_count();
if (count == 0) {
// Let the user know if there's no available conversations
if (this.current_folder is Geary.SearchFolder) {
@@ -506,14 +522,6 @@ public class MainWindow : Gtk.ApplicationWindow {
this.conversation_viewer.show_empty_folder();
}
this.application.controller.enable_message_buttons(false);
- } else {
- // When not doing autoselect, we never get
- // conversations_selected firing from the convo list,
- // so we need to stop the loading spinner here
- if (!this.application.config.autoselect) {
- this.conversation_viewer.show_none_selected();
- this.application.controller.enable_message_buttons(false);
- }
}
}
}
diff --git a/src/client/conversation-list/conversation-list.vala
b/src/client/conversation-list/conversation-list.vala
index c52ed56..6dc3ddc 100644
--- a/src/client/conversation-list/conversation-list.vala
+++ b/src/client/conversation-list/conversation-list.vala
@@ -28,6 +28,8 @@ public class ConversationList : Gtk.ListBox {
private Configuration config;
+ private int selected_index = -1;
+ private bool selection_frozen = false;
private Gee.Set<Geary.App.Conversation>? visible_conversations = null;
private Geary.Scheduler.Scheduled? update_visible_scheduled = null;
private bool enable_load_more = true;
@@ -81,6 +83,8 @@ public class ConversationList : Gtk.ListBox {
// Clear these since they will belong to the old model
this.selected = null;
+ this.selected_index = -1;
+
Gee.List<Geary.RFC822.MailboxAddress> account_addresses =
displayed.account.information.get_all_mailboxes();
bool use_to = displayed.special_folder_type.is_outgoing();
base.bind_model(this.model, (convo) => {
@@ -93,6 +97,18 @@ public class ConversationList : Gtk.ListBox {
);
}
+ public void freeze_selection() {
+ this.selection_frozen = true;
+ this.selected = null;
+ set_selection_mode(Gtk.SelectionMode.NONE);
+ }
+
+ public void thaw_selection() {
+ set_selection_mode(Gtk.SelectionMode.SINGLE);
+ this.selection_frozen = false;
+ restore_selection();
+ }
+
public void select_conversation(Geary.App.Conversation target) {
for (int i = 0; i < this.model.get_n_items(); i++) {
Gtk.ListBoxRow? row = get_row_at_index(i);
@@ -113,20 +129,25 @@ public class ConversationList : Gtk.ListBox {
return visible;
}
- private void selection_changed() {
- Geary.App.Conversation? selected = null;
- Gtk.ListBoxRow? row = get_selected_row();
- if (row != null) {
- selected = ((ConversationListItem) row.get_child()).conversation;
- }
+ private Gtk.ListBoxRow? restore_selection() {
+ Gtk.ListBoxRow? row = null;
+ if (this.selected_index >= 0) {
+ int new_index = this.selected_index;
+ if (new_index >= this.model.get_n_items()) {
+ new_index = ((int) this.model.get_n_items()) - 1;
+ }
- debug("Selection changed to: %s",
- selected != null ? selected.to_string() : null
- );
- if (this.selected != selected) {
- this.selected = selected;
- this.conversation_selection_changed(selected);
+ // XXX we should be only calling select_row() if
+ // autoselect is enabled, otherwise we should simply be
+ // updating the cursor, but Gtk.ListBox doesn't allow us
+ // to do that --- move_cursor() doesn't seem to work and
+ // is O(n) anyway.
+ row = get_row_at_index(new_index);
+ if (row != null) {
+ select_row(row);
+ }
}
+ return row;
}
private void schedule_visible_conversations_changed() {
@@ -137,6 +158,37 @@ public class ConversationList : Gtk.ListBox {
});
}
+ private void selection_changed() {
+ if (!this.selection_frozen) {
+ Geary.App.Conversation? selected = null;
+ Gtk.ListBoxRow? row = get_selected_row();
+
+ // If a row was de-selected then we need to work out if
+ // that was because of a conversation being removed from
+ // the list, and if so select a new one
+ if (row == null &&
+ this.selected != null &&
+ !this.model.monitor.has_conversation(this.selected)) {
+ row = restore_selection();
+ }
+
+ if (row != null) {
+ selected = ((ConversationListItem) row.get_child()).conversation;
+ this.selected_index = row.get_index();
+ } else {
+ this.selected_index = -1;
+ }
+
+ debug("Selection changed to: %s",
+ selected != null ? selected.to_string() : null
+ );
+ if (this.selected != selected) {
+ this.selected = selected;
+ this.conversation_selection_changed(selected);
+ }
+ }
+ }
+
private void update_visible_conversations() {
Gee.Set<Geary.App.Conversation> visible_now = get_visible_conversations();
if (this.visible_conversations == null ||
diff --git a/src/client/conversation-viewer/conversation-viewer.vala
b/src/client/conversation-viewer/conversation-viewer.vala
index 65e4af5..c7517b8 100644
--- a/src/client/conversation-viewer/conversation-viewer.vala
+++ b/src/client/conversation-viewer/conversation-viewer.vala
@@ -103,16 +103,11 @@ public class ConversationViewer : Gtk.Stack {
// XXX move the ConversationListView management code into
// GearyController or somewhere more appropriate
ConversationList conversation_list =
- ((MainWindow) GearyApplication.instance.controller.main_window).conversation_list;
- Geary.App.Conversation prev_selection = conversation_list.selected;
- conversation_list.unselect_all();
+ GearyApplication.instance.controller.main_window.conversation_list;
+ conversation_list.freeze_selection();
box.vanished.connect((box) => {
- set_visible_child(this.conversation_page);
- if (prev_selection == null) {
- conversation_list.conversation_selection_changed(null);
- } else {
- conversation_list.select_conversation(prev_selection);
- }
+ show_none_selected();
+ conversation_list.thaw_selection();
});
this.composer_page.add(box);
set_visible_child(this.composer_page);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]