From 48fdf9575741df298c3442f01c82b10bf56dc8be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 17 May 2023 14:38:10 -0700 Subject: [PATCH 1/7] MessageList: Rewrite headers --- data/application.css | 18 ++- src/MessageList/MessageList.vala | 31 +++++ src/MessageList/MessageListItem.vala | 166 ++++++++++----------------- 3 files changed, 109 insertions(+), 106 deletions(-) diff --git a/data/application.css b/data/application.css index acccbdbbe..aa9de5a83 100644 --- a/data/application.css +++ b/data/application.css @@ -7,8 +7,22 @@ ); } -.card.collapsed { - margin-bottom: -64px; +.message-list list { + padding: 0 1rem 0.25rem; +} + +.message-list list > .h4 { + font-size: 1.25rem; + font-weight: 600; + padding: 0.75rem 0; +} + +.message-list-item { + margin: 0.75rem 0; +} + +.message-list-item.collapsed { + margin: 0.5rem 0; } .conversation-list-item { diff --git a/src/MessageList/MessageList.vala b/src/MessageList/MessageList.vala index 7432d6383..06ebda3c5 100644 --- a/src/MessageList/MessageList.vala +++ b/src/MessageList/MessageList.vala @@ -15,6 +15,7 @@ public class Mail.MessageList : Gtk.Box { construct { get_style_context ().add_class (Gtk.STYLE_CLASS_BACKGROUND); + get_style_context ().add_class ("message-list"); var application_instance = (Gtk.Application) GLib.Application.get_default (); @@ -169,6 +170,7 @@ public class Mail.MessageList : Gtk.Box { list_box.get_style_context ().add_class (Gtk.STYLE_CLASS_BACKGROUND); list_box.set_placeholder (placeholder); list_box.set_sort_func (message_sort_function); + list_box.set_header_func (message_header_func); scrolled_window = new Gtk.ScrolledWindow (null, null) { hscrollbar_policy = NEVER @@ -300,6 +302,35 @@ public class Mail.MessageList : Gtk.Box { ((SimpleAction) main_window.lookup_action (MainWindow.ACTION_MOVE_TO_TRASH)).set_enabled (enabled); } + private void message_header_func (Gtk.ListBoxRow row, Gtk.ListBoxRow? before) { + unowned var message = (MessageListItem) row; + unowned var message_before = (MessageListItem) before; + + var subject = message.message_info.subject; + + if (message_before == null || message_before != null && sanitize_subject (message_before.message_info.subject) != sanitize_subject (subject)) { + if (subject == "") { + subject = _("No Subject"); + } + + var header_label = new Granite.HeaderLabel (subject) { + wrap = true, + }; + + row.set_header (header_label); + } + } + + private string sanitize_subject (string _subject) { + var subject = _subject.down (); + subject = subject.replace (" ", ""); + subject = subject.replace (":", ""); + subject = subject.replace ("re", ""); + subject = subject.replace ("fwd", ""); + + return subject; + } + private static int message_sort_function (Gtk.ListBoxRow item1, Gtk.ListBoxRow item2) { unowned MessageListItem message1 = (MessageListItem)item1; unowned MessageListItem message2 = (MessageListItem)item2; diff --git a/src/MessageList/MessageListItem.vala b/src/MessageList/MessageListItem.vala index 3d61762d8..c2b7b7029 100644 --- a/src/MessageList/MessageListItem.vala +++ b/src/MessageList/MessageListItem.vala @@ -28,7 +28,6 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { private Gtk.InfoBar blocked_images_infobar; private Gtk.Revealer secondary_revealer; - private Gtk.Stack header_stack; private Gtk.StyleContext style_context; private Hdy.Avatar avatar; private Gtk.FlowBox attachment_bar = null; @@ -46,7 +45,6 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { } set { secondary_revealer.reveal_child = value; - header_stack.set_visible_child_name (value ? "large" : "small"); if (value) { if (!message_loaded) { get_message.begin (); @@ -63,10 +61,6 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { public MessageListItem (Camel.MessageInfo message_info) { Object ( - margin_top: 12, - margin_bottom: 12, - margin_start: 12, - margin_end: 12, message_info: message_info ); } @@ -81,6 +75,7 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { style_context = get_style_context (); style_context.add_class (Granite.STYLE_CLASS_CARD); + style_context.add_class ("message-list-item"); unowned string? parsed_address; unowned string? parsed_name; @@ -93,53 +88,57 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { parsed_name = parsed_address; } - avatar = new Hdy.Avatar (48, parsed_name, true) { - valign = Gtk.Align.START + avatar = new Hdy.Avatar (40, parsed_name, true) { + valign = START }; - var from_label = new Gtk.Label (_("From:")) { - halign = END, - valign = START + var from_label = new Gtk.Label (message_info.from) { + wrap = true, + xalign = 0 }; - from_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); var to_label = new Gtk.Label (_("To:")) { - halign = END, - valign = START + halign = END }; to_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - var subject_label = new Gtk.Label (_("Subject:")) { - halign = END, - valign = START - }; - subject_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - - var from_val_label = new Gtk.Label (message_info.from) { + var to_val_label = new Gtk.Label (message_info.to) { + hexpand = true, wrap = true, xalign = 0 }; - var to_val_label = new Gtk.Label (message_info.to) { - wrap = true, - xalign = 0 + var relevant_timestamp = message_info.date_received; + if (relevant_timestamp == 0) { + // Sent messages do not have a date_received timestamp. + relevant_timestamp = message_info.date_sent; + } + + var date_format = Granite.DateTime.get_default_date_format (false, true, true); + var time_format = Granite.DateTime.get_default_time_format (desktop_settings.get_enum ("clock-format") == 1, false); + + var datetime_label = new Gtk.Label ( + ///TRANSLATORS: The first %s represents the date and the second %s the time of the message (either when it was received or sent) + new DateTime.from_unix_utc (relevant_timestamp).to_local ().format (_("%s at %s").printf (date_format, time_format)) + ) { + halign = END }; + datetime_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - var subject_val_label = new Gtk.Label (message_info.subject) { - wrap = true, - xalign = 0 + var action_box = new Gtk.Box (HORIZONTAL, 6) { + halign = END, + hexpand = true, + margin_top = 3 }; var fields_grid = new Gtk.Grid () { - column_spacing = 6, - row_spacing = 6 + column_spacing = 3, }; - fields_grid.attach (from_label, 0, 0, 1, 1); - fields_grid.attach (to_label, 0, 1, 1, 1); - fields_grid.attach (subject_label, 0, 3, 1, 1); - fields_grid.attach (from_val_label, 1, 0, 1, 1); - fields_grid.attach (to_val_label, 1, 1, 1, 1); - fields_grid.attach (subject_val_label, 1, 3, 1, 1); + fields_grid.attach (from_label, 0, 0, 2); + fields_grid.attach (to_label, 0, 1); + fields_grid.attach (to_val_label, 1, 1); + fields_grid.attach (datetime_label, 2, 0); + fields_grid.attach (action_box, 2, 1); var cc_info = message_info.cc; if (cc_info != null) { @@ -154,55 +153,25 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { xalign = 0 }; - fields_grid.attach (cc_label, 0, 2, 1, 1); - fields_grid.attach (cc_val_label, 1, 2, 1, 1); + fields_grid.attach (cc_label, 0, 2); + fields_grid.attach (cc_val_label, 1, 2); } - var small_from_label = new Gtk.Label (message_info.from) { - ellipsize = END, - xalign = 0 - }; - - var small_fields_grid = new Gtk.Grid (); - small_fields_grid.attach (small_from_label, 0, 0, 1, 1); + var starred_icon = new Gtk.Image (); - header_stack = new Gtk.Stack () { - homogeneous = false, - transition_type = CROSSFADE + var starred_button = new Gtk.Button () { + child = starred_icon }; - header_stack.add_named (fields_grid, "large"); - header_stack.add_named (small_fields_grid, "small"); - header_stack.show_all (); - - var relevant_timestamp = message_info.date_received; - if (relevant_timestamp == 0) { - // Sent messages do not have a date_received timestamp. - relevant_timestamp = message_info.date_sent; - } - - var date_format = Granite.DateTime.get_default_date_format (false, true, true); - var time_format = Granite.DateTime.get_default_time_format (desktop_settings.get_enum ("clock-format") == 1, false); - - ///TRANSLATORS: The first %s represents the date and the second %s the time of the message (either when it was received or sent) - var datetime_label = new Gtk.Label (new DateTime.from_unix_utc (relevant_timestamp).to_local ().format (_("%s at %s").printf (date_format, time_format))); - datetime_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL); - - var starred_icon = new Gtk.Image (); - starred_icon.icon_size = Gtk.IconSize.MENU; + starred_button.get_style_context ().add_class ("image-button"); if (Camel.MessageFlags.FLAGGED in (int) message_info.flags) { starred_icon.icon_name = "starred-symbolic"; - starred_icon.tooltip_text = _("Unstar message"); + starred_button.tooltip_text = _("Unstar message"); } else { starred_icon.icon_name = "non-starred-symbolic"; - starred_icon.tooltip_text = _("Star message"); + starred_button.tooltip_text = _("Star message"); } - var starred_button = new Gtk.Button () { - child = starred_icon - }; - starred_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - var upper_section = new Menu (); upper_section.append (_("Reply"), Action.print_detailed_name ( MainWindow.ACTION_PREFIX + MainWindow.ACTION_REPLY, message_info.uid @@ -226,24 +195,11 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { var actions_menu_button = new Gtk.MenuButton () { image = new Gtk.Image.from_icon_name ("view-more-symbolic", Gtk.IconSize.MENU), tooltip_text = _("More"), - margin_top = 6, - valign = START, - halign = END, menu_model = actions_menu, use_popover = false }; actions_menu_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - var action_grid = new Gtk.Grid () { - column_spacing = 3, - hexpand = true, - halign = END, - valign = START - }; - action_grid.attach (datetime_label, 0, 0); - action_grid.attach (starred_button, 2, 0); - action_grid.attach (actions_menu_button, 2, 1); - var header = new Gtk.Grid () { margin_top = 12, margin_bottom = 12, @@ -251,9 +207,8 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { margin_end = 12, column_spacing = 12 }; - header.attach (avatar, 0, 0, 1, 3); - header.attach (header_stack, 1, 0, 1, 3); - header.attach (action_grid, 2, 0); + header.attach (avatar, 0, 0, 1); + header.attach (fields_grid, 1, 0, 1); var header_event_box = new Gtk.EventBox (); header_event_box.events |= Gdk.EventMask.ENTER_NOTIFY_MASK; @@ -302,6 +257,24 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { secondary_box.add (blocked_images_infobar); secondary_box.add (web_view); + if (Camel.MessageFlags.ATTACHMENTS in (int) message_info.flags) { + var attachment_icon = new Gtk.Image.from_icon_name ("mail-attachment-symbolic", Gtk.IconSize.MENU) { + tooltip_text = _("This message contains one or more attachments") + }; + action_box.add (attachment_icon); + + attachment_bar = new Gtk.FlowBox () { + hexpand = true, + homogeneous = true + }; + attachment_bar.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); + attachment_bar.get_style_context ().add_class ("bottom-toolbar"); + secondary_box.add (attachment_bar); + } + + action_box.add (starred_button); + action_box.add (actions_menu_button); + secondary_revealer = new Gtk.Revealer () { transition_type = SLIDE_UP }; @@ -314,21 +287,6 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { base_box.add (header_event_box); base_box.add (secondary_revealer); - if (Camel.MessageFlags.ATTACHMENTS in (int) message_info.flags) { - var attachment_icon = new Gtk.Image.from_icon_name ("mail-attachment-symbolic", Gtk.IconSize.MENU); - attachment_icon.margin_start = 6; - attachment_icon.tooltip_text = _("This message contains one or more attachments"); - action_grid.attach (attachment_icon, 1, 0); - - attachment_bar = new Gtk.FlowBox () { - hexpand = true, - homogeneous = true - }; - attachment_bar.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - attachment_bar.get_style_context ().add_class ("bottom-toolbar"); - secondary_box.add (attachment_bar); - } - add (base_box); expanded = false; show_all (); From d35c9feefa82169e4207b22ea7b9a5fe5bb44ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 17 May 2023 14:43:09 -0700 Subject: [PATCH 2/7] Reduce diff --- src/MessageList/MessageListItem.vala | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/MessageList/MessageListItem.vala b/src/MessageList/MessageListItem.vala index c2b7b7029..f75d53cb2 100644 --- a/src/MessageList/MessageListItem.vala +++ b/src/MessageList/MessageListItem.vala @@ -257,6 +257,18 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { secondary_box.add (blocked_images_infobar); secondary_box.add (web_view); + secondary_revealer = new Gtk.Revealer () { + transition_type = SLIDE_UP + }; + secondary_revealer.add (secondary_box); + + var base_box = new Gtk.Box (VERTICAL, 0) { + hexpand = true, + vexpand = true + }; + base_box.add (header_event_box); + base_box.add (secondary_revealer); + if (Camel.MessageFlags.ATTACHMENTS in (int) message_info.flags) { var attachment_icon = new Gtk.Image.from_icon_name ("mail-attachment-symbolic", Gtk.IconSize.MENU) { tooltip_text = _("This message contains one or more attachments") @@ -275,18 +287,6 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { action_box.add (starred_button); action_box.add (actions_menu_button); - secondary_revealer = new Gtk.Revealer () { - transition_type = SLIDE_UP - }; - secondary_revealer.add (secondary_box); - - var base_box = new Gtk.Box (VERTICAL, 0) { - hexpand = true, - vexpand = true - }; - base_box.add (header_event_box); - base_box.add (secondary_revealer); - add (base_box); expanded = false; show_all (); From 1de0fe172af6b2196f870f2b714aec4f531b4b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Wed, 17 May 2023 14:44:14 -0700 Subject: [PATCH 3/7] Header is a box --- src/MessageList/MessageListItem.vala | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/MessageList/MessageListItem.vala b/src/MessageList/MessageListItem.vala index f75d53cb2..5a185c841 100644 --- a/src/MessageList/MessageListItem.vala +++ b/src/MessageList/MessageListItem.vala @@ -200,15 +200,14 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { }; actions_menu_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); - var header = new Gtk.Grid () { + var header = new Gtk.Box (HORIZONTAL, 12) { margin_top = 12, margin_bottom = 12, margin_start = 12, - margin_end = 12, - column_spacing = 12 + margin_end = 12 }; - header.attach (avatar, 0, 0, 1); - header.attach (fields_grid, 1, 0, 1); + header.add (avatar); + header.add (fields_grid); var header_event_box = new Gtk.EventBox (); header_event_box.events |= Gdk.EventMask.ENTER_NOTIFY_MASK; From f7744c53771d6032c176984a9cdd12593744167d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 18 May 2023 11:04:49 -0700 Subject: [PATCH 4/7] Fewer margin --- data/application.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/application.css b/data/application.css index aa9de5a83..4f493e208 100644 --- a/data/application.css +++ b/data/application.css @@ -22,7 +22,7 @@ } .message-list-item.collapsed { - margin: 0.5rem 0; + margin-bottom: 0.25rem; } .conversation-list-item { From 62eff09b1055451ed5c4933c0f79cff8299addbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 18 May 2023 11:32:23 -0700 Subject: [PATCH 5/7] Try to overlap things again --- data/application.css | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/data/application.css b/data/application.css index 4f493e208..2f4f182cf 100644 --- a/data/application.css +++ b/data/application.css @@ -17,12 +17,17 @@ padding: 0.75rem 0; } +.message-list list > .h4 + .h4 { + margin-bottom: 2.75em; +} + .message-list-item { margin: 0.75rem 0; } -.message-list-item.collapsed { - margin-bottom: 0.25rem; +.message-list-item.collapsed + .message-list-item { + margin-top: -3.25em; + margin-bottom: 1em; } .conversation-list-item { From 0bff7dadfe103fedad0a44b51cf75db16bb58967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 18 May 2023 12:02:08 -0700 Subject: [PATCH 6/7] Fix overlapping header --- src/MessageList/MessageListItem.vala | 30 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/MessageList/MessageListItem.vala b/src/MessageList/MessageListItem.vala index 5a185c841..39d80adf2 100644 --- a/src/MessageList/MessageListItem.vala +++ b/src/MessageList/MessageListItem.vala @@ -27,6 +27,7 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { private GLib.Cancellable loading_cancellable; private Gtk.InfoBar blocked_images_infobar; + private Gtk.Revealer fields_revealer; private Gtk.Revealer secondary_revealer; private Gtk.StyleContext style_context; private Hdy.Avatar avatar; @@ -45,6 +46,7 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { } set { secondary_revealer.reveal_child = value; + fields_revealer.reveal_child = value; if (value) { if (!message_loaded) { get_message.begin (); @@ -127,18 +129,19 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { var action_box = new Gtk.Box (HORIZONTAL, 6) { halign = END, - hexpand = true, - margin_top = 3 + hexpand = true }; var fields_grid = new Gtk.Grid () { column_spacing = 3, + margin_top = 3 }; - fields_grid.attach (from_label, 0, 0, 2); - fields_grid.attach (to_label, 0, 1); - fields_grid.attach (to_val_label, 1, 1); - fields_grid.attach (datetime_label, 2, 0); - fields_grid.attach (action_box, 2, 1); + fields_grid.attach (to_label, 0, 0); + fields_grid.attach (to_val_label, 1, 0); + fields_grid.attach (action_box, 2, 0); + + fields_revealer = new Gtk.Revealer (); + fields_revealer.add (fields_grid); var cc_info = message_info.cc; if (cc_info != null) { @@ -153,8 +156,8 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { xalign = 0 }; - fields_grid.attach (cc_label, 0, 2); - fields_grid.attach (cc_val_label, 1, 2); + fields_grid.attach (cc_label, 0, 1); + fields_grid.attach (cc_val_label, 1, 1); } var starred_icon = new Gtk.Image (); @@ -200,6 +203,13 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { }; actions_menu_button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT); + var header_vgrid = new Gtk.Grid () { + valign = START + }; + header_vgrid.attach (from_label, 0, 0); + header_vgrid.attach (datetime_label, 1, 0); + header_vgrid.attach (fields_revealer, 0, 1, 2); + var header = new Gtk.Box (HORIZONTAL, 12) { margin_top = 12, margin_bottom = 12, @@ -207,7 +217,7 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { margin_end = 12 }; header.add (avatar); - header.add (fields_grid); + header.add (header_vgrid); var header_event_box = new Gtk.EventBox (); header_event_box.events |= Gdk.EventMask.ENTER_NOTIFY_MASK; From 1a50ba77a178d30d89e62d1a2a13e1bc53765f6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Danielle=20For=C3=A9?= Date: Thu, 18 May 2023 12:08:04 -0700 Subject: [PATCH 7/7] valign datetime --- src/MessageList/MessageListItem.vala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/MessageList/MessageListItem.vala b/src/MessageList/MessageListItem.vala index 39d80adf2..fe156b412 100644 --- a/src/MessageList/MessageListItem.vala +++ b/src/MessageList/MessageListItem.vala @@ -123,7 +123,8 @@ public class Mail.MessageListItem : Gtk.ListBoxRow { ///TRANSLATORS: The first %s represents the date and the second %s the time of the message (either when it was received or sent) new DateTime.from_unix_utc (relevant_timestamp).to_local ().format (_("%s at %s").printf (date_format, time_format)) ) { - halign = END + halign = END, + valign = START }; datetime_label.get_style_context ().add_class (Gtk.STYLE_CLASS_DIM_LABEL);