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)
This commit is contained in:
parent
8348f2ef19
commit
864a3135e3
12 changed files with 230 additions and 36 deletions
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1179,11 +1179,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);
|
||||
|
|
@ -1588,9 +1600,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.main_toolbar.full_actions.service_provider = service_provider;
|
||||
this.main_toolbar.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
32
src/client/components/folder-popover-row.vala
Normal file
32
src/client/components/folder-popover-row.vala
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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");
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -66,6 +66,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',
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
46
ui/folder-popover-row.ui
Normal file
46
ui/folder-popover-row.ui
Normal file
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
|
|
|
|||
15
ui/geary.css
15
ui/geary.css
|
|
@ -68,12 +68,21 @@ revealer components-conversation-actions {
|
|||
|
||||
/* FolderPopover */
|
||||
|
||||
.geary-folder-popover-list {
|
||||
border: 1px solid @borders;
|
||||
border-radius: 3px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,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>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue