Tidy up ConversationMessage styling and state management.

* src/client/components/main-window.vala: Adjust theme CSS style to
  account for new widget classes. Fix style for last row in the convo
  listbox.

* src/client/conversation-viewer/conversation-message.vala: Decouple
  updating message state and updating message flags. Prefix CSS classes
  with "geary_" to prevent class name clashes.

* src/client/conversation-viewer/conversation-viewer.vala: Manually
  maintain a CSS class on the last row of the convo listbox to work
  around Bug 764710. Prefix CSS classes with "geary_" to prevent class
  name clashes.
  (ConversationViewer::on_update_flags): Renamed from update_flags since
  it is only ever called as a signal handler. Remove most of the work -
  it is now done by ConversationMessage.
This commit is contained in:
Michael James Gratton 2016-04-16 23:59:19 +10:00
parent 0a4611a3f4
commit 9e7fee035a
3 changed files with 78 additions and 64 deletions

View file

@ -57,6 +57,9 @@ public class ConversationMessage : Gtk.Box {
// The allocation for the web view
public Gdk.Rectangle web_view_allocation { get; private set; }
// Is the message body shown or not?
public bool is_message_body_visible = false;
// Has the message body been been fully loaded?
public bool is_loading_complete = false;
@ -235,15 +238,12 @@ public class ConversationMessage : Gtk.Box {
// }
// }
update_flags(email);
update_message_state(false);
}
public bool is_message_visible() {
return get_style_context().has_class("show-message");
}
public void show_message(bool include_transitions=true) {
get_style_context().add_class("show-message");
public void show_message_body(bool include_transitions=true) {
is_message_body_visible = true;
get_style_context().add_class("geary_show_body");
avatar_image.set_pixel_size(32); // XXX constant
Gtk.RevealerTransitionType revealer = preview_revealer.get_transition_type();
@ -264,7 +264,6 @@ public class ConversationMessage : Gtk.Box {
unstar_button.set_sensitive(true);
message_menubutton.set_sensitive(true);
// XXX this is pretty gross
revealer = body_revealer.get_transition_type();
if (!include_transitions) {
body_revealer.set_transition_type(Gtk.RevealerTransitionType.NONE);
@ -273,8 +272,9 @@ public class ConversationMessage : Gtk.Box {
body_revealer.set_transition_type(revealer);
}
public void hide_message() {
get_style_context().remove_class("show-message");
public void hide_message_body() {
is_message_body_visible = false;
get_style_context().remove_class("geary_show_body");
avatar_image.set_pixel_size(24); // XXX constant
preview_revealer.set_reveal_child(true);
header_revealer.set_reveal_child(false);
@ -379,11 +379,20 @@ public class ConversationMessage : Gtk.Box {
return menu;
}
public void update_flags(Geary.Email email) {
this.email.set_flags(email.email_flags);
update_message_state();
}
public bool is_manual_read() {
return get_style_context().has_class("geary_manual_read");
}
public void update_flags(Geary.Email email) {
public void mark_manual_read() {
get_style_context().add_class("geary_manual_read");
}
private void update_message_state(bool include_transitions=true) {
Geary.EmailFlags flags = email.email_flags;
Gtk.StyleContext style = get_style_context();
@ -409,10 +418,6 @@ public class ConversationMessage : Gtk.Box {
// Geary.SpecialFolderType.SENT.get_display_name()));
}
public void mark_manual_read() {
get_style_context().add_class("manual_read");
}
private void load_message_body() {
bool load_images = false;
string? body_text = null;

View file

@ -101,6 +101,7 @@ public class ConversationViewer : Gtk.Stack {
// Conversation messages list
[GtkChild]
private Gtk.ListBox conversation_listbox;
private Gtk.Widget? last_list_row;
// Label for displaying messages in the main pane.
[GtkChild]
@ -148,7 +149,11 @@ public class ConversationViewer : Gtk.Stack {
// embedded composer and should not be activated.
ConversationMessage? msg = row.get_child() as ConversationMessage;
if (email_to_row.size > 1 && msg != null) {
toggle_show_message(row);
if (msg.is_message_body_visible) {
hide_message(row);
} else {
show_message(row);
}
}
});
conversation_listbox.realize.connect(() => {
@ -156,6 +161,24 @@ public class ConversationViewer : Gtk.Stack {
.value_changed.connect(check_mark_read);
});
conversation_listbox.size_allocate.connect(check_mark_read);
conversation_listbox.add.connect((widget) => {
// Due to Bug 764710, we can only use the CSS
// :last-child selector for GTK themes after 3.20.3,
// so for now manually maintain a class on the last
// box in the convo listbox so we can emulate it.
Gtk.Widget current_last_row =
conversation_listbox.get_children().last().data;;
if (last_list_row != current_last_row) {
if (last_list_row != null) {
last_list_row.get_style_context().remove_class("geary_last");
}
last_list_row = current_last_row;
last_list_row.get_style_context().add_class("geary_last");
}
});
// Setup state machine for search/find states.
Geary.State.Mapping[] mappings = {
@ -308,7 +331,7 @@ public class ConversationViewer : Gtk.Stack {
embed.set_property("name", "composer_embed"); // Bug 764622
Gtk.ListBoxRow row = new Gtk.ListBoxRow();
row.get_style_context().add_class("composer");
row.get_style_context().add_class("geary_composer");
row.show();
row.add(embed);
conversation_listbox.add(row);
@ -377,7 +400,7 @@ public class ConversationViewer : Gtk.Stack {
if (current_conversation != null) {
current_conversation.appended.disconnect(on_conversation_appended);
current_conversation.trimmed.disconnect(on_conversation_trimmed);
current_conversation.email_flags_changed.disconnect(update_flags);
current_conversation.email_flags_changed.disconnect(on_update_flags);
current_conversation = null;
}
@ -430,7 +453,7 @@ public class ConversationViewer : Gtk.Stack {
current_conversation.appended.connect(on_conversation_appended);
current_conversation.trimmed.connect(on_conversation_trimmed);
current_conversation.email_flags_changed.connect(update_flags);
current_conversation.email_flags_changed.connect(on_update_flags);
GearyApplication.instance.controller.enable_message_buttons(true);
}
@ -617,7 +640,7 @@ public class ConversationViewer : Gtk.Stack {
ConversationMessage message = new ConversationMessage(email, current_folder);
message.link_selected.connect((link) => { link_selected(link); });
message.web_view.button_release_event.connect_after((event) => {
message.body_box.button_release_event.connect_after((event) => {
// Consume all non-consumed clicks so the row is not
// inadvertently activated after clicking on the
// message body.
@ -627,11 +650,10 @@ public class ConversationViewer : Gtk.Stack {
Gtk.ListBoxRow row = new Gtk.ListBoxRow();
row.show();
row.add(message);
email_to_row.set(email.id, row);
conversation_listbox.add(row);
email_to_row.set(email.id, row);
if (email.is_unread() == Geary.Trillian.TRUE) {
show_message(row, false);
}
@ -648,52 +670,23 @@ public class ConversationViewer : Gtk.Stack {
}
private void show_message(Gtk.ListBoxRow row, bool include_transitions=true) {
row.get_style_context().add_class("show-message");
((ConversationMessage) row.get_child()).show_message(include_transitions);
row.get_style_context().add_class("geary_expand");
((ConversationMessage) row.get_child()).show_message_body(include_transitions);
}
private void hide_message(Gtk.ListBoxRow row) {
row.get_style_context().remove_class("show-message");
((ConversationMessage) row.get_child()).hide_message();
}
private void toggle_show_message(Gtk.ListBoxRow row) {
if (row.get_style_context().has_class("show-message")) {
hide_message(row);
} else {
show_message(row);
}
row.get_style_context().remove_class("geary_expand");
((ConversationMessage) row.get_child()).hide_message_body();
}
private void compress_emails() {
conversation_listbox.get_style_context().add_class("compressed");
conversation_listbox.get_style_context().add_class("geary_compressed");
}
//private void decompress_emails() {
// conversation_listbox.get_style_context().remove_class("compressed");
// conversation_listbox.get_style_context().remove_class("geary_compressed");
//}
private void update_flags(Geary.Email email) {
// Nothing to do if we aren't displaying this email.
if (!email_to_row.has_key(email.id)) {
return;
}
Geary.EmailFlags flags = email.email_flags;
// Update the flags in our message set.
foreach (Geary.Email message in messages) {
if (message.id.equal_to(email.id)) {
message.set_flags(flags);
break;
}
}
// Get the convo message and update its state.
Gtk.ListBoxRow row = email_to_row.get(email.id);
((ConversationMessage) row.get_child()).update_flags(email);
}
public void show_find_bar() {
fsm.issue(SearchEvent.OPEN_FIND_BAR);
conversation_find_bar.focus_entry();
@ -706,6 +699,17 @@ public class ConversationViewer : Gtk.Stack {
conversation_find_bar.find(forward);
}
private void on_update_flags(Geary.Email email) {
// Nothing to do if we aren't displaying this email.
if (!email_to_row.has_key(email.id)) {
return;
}
// Get the convo message and update its state.
Gtk.ListBoxRow row = email_to_row.get(email.id);
((ConversationMessage) row.get_child()).update_flags(email);
}
// State reset.
private uint on_reset(uint state, uint event, void *user, Object? object) {
//web_view.set_highlight_text_matches(false);

View file

@ -58,27 +58,32 @@ row.geary-folder-popover-list-row > label {
}
#conversation_listbox {
padding: 18px 18px calc(18px/2);
padding: 18px;
}
#conversation_listbox > row {
margin: 0;
border: 1px solid @borders;
border-bottom-width: 0;
padding: 0;
background: shade(@theme_base_color, 0.96);
box-shadow: 0 4px 8px 1px rgba(0,0,0,0.4);
transition: margin 0.1s, background 0.15s;
}
#conversation_listbox > row > box {
background: shade(@theme_base_color, 0.96);
}
#conversation_listbox > row:hover,
#conversation_listbox > row.show-message,
#conversation_listbox > row.show-message:hover {
#conversation_listbox > row > box.geary_show_body,
#conversation_listbox > row:hover > box.geary_show_body {
background: @theme_base_color;
}
#conversation_listbox > row.show-message,
#conversation_listbox > row.composer {
margin-bottom: calc(18px/2);
#conversation_listbox > row.geary_expand,
#conversation_listbox > row.geary_composer {
margin-bottom: 18px;
border-bottom-width: 1px;
}
#conversation_listbox > row.geary_last {
margin-bottom: 0;
}
#ConversationMessage {
padding: 12px;