[geary/wip/728002-webkit2] Stop the insert link popover being dismissed when selecting text.
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/728002-webkit2] Stop the insert link popover being dismissed when selecting text.
- Date: Sun, 29 Jan 2017 14:02:21 +0000 (UTC)
commit ee5b030cdea449095af673ab292e969b2d834760
Author: Michael James Gratton <mike vee net>
Date: Mon Jan 30 00:23:49 2017 +1100
Stop the insert link popover being dismissed when selecting text.
* src/client/composer/composer-web-view.vala (ComposerWebView): Add
::save_selection and ::free_selection to allow the selection to be
saved when inserting a link. Thunk calls to JS.
(ComposerWebView::insert_link): Add selection id param, pass through to
JS.
* src/client/composer/composer-widget.vala
(ComposerWidget::new_link_popover): Manage saving the editor's
selection, passing its id when inserting a link, freeing it
again. Convert into an async method so we can wait for the selection id
to get back from the WebProcess, update call sites.
(ComposerWidget::on_insert_link): Disconnect and reconnect selection
changed signal so the popover isn't dismissed when the selection does
change/
* ui/composer-web-view.js (ComposerPageState): Implement new
::saveSelection, ::freeSelection and selectionId param on ::insertLink.
src/client/composer/composer-web-view.vala | 26 ++++++++++-
src/client/composer/composer-widget.vala | 65 ++++++++++++++++++++-------
ui/composer-web-view.js | 26 ++++++------
3 files changed, 85 insertions(+), 32 deletions(-)
---
diff --git a/src/client/composer/composer-web-view.vala b/src/client/composer/composer-web-view.vala
index d76479c..f86b0e4 100644
--- a/src/client/composer/composer-web-view.vala
+++ b/src/client/composer/composer-web-view.vala
@@ -253,6 +253,25 @@ public class ComposerWebView : ClientWebView {
}
/**
+ * Saves the current text selection so it can be restored later.
+ *
+ * Returns an id to be used to refer to the selection in
+ * subsequent calls.
+ */
+ public async string save_selection() throws Error {
+ return WebKitUtil.to_string(
+ yield call(Geary.JS.callable("geary.saveSelection"), null)
+ );
+ }
+
+ /**
+ * Removes a saved selection.
+ */
+ public void free_selection(string id) {
+ this.call.begin(Geary.JS.callable("geary.freeSelection").string(id), null);
+ }
+
+ /**
* Cuts selected content and sends it to the clipboard.
*/
public void cut_clipboard() {
@@ -354,8 +373,11 @@ public class ComposerWebView : ClientWebView {
* will be updated, else if some text is selected, an A element
* will be inserted wrapping the selection.
*/
- public void insert_link(string href) {
- this.call.begin(Geary.JS.callable("geary.insertLink").string(href), null);
+ public void insert_link(string href, string selection_id) {
+ this.call.begin(
+ Geary.JS.callable("geary.insertLink").string(href).string(selection_id),
+ null
+ );
}
/**
diff --git a/src/client/composer/composer-widget.vala b/src/client/composer/composer-widget.vala
index 215fc07..94c4c50 100644
--- a/src/client/composer/composer-widget.vala
+++ b/src/client/composer/composer-widget.vala
@@ -503,7 +503,7 @@ public class ComposerWidget : Gtk.EventBox {
this.editor.key_press_event.connect(on_editor_key_press_event);
this.editor.load_changed.connect(on_load_changed);
this.editor.mouse_target_changed.connect(on_mouse_target_changed);
- this.editor.selection_changed.connect((has_selection) => { update_cursor_actions(); });
+ this.editor.selection_changed.connect(on_selection_changed);
// Place the message area before the compose toolbar in the focus chain, so that
// the user can tab directly from the Subject: field to the message area.
@@ -2098,15 +2098,22 @@ public class ComposerWidget : Gtk.EventBox {
return account_sig;
}
- private ComposerLinkPopover new_link_popover(ComposerLinkPopover.Type type,
- string url) {
+ private async ComposerLinkPopover new_link_popover(ComposerLinkPopover.Type type,
+ string url) {
+ var selection_id = "";
+ try {
+ selection_id = yield this.editor.save_selection();
+ } catch (Error err) {
+ debug("Error saving selection: %s", err.message);
+ }
ComposerLinkPopover popover = new ComposerLinkPopover(type);
popover.set_link_url(url);
- popover.hide.connect(() => {
+ popover.closed.connect(() => {
+ this.editor.free_selection(selection_id);
Idle.add(() => { popover.destroy(); return Source.REMOVE; });
});
popover.link_activate.connect((link_uri) => {
- this.editor.insert_link(popover.link_uri);
+ this.editor.insert_link(popover.link_uri, selection_id);
});
popover.link_delete.connect(() => {
this.editor.delete_link();
@@ -2161,13 +2168,14 @@ public class ComposerWidget : Gtk.EventBox {
location.x = (int) button.x;
location.y = (int) button.y;
- ComposerLinkPopover popover = new_link_popover(
- ComposerLinkPopover.Type.EXISTING_LINK,
- this.pointer_url
- );
- popover.set_relative_to(this.editor);
- popover.set_pointing_to(location);
- popover.show();
+ this.new_link_popover.begin(
+ ComposerLinkPopover.Type.EXISTING_LINK, this.pointer_url,
+ (obj, res) => {
+ ComposerLinkPopover popover = this.new_link_popover.end(res);
+ popover.set_relative_to(this.editor);
+ popover.set_pointing_to(location);
+ popover.show();
+ });
}
return Gdk.EVENT_PROPAGATE;
}
@@ -2253,15 +2261,38 @@ public class ComposerWidget : Gtk.EventBox {
}
private void on_insert_link(SimpleAction action, Variant? param) {
- ComposerLinkPopover popover = this.cursor_url == null
- ? new_link_popover(ComposerLinkPopover.Type.NEW_LINK, "http://")
- : new_link_popover(ComposerLinkPopover.Type.EXISTING_LINK, this.cursor_url);
- popover.set_relative_to(this.insert_link_button);
- popover.show();
+ ComposerLinkPopover.Type type = ComposerLinkPopover.Type.NEW_LINK;
+ string url = "http://";
+ if (this.cursor_url != null) {
+ type = ComposerLinkPopover.Type.EXISTING_LINK;
+ url = this.cursor_url;
+ }
+
+ this.new_link_popover.begin(type, url, (obj, res) => {
+ ComposerLinkPopover popover = this.new_link_popover.end(res);
+
+ // We have to disconnect then reconnect the selection
+ // changed signal for the duration of the popover
+ // being active since if the user selects the text in
+ // the URL entry, then the editor will lose its
+ // selection, the inset link action will become
+ // disabled, and the popover will disappear
+ this.editor.selection_changed.disconnect(on_selection_changed);
+ popover.closed.connect(() => {
+ this.editor.selection_changed.connect(on_selection_changed);
+ });
+
+ popover.set_relative_to(this.insert_link_button);
+ popover.show();
+ });
}
private void on_open_inspector(SimpleAction action, Variant? param) {
this.editor.get_inspector().show();
}
+ private void on_selection_changed(bool has_selection) {
+ update_cursor_actions();
+ }
+
}
diff --git a/ui/composer-web-view.js b/ui/composer-web-view.js
index 7c7b612..db75ca1 100644
--- a/ui/composer-web-view.js
+++ b/ui/composer-web-view.js
@@ -26,12 +26,11 @@ ComposerPageState.prototype = {
__proto__: PageState.prototype,
init: function() {
PageState.prototype.init.apply(this, []);
-
this.messageBody = null;
-
this.undoEnabled = false;
this.redoEnabled = false;
-
+ this.selections = new Map();
+ this.nextSelectionId = 0;
this.cursorContext = null;
let state = this;
@@ -138,21 +137,22 @@ ComposerPageState.prototype = {
document.execCommand("redo", false, null);
this.checkCommandStack();
},
- insertLink: function(href) {
+ saveSelection: function() {
+ let id = ++this.nextSelectionId.toString();
+ this.selections.set(id, SelectionUtil.save());
+ return id;
+ },
+ freeSelection: function(id) {
+ this.selections.delete(id);
+ },
+ insertLink: function(href, selectionId) {
if (!window.getSelection().isCollapsed) {
// There is currently a selection, so assume the user
// knows what they are doing and just linkify it.
document.execCommand("createLink", false, href);
} else {
- let selected = SelectionUtil.getCursorElement();
- if (selected != null && selected.tagName == "A") {
- // The current cursor element is an A, so select it
- // since createLink requires a range
- let selection = SelectionUtil.save();
- SelectionUtil.selectNode(selected);
- document.execCommand("createLink", false, href);
- SelectionUtil.restore(selection);
- }
+ SelectionUtil.restore(this.selections.get(selectionId));
+ document.execCommand("createLink", false, href);
}
},
deleteLink: function() {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]