[geary/gnumdk/stable: 21/21] components: Rework Folder Popover
- From: Cédric Bellegarde <cbellegarde src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/gnumdk/stable: 21/21] components: Rework Folder Popover
- Date: Mon, 1 Aug 2022 12:45:48 +0000 (UTC)
commit 94337634e8853f5e31db9ef77d5feedd8dba8d73
Author: Cédric Bellegarde <cedric bellegarde adishatz org>
Date: Mon Jul 18 13:54:39 2022 +0200
components: Rework Folder Popover
- Do not use tags for service providers not using this metaphor
- Do not show folders with a dedicated button: Trash, Archive, ...
- Do not show folders as an IMAP path but as a human readable path (>INBOX>Folder vs Boîte de
reception/Folder)
.../application/application-folder-context.vala | 13 ++++-
.../application/application-main-window.vala | 39 +++++++++++++--
.../components-conversation-actions.vala | 36 ++++++++++++--
src/client/components/folder-popover-row.vala | 32 ++++++++++++
src/client/components/folder-popover.vala | 58 ++++++++++++++--------
.../folder-list/folder-list-account-branch.vala | 13 ++++-
src/client/meson.build | 1 +
src/client/util/util-gtk.vala | 9 ++++
ui/folder-popover-row.ui | 46 +++++++++++++++++
ui/folder-popover.ui | 5 +-
ui/geary.css | 14 ++++--
ui/org.gnome.Geary.gresource.xml | 1 +
12 files changed, 230 insertions(+), 37 deletions(-)
---
diff --git a/src/client/application/application-folder-context.vala
b/src/client/application/application-folder-context.vala
index 4ed47cf56..1a16385b9 100644
--- a/src/client/application/application-folder-context.vala
+++ b/src/client/application/application-folder-context.vala
@@ -46,6 +46,17 @@ public class Application.FolderContext : Geary.BaseObject,
return this.folder.path.compare_to(other.folder.path);
}
+ private string get_default_icon_name() {
+ var service_provider = this.folder.account.information.service_provider;
+
+ switch (service_provider) {
+ case Geary.ServiceProvider.GMAIL:
+ return "tag-symbolic";
+ default:
+ return "folder-symbolic";
+ }
+ }
+
private void update() {
this.display_name = Util.I18n.to_folder_display_name(this.folder);
@@ -88,7 +99,7 @@ public class Application.FolderContext : Geary.BaseObject,
break;
default:
- this.icon_name = "tag-symbolic";
+ this.icon_name = get_default_icon_name();
break;
}
diff --git a/src/client/application/application-main-window.vala
b/src/client/application/application-main-window.vala
index 41b4493ff..4270a6004 100644
--- a/src/client/application/application-main-window.vala
+++ b/src/client/application/application-main-window.vala
@@ -1168,11 +1168,23 @@ public class Application.MainWindow :
/** Adds a folder to the window. */
private void add_folders(Gee.Collection<FolderContext> to_add) {
+ // Build map between path and display name for
+ // special directories
+ var map = new Gee.HashMap<string,string>();
+ foreach (var context in to_add) {
+ var folder = context.folder;
+ if (folder.used_as == Geary.Folder.SpecialUse.NONE)
+ continue;
+ map.set(
+ folder.path.to_string().substring(1),
+ context.display_name
+ );
+ }
foreach (var context in to_add) {
this.folder_list.add_folder(context);
if (context.folder.account == this.selected_account) {
foreach (var menu in this.folder_popovers) {
- menu.add_folder(context.folder);
+ menu.add_folder(context, map);
}
}
context.folder.use_changed.connect(on_use_changed);
@@ -1561,9 +1573,28 @@ public class Application.MainWindow :
this.search_bar.set_account(account);
if (account != null) {
+ var service_provider = account.information.service_provider;
+ this.conversation_list_actions.service_provider = service_provider;
+ this.conversation_headerbar.full_actions.service_provider = service_provider;
+ this.conversation_headerbar.compact_actions.service_provider = service_provider;
+
foreach (var menu in this.folder_popovers) {
- foreach (var folder in account.list_folders()) {
- menu.add_folder(folder);
+ var folders = account.list_folders();
+ // Build map between path and display name for
+ // special directories
+ var map = new Gee.HashMap<string,string>();
+ foreach (var folder in folders) {
+ var context = new Application.FolderContext(folder);
+ if (folder.used_as == Geary.Folder.SpecialUse.NONE)
+ continue;
+ map.set(
+ folder.path.to_string().substring(1),
+ context.display_name
+ );
+ }
+ foreach (var folder in folders) {
+ var context = new Application.FolderContext(folder);
+ menu.add_folder(context, map);
}
}
}
@@ -2408,7 +2439,7 @@ public class Application.MainWindow :
this.conversation_list_actions_revealer.child_revealed) {
this.conversation_list_actions.show_copy_menu();
} else if (this.is_conversation_viewer_shown) {
- this.main_toolbar.shown_actions.show_copy_menu();
+ this.conversation_headerbar.shown_actions.show_copy_menu();
} else {
error_bell();
}
diff --git a/src/client/components/components-conversation-actions.vala
b/src/client/components/components-conversation-actions.vala
index 8030c424b..7adb6afc3 100644
--- a/src/client/components/components-conversation-actions.vala
+++ b/src/client/components/components-conversation-actions.vala
@@ -24,6 +24,8 @@ public class Components.ConversationActions : Gtk.Box {
public int selected_conversations { get; set; }
+ public Geary.ServiceProvider service_provider { get; set; }
+
[GtkChild] private unowned Gtk.Box response_buttons { get; }
[GtkChild] private unowned Gtk.Box mark_copy_move_buttons { get; }
@@ -56,6 +58,7 @@ public class Components.ConversationActions : Gtk.Box {
);
this.notify["selected-conversations"].connect(() => update_conversation_buttons());
+ this.notify["service-provider"].connect(() => update_conversation_buttons());
this.mark_message_button.popover = new Gtk.Popover.from_model(null, mark_menu);
this.copy_message_button.popover = copy_folder_menu;
this.move_message_button.popover = move_folder_menu;
@@ -110,11 +113,7 @@ public class Components.ConversationActions : Gtk.Box {
"Mark conversations",
this.selected_conversations
);
- this.copy_message_button.tooltip_text = ngettext(
- "Add label to conversation",
- "Add label to conversations",
- this.selected_conversations
- );
+
this.move_message_button.tooltip_text = ngettext(
"Move conversation",
"Move conversations",
@@ -126,6 +125,33 @@ public class Components.ConversationActions : Gtk.Box {
this.selected_conversations
);
+ var copy_icon_name = "edit-copy-symbolic";
+ var move_icon_name = "edit-cut-symbolic";
+ switch (this.service_provider) {
+ case Geary.ServiceProvider.GMAIL:
+ this.copy_message_button.tooltip_text = ngettext(
+ "Add label to conversation",
+ "Add label to conversations",
+ this.selected_conversations
+ );
+ copy_icon_name = "tag-symbolic";
+ move_icon_name = "folder-symbolic";
+ break;
+ default:
+ this.copy_message_button.tooltip_text = ngettext(
+ "Copy conversation",
+ "Copy conversations",
+ this.selected_conversations
+ );
+ break;
+ }
+ this.copy_message_button.set_image(
+ new Gtk.Image.from_icon_name(copy_icon_name, Gtk.IconSize.BUTTON)
+ );
+ this.move_message_button.set_image(
+ new Gtk.Image.from_icon_name(move_icon_name, Gtk.IconSize.BUTTON)
+ );
+
if (this.show_trash_button) {
this.trash_delete_button.action_name = Action.Window.prefix(
Application.MainWindow.ACTION_TRASH_CONVERSATION
diff --git a/src/client/components/folder-popover-row.vala b/src/client/components/folder-popover-row.vala
new file mode 100644
index 000000000..98033bcdf
--- /dev/null
+++ b/src/client/components/folder-popover-row.vala
@@ -0,0 +1,32 @@
+/* Copyright 2022 Cédric Bellegarde <cedric bellegarde adishatz org>
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+[GtkTemplate (ui = "/org/gnome/Geary/folder-popover-row.ui")]
+public class FolderPopoverRow : Gtk.ListBoxRow {
+
+ [GtkChild] private unowned Gtk.Image image;
+ [GtkChild] private unowned Gtk.Label label;
+
+ public FolderPopoverRow(Application.FolderContext context, Gee.HashMap<string,string> map) {
+ string[] as_array = context.folder.path.as_array();
+
+ if (map.has_key(as_array[0])) {
+ as_array[0] = map[as_array[0]];
+ }
+
+ var i = 0;
+ foreach (string name in as_array) {
+ as_array[i] = GLib.Markup.escape_text(name);
+ i += 1;
+ }
+
+ this.set_data("folder", context.folder);
+ this.image.icon_name = context.icon_name;
+
+ this.label.set_markup(string.joinv("<span alpha='30%'> / </span>", as_array));
+ this.label.query_tooltip.connect(Util.Gtk.query_tooltip_label);
+ }
+}
diff --git a/src/client/components/folder-popover.vala b/src/client/components/folder-popover.vala
index faba1df2b..90dfd81f0 100644
--- a/src/client/components/folder-popover.vala
+++ b/src/client/components/folder-popover.vala
@@ -28,7 +28,8 @@ public class FolderPopover : Gtk.Popover {
return get_row_with_folder(folder) != null;
}
- public void add_folder(Geary.Folder folder) {
+ public void add_folder(Application.FolderContext context, Gee.HashMap<string,string> map) {
+ Geary.Folder folder = context.folder;
// don't allow multiples and don't allow folders that can't be opened (that means they
// support almost no operations and have no content)
if (has_folder(folder) || folder.properties.is_openable.is_impossible())
@@ -39,14 +40,36 @@ public class FolderPopover : Gtk.Popover {
if (folder.properties.is_local_only || folder.properties.is_virtual)
return;
- list_box.add(build_row(folder));
+ // Moving mails to Drafts folder not supported
+ switch (folder.account.information.service_provider) {
+ case Geary.ServiceProvider.GMAIL:
+ if (folder.used_as == Geary.Folder.SpecialUse.DRAFTS)
+ return;
+ break;
+ default:
+ break;
+ }
+
+ // Ignore special directories already having a dedicated button
+ switch (folder.used_as) {
+ case Geary.Folder.SpecialUse.ARCHIVE:
+ case Geary.Folder.SpecialUse.TRASH:
+ case Geary.Folder.SpecialUse.JUNK:
+ return;
+ default:
+ break;
+ }
+
+ var row = new FolderPopoverRow(context, map);
+ row.show();
+ list_box.add(row);
list_box.invalidate_sort();
}
- public void enable_disable_folder(Geary.Folder folder, bool sensitive) {
+ public void enable_disable_folder(Geary.Folder folder, bool visible) {
Gtk.ListBoxRow row = get_row_with_folder(folder);
if (row != null)
- row.sensitive = sensitive;
+ row.visible = visible;
}
public void remove_folder(Geary.Folder folder) {
@@ -68,20 +91,6 @@ public class FolderPopover : Gtk.Popover {
list_box.foreach((row) => list_box.remove(row));
}
- private Gtk.ListBoxRow build_row(Geary.Folder folder) {
- Gtk.ListBoxRow row = new Gtk.ListBoxRow();
- row.get_style_context().add_class("geary-folder-popover-list-row");
- row.set_data("folder", folder);
-
- Gtk.Label label = new Gtk.Label(folder.path.to_string());
- label.set_halign(Gtk.Align.START);
- row.add(label);
-
- row.show_all();
-
- return row;
- }
-
[GtkCallback]
private void on_row_activated(Gtk.ListBoxRow? row) {
if (row != null) {
@@ -118,8 +127,8 @@ public class FolderPopover : Gtk.Popover {
}
private bool row_filter(Gtk.ListBoxRow row) {
- Gtk.Label label = row.get_child() as Gtk.Label;
- if (label.label.down().contains(search_entry.text.down())) {
+ Geary.Folder folder = row.get_data<Geary.Folder>("folder");
+ if (folder.path.to_string().down().contains(search_entry.text.down())) {
filtered_folder_count++;
return true;
}
@@ -129,6 +138,13 @@ public class FolderPopover : Gtk.Popover {
private int row_sort(Gtk.ListBoxRow row1, Gtk.ListBoxRow row2) {
Geary.Folder folder1 = row1.get_data<Geary.Folder>("folder");
Geary.Folder folder2 = row2.get_data<Geary.Folder>("folder");
- return folder1.path.compare_to(folder2.path);
+ if (folder1.used_as != Geary.Folder.SpecialUse.NONE &&
+ folder2.used_as == Geary.Folder.SpecialUse.NONE)
+ return -1;
+ else if (folder1.used_as == Geary.Folder.SpecialUse.NONE &&
+ folder2.used_as != Geary.Folder.SpecialUse.NONE)
+ return 1;
+ else
+ return folder1.path.compare_to(folder2.path);
}
}
diff --git a/src/client/folder-list/folder-list-account-branch.vala
b/src/client/folder-list/folder-list-account-branch.vala
index 4e67a1948..ffb576a96 100644
--- a/src/client/folder-list/folder-list-account-branch.vala
+++ b/src/client/folder-list/folder-list-account-branch.vala
@@ -43,7 +43,18 @@ public class FolderList.AccountBranch : Sidebar.Branch {
// Translators: The name of the folder group containing
// folders created by people (as opposed to special-use
// folders)
- user_folder_group = new SpecialGrouping(2, _("Labels"), "tag-symbolic");
+ string name, icon_name;
+ switch (account.information.service_provider) {
+ case Geary.ServiceProvider.GMAIL:
+ name = _("Labels");
+ icon_name = "tag-symbolic";
+ break;
+ default:
+ name = _("Folders");
+ icon_name = "folder-symbolic";
+ break;
+ }
+ user_folder_group = new SpecialGrouping(2, name, icon_name);
folder_entries = new Gee.HashMap<Geary.FolderPath, FolderEntry>();
this.display_name = account.information.display_name;
diff --git a/src/client/meson.build b/src/client/meson.build
index ef8e7d641..eeabedbb9 100644
--- a/src/client/meson.build
+++ b/src/client/meson.build
@@ -68,6 +68,7 @@ client_vala_sources = files(
'components/components-web-view.vala',
'components/count-badge.vala',
'components/folder-popover.vala',
+ 'components/folder-popover-row.vala',
'components/icon-factory.vala',
'components/monitored-progress-bar.vala',
'components/monitored-spinner.vala',
diff --git a/src/client/util/util-gtk.vala b/src/client/util/util-gtk.vala
index 09d59e816..63e27e136 100644
--- a/src/client/util/util-gtk.vala
+++ b/src/client/util/util-gtk.vala
@@ -227,4 +227,13 @@ namespace Util.Gtk {
};
}
+ /* Connect this to Gtk.Widget.query_tooltip signal, will only show tooltip if label ellipsized */
+ public bool query_tooltip_label(global::Gtk.Widget widget, int x, int y, bool keyboard,
global::Gtk.Tooltip tooltip) {
+ global::Gtk.Label label = widget as global::Gtk.Label;
+ if (label.get_layout().is_ellipsized()) {
+ tooltip.set_markup(label.label);
+ return true;
+ }
+ return false;
+ }
}
diff --git a/ui/folder-popover-row.ui b/ui/folder-popover-row.ui
new file mode 100644
index 000000000..b7a9309e0
--- /dev/null
+++ b/ui/folder-popover-row.ui
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+ <requires lib="gtk+" version="3.14"/>
+ <template class="FolderPopoverRow" parent="GtkListBoxRow">
+ <child>
+ <object class="GtkBox" id="container">
+ <property name="visible">True</property>
+ <property name="margin_start">6</property>
+ <property name="margin_end">6</property>
+ <property name="margin_top">6</property>
+ <property name="margin_bottom">6</property>
+ <property name="orientation">horizontal</property>
+ <property name="spacing">10</property>
+ <child>
+ <object class="GtkImage" id="image">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkLabel" id="label">
+ <property name="visible">True</property>
+ <property name="halign">start</property>
+ <property name="hexpand">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="ellipsize">end</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">1</property>
+ </packing>
+ </child>
+ </object>
+ </child>
+ <style>
+ <class name="geary-folder-popover-list-row"/>
+ </style>
+ </template>
+</interface>
diff --git a/ui/folder-popover.ui b/ui/folder-popover.ui
index 473d3dc34..881c8a5fb 100644
--- a/ui/folder-popover.ui
+++ b/ui/folder-popover.ui
@@ -29,14 +29,15 @@
</child>
<child>
<object class="GtkScrolledWindow" id="scrolled">
- <property name="min_content_width">200</property>
+ <property name="width-request">300</property>
<property name="min_content_height">320</property>
<property name="visible">True</property>
- <property name="shadow_type">in</property>
+ <property name="shadow_type">none</property>
<property name="hscrollbar_policy">never</property>
<child>
<object class="GtkListBox" id="list_box">
<property name="visible">True</property>
+ <property name="valign">start</property>
<property name="activate_on_single_click">True</property>
<signal name="row_activated" handler="on_row_activated" swapped="no"/>
<style>
diff --git a/ui/geary.css b/ui/geary.css
index 84533f5ff..309b756bb 100644
--- a/ui/geary.css
+++ b/ui/geary.css
@@ -68,12 +68,20 @@ revealer components-conversation-actions {
/* FolderPopover */
+.geary-folder-popover-list {
+ border: 1px solid @borders;
+ border-radius: 3px;
+}
+
row.geary-folder-popover-list-row {
padding: 6px;
- border-color: @borders;
- border-style: groove;
- border-bottom-width: 1px;
+ border-bottom: 1px solid @borders;
}
+
+row.geary-folder-popover-list-row:last-child {
+ border-bottom: none;
+}
+
row.geary-folder-popover-list-row > label {
color: @theme_text_color;
}
diff --git a/ui/org.gnome.Geary.gresource.xml b/ui/org.gnome.Geary.gresource.xml
index d25e3b596..a486d1fa8 100644
--- a/ui/org.gnome.Geary.gresource.xml
+++ b/ui/org.gnome.Geary.gresource.xml
@@ -43,6 +43,7 @@
<file compressed="true">conversation-web-view.js</file>
<file compressed="true" preprocess="xml-stripblanks">find_bar.glade</file>
<file compressed="true" preprocess="xml-stripblanks">folder-popover.ui</file>
+ <file compressed="true" preprocess="xml-stripblanks">folder-popover-row.ui</file>
<file compressed="true" preprocess="xml-stripblanks">gtk/help-overlay.ui</file>
<file compressed="true" preprocess="xml-stripblanks">password-dialog.glade</file>
<file compressed="true" preprocess="xml-stripblanks">problem-details-dialog.ui</file>
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]