From 69a53d9db9af4a73b68bf2d656fe41d291d23c3b Mon Sep 17 00:00:00 2001 From: Michael James Gratton Date: Tue, 12 Apr 2016 01:06:09 +1000 Subject: [PATCH] Reenable and update code for embedded message composer. The embedded composer is now added to the the conversation list box. Still needs some work to fix focus and scrolling issues, also to insert the composer in the right place in the list. * src/client/components/main-window.vala (MainWindow::set_styling): Adjust theme CSS to make padding around embedded coposer not so terrible. Fix style for embedded headerbar. * src/client/composer/composer-embed.vala: Don't attempt to up-manage it's parent's state, since the parent has a much better idea of how best to do that. Instead of passing in a ConversationViewer, just pass in a Gtk.ScrolledWindow that needs to be adjusted as the embededded editor and add some signals needed by the ConversationViewer. Reenabled some code needed to get scroll event passthrough working. * src/client/conversation-viewer/conversation-viewer.vala: Remove old embedded composer code. Adjust conversation_listbox callbacks to handle the embedded composer being present. (ConversationViewer::get_selected_message): Fixed to actually return a message. (ConversationViewer::do_embedded_composer): New method to set up an embedded composer. * src/client/application/geary-controller.vala (GearyController::create_compose_widget_async): Call new ConversationViewer::do_embedded_composer to let it set up a new embedded composer when needed. --- src/client/application/geary-controller.vala | 7 +- src/client/composer/composer-box.vala | 4 - src/client/composer/composer-embed.vala | 101 ++++++------------ .../conversation-viewer.vala | 57 +++++++--- ui/geary.css | 11 +- 5 files changed, 90 insertions(+), 90 deletions(-) diff --git a/src/client/application/geary-controller.vala b/src/client/application/geary-controller.vala index e12ae46c..153126d3 100644 --- a/src/client/application/geary-controller.vala +++ b/src/client/application/geary-controller.vala @@ -2166,10 +2166,11 @@ public class GearyController : Geary.BaseObject { if (inline) { if (widget.state == ComposerWidget.ComposerState.NEW || - widget.state == ComposerWidget.ComposerState.PANED) + widget.state == ComposerWidget.ComposerState.PANED) { main_window.conversation_viewer.do_compose(widget); - else - new ComposerEmbed(widget, main_window.conversation_viewer, referred); // is_draft + } else { + main_window.conversation_viewer.do_embedded_composer(widget, referred); + } } else { new ComposerWindow(widget); widget.state = ComposerWidget.ComposerState.DETACHED; diff --git a/src/client/composer/composer-box.vala b/src/client/composer/composer-box.vala index 957b939b..496c5d37 100644 --- a/src/client/composer/composer-box.vala +++ b/src/client/composer/composer-box.vala @@ -18,12 +18,8 @@ public class ComposerBox : Gtk.Frame, ComposerContainer { public Gtk.ApplicationWindow top_window { get { return (Gtk.ApplicationWindow) get_toplevel(); } - - public Gtk.Window top_window { - get { return (Gtk.Window) get_toplevel(); } } - public signal void vanished(); diff --git a/src/client/composer/composer-embed.vala b/src/client/composer/composer-embed.vala index 19acab5d..74416379 100644 --- a/src/client/composer/composer-embed.vala +++ b/src/client/composer/composer-embed.vala @@ -12,57 +12,43 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { private const int MIN_EDITOR_HEIGHT = 200; - private ConversationViewer conversation_viewer; - - // The id of the composer HTML element - private string embed_id; - private bool setting_inner_scroll; - private bool scrolled_to_bottom = false; - //private double inner_scroll_adj_value; - private int inner_view_height; - private int min_height = MIN_EDITOR_HEIGHT; - - protected ComposerWidget composer { get; set; } - - protected Gee.MultiMap? old_accelerators { get; set; } + public Geary.Email referred { get; private set; } public Gtk.ApplicationWindow top_window { get { return (Gtk.ApplicationWindow) get_toplevel(); } } - public ComposerEmbed(ComposerWidget composer, ConversationViewer conversation_viewer, - Geary.Email referred) { + protected ComposerWidget composer { get; set; } + + protected Gee.MultiMap? old_accelerators { get; set; } + + private Gtk.ScrolledWindow outer_scroller; + private bool setting_inner_scroll; + private bool scrolled_to_bottom = false; + private double inner_scroll_adj_value; + private int inner_view_height; + private int min_height = MIN_EDITOR_HEIGHT; + + + public signal void loaded(); + public signal void vanished(); + + + public ComposerEmbed(Geary.Email referred, + ComposerWidget composer, + Gtk.ScrolledWindow outer_scroller) { + this.referred = referred; this.composer = composer; - this.conversation_viewer = conversation_viewer; + this.outer_scroller = outer_scroller; this.halign = Gtk.Align.FILL; this.valign = Gtk.Align.FILL; - WebKit.DOM.HTMLElement? email_element = null; - // email_element = conversation_viewer.web_view.get_dom_document().get_element_by_id( - // conversation_viewer.get_div_id(referred.id)) as WebKit.DOM.HTMLElement; - // embed_id = referred.id.to_string() + "_reply"; - // if (email_element == null) { - // warning("Embedded composer could not find email to follow."); - // email_element = conversation_viewer.web_view.get_dom_document().get_element_by_id( - // "placeholder") as WebKit.DOM.HTMLElement; - // } - - try { - email_element.insert_adjacent_html("afterend", - @"
"); - } catch (Error error) { - debug("Error creating embed element: %s", error.message); - return; - } - add(composer); realize.connect(on_realize); this.composer.editor.focus_in_event.connect(on_focus_in); this.composer.editor.focus_out_event.connect(on_focus_out); this.composer.editor.document_load_finished.connect(on_loaded); - this.conversation_viewer.compose_overlay.add_overlay(this); show(); - present(); } private void on_realize() { @@ -86,7 +72,7 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { } Idle.add(() => { recalc_height(); - conversation_viewer.compose_overlay.queue_resize(); + loaded(); return false; }); } @@ -190,12 +176,12 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { } private void on_inner_scroll(Gtk.Adjustment adj) { - // double delta = adj.value - this.inner_scroll_adj_value; - // this.inner_scroll_adj_value = adj.value; - // if (delta != 0 && !setting_inner_scroll) { - // Gtk.Adjustment outer_adj = this.conversation_viewer.web_view.vadjustment; - // outer_adj.set_value(outer_adj.value + delta); - // } + double delta = adj.value - this.inner_scroll_adj_value; + this.inner_scroll_adj_value = adj.value; + if (delta != 0 && !this.setting_inner_scroll) { + Gtk.Adjustment outer_adj = outer_scroller.vadjustment; + this.outer_adj.set_value(outer_adj.value + delta); + } } private void on_adjust_changed(Gtk.Adjustment adj) { @@ -225,30 +211,21 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { if (view_height != inner_view_height || min_height != base_height + MIN_EDITOR_HEIGHT) { this.inner_view_height = view_height; this.min_height = base_height + MIN_EDITOR_HEIGHT; + // Calculate height widget should be to avoid scrolling in editor - // int widget_height = int.max(view_height + base_height - 2, min_height); //? about 2 - // WebKit.DOM.Element embed = this.conversation_viewer.web_view - // .get_dom_document().get_element_by_id(this.embed_id); - // if (embed != null) { - // try { - // embed.style.set_property("height", @"$widget_height", ""); - // } catch (Error error) { - // debug("Error setting height of composer widget"); - // } - // } + int widget_height = int.max(view_height + base_height - 2, min_height); //? about 2 + set_size_request(-1, widget_height); } return false; } private bool on_inner_scroll_event(Gdk.EventScroll event) { - //this.conversation_viewer.web_view.scroll_event(event); + this.outer_scroller.scroll_event(event); return true; } public void present() { - this.top_window.present(); - // this.conversation_viewer.web_view.get_dom_document().get_element_by_id(this.embed_id) - // .scroll_into_view_if_needed(false); + top_window.present(); } public void vanish() { @@ -256,20 +233,12 @@ public class ComposerEmbed : Gtk.EventBox, ComposerContainer { this.composer.state = ComposerWidget.ComposerState.DETACHED; this.composer.editor.focus_in_event.disconnect(on_focus_in); this.composer.editor.focus_out_event.disconnect(on_focus_out); - - // WebKit.DOM.Element embed = this.conversation_viewer.web_view.get_dom_document(). - // get_element_by_id(this.embed_id); - // try{ - // embed.parent_element.remove_child(embed); - // } catch (Error error) { - // warning("Could not remove embed from WebView: %s", error.message); - // } + vanished(); } public void close_container() { if (visible) vanish(); - this.conversation_viewer.compose_overlay.remove(this); } } diff --git a/src/client/conversation-viewer/conversation-viewer.vala b/src/client/conversation-viewer/conversation-viewer.vala index 96cf2758..4712b649 100644 --- a/src/client/conversation-viewer/conversation-viewer.vala +++ b/src/client/conversation-viewer/conversation-viewer.vala @@ -86,9 +86,6 @@ public class ConversationViewer : Gtk.Stack { // Current conversation, or null if none. public Geary.App.Conversation? current_conversation = null; - // Overlay containing any inline composers. - public ScrollableOverlay compose_overlay; - // Stack pages [GtkChild] private Gtk.Image splash_page; @@ -135,13 +132,23 @@ public class ConversationViewer : Gtk.Stack { public ConversationViewer() { // Setup the conversation list box conversation_listbox.set_sort_func((row1, row2) => { - return Geary.Email.compare_sent_date_ascending( - ((ConversationMessage) row1.get_child()).email, - ((ConversationMessage) row2.get_child()).email - ); + // If not a ConversationMessage, will be an + // embedded composer and should always be last. + ConversationMessage? msg1 = row1.get_child() as ConversationMessage; + if (msg1 == null) { + return 1; + } + ConversationMessage? msg2 = row2.get_child() as ConversationMessage; + if (msg2 == null) { + return -1; + } + return Geary.Email.compare_sent_date_ascending(msg1.email, msg2.email); }); conversation_listbox.row_activated.connect((box, row) => { - if (email_to_row.size > 1) { + // If not a ConversationMessage, will be an + // 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); } }); @@ -171,9 +178,6 @@ public class ConversationViewer : Gtk.Stack { GearyApplication.instance.controller.folder_selected.connect(on_folder_selected); GearyApplication.instance.controller.conversation_count_changed.connect(on_conversation_count_changed); - //compose_overlay = new ScrollableOverlay(web_view); - //conversation_viewer_scrolled.add(compose_overlay); - //conversation_find_bar = new ConversationFindBar(web_view); //conversation_find_bar.no_show_all = true; //conversation_find_bar.close.connect(() => { fsm.issue(SearchEvent.CLOSE_FIND_BAR); }); @@ -187,9 +191,10 @@ public class ConversationViewer : Gtk.Stack { } public Geary.Email? get_selected_message(out string? quote) { - // XXX - quote = ""; - return null; + // XXX check to see if there is a message with selected text, + // if so return that + quote = null; + return messages.is_empty ? null : messages.last(); } public void check_mark_read() { @@ -270,6 +275,30 @@ public class ConversationViewer : Gtk.Stack { set_visible_child(composer_page); } + public void do_embedded_composer(ComposerWidget composer, Geary.Email referred) { + state = ViewState.CONVERSATION; + + ComposerEmbed embed = new ComposerEmbed( + referred, composer, conversation_page + ); + 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("frame"); + row.show(); + row.add(embed); + conversation_listbox.add(row); + + embed.loaded.connect((box) => { + row.grab_focus(); + }); + embed.vanished.connect((box) => { + conversation_listbox.remove(row); + }); + + } + // Removes all displayed e-mails from the view. private void clear() { foreach (Gtk.Widget child in conversation_listbox.get_children()) { diff --git a/ui/geary.css b/ui/geary.css index 5ccd07fa..5d85843b 100644 --- a/ui/geary.css +++ b/ui/geary.css @@ -58,7 +58,7 @@ row.geary-folder-popover-list-row > label { } #conversation_listbox { - padding: 18px 18px 0; + padding: 18px 18px calc(18px/2); } #conversation_listbox > row { margin: 0; @@ -67,8 +67,9 @@ row.geary-folder-popover-list-row > label { box-shadow: 0 4px 8px 1px rgba(0,0,0,0.4); transition: margin 0.1s; } -#conversation_listbox > row.show-message { - margin-bottom: 18px; +#conversation_listbox > row.show-message, +#conversation_listbox > row.composer { + margin-bottom: calc(18px/2); border-bottom-width: 1px; } @@ -81,3 +82,7 @@ row.geary-folder-popover-list-row > label { #ConversationMessage separator { margin: 12px 0; } + +#composer_embed headerbar { + border-radius: 0px; +}