[evolution/wip/mcrha/webkit-jsc-api] Pre-code EvoEditor.InsertSignature() and (finish) EvoEditor.ReplaceSelection()



commit 564ad2c1e6454e39ef18433ce6323d9415f2219e
Author: Milan Crha <mcrha redhat com>
Date:   Mon Jan 20 15:54:16 2020 +0100

    Pre-code EvoEditor.InsertSignature() and (finish) EvoEditor.ReplaceSelection()

 data/webkit/e-editor.js                     | 227 +++++++++++++++++++++++++++-
 src/modules/webkit-editor/e-webkit-editor.c |  55 ++-----
 2 files changed, 235 insertions(+), 47 deletions(-)
---
diff --git a/data/webkit/e-editor.js b/data/webkit/e-editor.js
index 225d8d8b07..79fc9819dd 100644
--- a/data/webkit/e-editor.js
+++ b/data/webkit/e-editor.js
@@ -3351,19 +3351,23 @@ EvoEditor.GetCaretWord = function()
        return range.toString();
 }
 
-EvoEditor.ReplaceCaretWord = function(replacement)
+EvoEditor.replaceSelectionWord = function(opType, expandWord, replacement)
 {
+       if (!expandWord && document.getSelection().isCollapsed)
+               return;
+
        if (document.getSelection().rangeCount < 1)
-               return null;
+               return;
 
        var range = document.getSelection().getRangeAt(0);
 
        if (!range)
-               return null;
+               return;
 
-       range.expand("word");
+       if (expandWord)
+               range.expand("word");
 
-       EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_EVENT, "ReplaceCaretWord", null, null, 
EvoEditor.CLAIM_CONTENT_FLAG_USE_PARENT_BLOCK_NODE | EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML);
+       EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_EVENT, opType, null, null, 
EvoEditor.CLAIM_CONTENT_FLAG_USE_PARENT_BLOCK_NODE | EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML);
        try {
                var fragment = range.extractContents(), node;
 
@@ -3375,7 +3379,7 @@ EvoEditor.ReplaceCaretWord = function(replacement)
                        ;
                }
 
-               if (node && node.nodeType == node.TEXT_NODE) {
+               if (node && node.nodeType == node.TEXT_NODE && replacement) {
                        var text;
 
                        /* Replace the word */
@@ -3387,12 +3391,22 @@ EvoEditor.ReplaceCaretWord = function(replacement)
                        document.getSelection().modify("move", "forward", "word");
                }
        } finally {
-               EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_EVENT, "ReplaceCaretWord");
+               EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_EVENT, opType);
                EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE);
                EvoEditor.EmitContentChanged();
        }
 }
 
+EvoEditor.ReplaceCaretWord = function(replacement)
+{
+       EvoEditor.replaceSelectionWord("ReplaceCaretWord", true, replacement);
+}
+
+EvoEditor.ReplaceSelection = function(replacement)
+{
+       EvoEditor.replaceSelectionWord("ReplaceSelection", false, replacement);
+}
+
 EvoEditor.SpellCheckContinue = function(fromCaret, directionNext)
 {
        var selection, storedSelection = null;
@@ -3505,8 +3519,205 @@ EvoEditor.GetCurrentSignatureUid = function()
        return "";
 }
 
-EvoEditor.InsertSignature = function(content, is_html, uid, fromMessage, checkChanged, ignoreNextChange, 
startBottom, topSignature, addDelimiter)
+EvoEditor.InsertSignature = function(content, isHTML, uid, fromMessage, checkChanged, ignoreNextChange, 
startBottom, topSignature, addDelimiter)
 {
+       var sigSpan, node;
+
+       sigSpan = document.createElement("SPAN");
+       sigSpan.className = "-x-evo-signature";
+       sigSpan.id = uid;
+
+       if (content) {
+               if (isHTML && EvoEditor.mode != EvoEditor.MODE_HTML) {
+                       node = document.createElement("SPAN");
+                       node.innerHTML = content;
+
+                       content = EvoConvert.ToPlainText(node, EvoEditor.NORMAL_PARAGRAPH_WIDTH);
+                       if (content != "") {
+                               content = "<PRE>" + content.replace(/\&/g, "&amp;").replace(/</g, 
"&lt;").replace(/>/g, "&gt;") + "</PRE>";
+                       }
+
+                       isHTML = false;
+               }
+
+               /* The signature dash convention ("-- \n") is specified
+                * in the "Son of RFC 1036", section 4.3.2.
+                * http://www.chemie.fu-berlin.de/outerspace/netnews/son-of-1036.html
+                */
+               if (addDelimiter) {
+                       var found;
+
+                       if (isHTML) {
+                               found = content.substr(0, 8).toUpperCase().startsWith("-- <BR>") || 
content.match(/\n-- <BR>/i) != null;
+                       } else {
+                               found = content.startsWith("-- \n") || content.match(/\n-- \n/i) != null;
+                       }
+
+                       /* Skip the delimiter if the signature already has one. */
+                       if (!found) {
+                               /* Always use the HTML delimiter as we are never in anything
+                                * like a strict plain text mode. */
+                               node = document.createElement("PRE");
+                               node.innerHTML = "-- <BR>";
+                               sigSpan.appendChild(node);
+                       }
+               }
+
+               sigSpan.insertAdjacentHTML("beforeend", content);
+
+               node = sigSpan.querySelector("[data-evo-signature-plain-text-mode]");
+               if (node)
+                       node.removeAttribute("[data-evo-signature-plain-text-mode]");
+
+               node = sigSpan.querySelector("#-x-evo-selection-start-marker");
+               if (node && node.parentElement)
+                       node.parentElement.removeChild(node);
+
+               node = sigSpan.querySelector("#-x-evo-selection-end-marker");
+               if (node && node.parentElement)
+                       node.parentElement.removeChild(node);
+       }
+
+       EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_GROUP, "InsertSignature");
+       try {
+               var signatures, ii, done = false, useWrapper = null;
+
+               signatures = document.getElementsByClassName("-x-evo-signature-wrapper");
+               for (ii = signatures.length; ii-- && !done;) {
+                       var wrapper, signature;
+
+                       wrapper = signatures[ii];
+                       signature = wrapper.firstElementChild;
+
+                       /* When we are editing a message with signature, we need to unset the
+                        * active signature id as if the signature in the message was edited
+                        * by the user we would discard these changes. */
+                       if (fromMessage && content && signature) {
+                               if (checkChanged) {
+                                       /* Normalize the signature that we want to insert as the one in the
+                                        * message already is normalized. */
+                                       webkit_dom_node_normalize (WEBKIT_DOM_NODE (signature_to_insert));
+                                       if (!webkit_dom_node_is_equal_node (WEBKIT_DOM_NODE 
(signature_to_insert), signature)) {
+                                               /* Signature in the body is different than the one with the
+                                                * same id, so set the active signature to None and leave
+                                                * the signature that is in the body. */
+                                               uid = "none";
+                                               ignoreNextChange = true;
+                                       }
+
+                                       checkChanged = false;
+                                       fromMessage = false;
+                               } else {
+                                       /* Old messages will have the signature id in the name attribute, 
correct it. */
+                                       if (signature.hasAttribute("name")) {
+                                               id = signature.getAttribute("name");
+                                               signature.id = id;
+                                               signature.removeAttribute(name);
+                                       } else {
+                                               id = signature.id;
+                                       }
+
+                                       /* Keep the signature and check if is it the same
+                                        * as the signature in body or the user previously
+                                        * changed it. */
+                                       checkChanged = true;
+                               }
+
+                               done = true;
+                       } else {
+                               EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, 
"InsertSignature::old-changes", wrapper, wrapper,
+                                       EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML | 
EvoEditor.CLAIM_CONTENT_FLAG_USE_PARENT_BLOCK_NODE);
+                               try {
+                                       /* If the top signature was set we have to remove the newline
+                                        * that was inserted after it */
+                                       if (topSignature) {
+                                               node = document.querySelector(".-x-evo-top-signature-spacer");
+                                               if (node && (!node.firstChild || !node.textContent ||
+                                                   (node.childNodes.length == 1 && node.firstChild.tagName 
== "BR"))) {
+                                                       if (node.parentElement)
+                                                               node.parentElement.removeChild(node);
+                                               }
+                                       }
+
+                                       /* Leave just one signature wrapper there as it will be reused. */
+                                       if (ii) {
+                                               if (wrapper.parentElement)
+                                                       wrapper.parentElement.removeChild(wrapper);
+                                       } else {
+                                               wrapper.removeChild(signature);
+                                               useWrapper = wrapper;
+                                       }
+                               } finally {
+                                       EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, 
"InsertSignature::old-changes");
+                               }
+                       }
+               }
+
+               if (!done) {
+                       if (useWrapper) {
+                               EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, 
"InsertSignature::new-changes", useWrapper, useWrapper, EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML);
+                               try {
+                                       useWrapper.appendChild(sigSpan);
+
+                                       /* Insert a spacer below the top signature */
+                                       if (topSignature && content) {
+                                               node = document.createElement("DIV");
+                                               node.appendChild(document.createElement("BR"));
+                                               node.className = "-x-evo-top-signature-spacer";
+
+                                               document.body.insertBefore(node, useWrapper.nextSibling);
+                                       }
+                               } finally {
+                                       EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, 
"InsertSignature::new-changes");
+                               }
+                       } else {
+                               useWrapper = document.createElement("DIV");
+                               useWrapper.className = "-x-evo-signature-wrapper";
+                               useWrapper.appendChild(sigSpan);
+
+                               EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, 
"InsertSignature::new-changes", document.body, document.body, EvoEditor.CLAIM_CONTENT_FLAG_SAVE_HTML);
+                               try {
+                                       if (topSignature) {
+                                               document.body.insertBefore(useWrapper, 
document.body.firstChild);
+
+                                               node = document.createElement("DIV");
+                                               node.appendChild(document.createElement("BR"));
+                                               node.className = "-x-evo-top-signature-spacer";
+
+                                               document.body.insertBefore(node, useWrapper.nextSibling);
+                                       } else {
+                                               document.body.appendChild(useWrapper);
+                                       }
+                               } finally {
+                                       EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, 
"InsertSignature::new-changes");
+                               }
+                       }
+
+                       fromMessage = false;
+
+                       // Position the caret and scroll to it
+                       if (startBottom) {
+                               if (topSignature) {
+                                       document.getSelection().setPosition(document.body.lastChild, 0);
+                               } else if (useWrapper.previousSibling) {
+                                       document.getSelection().setPosition(useWrapper.previousSibling, 0);
+                               } else {
+                                       document.getSelection().setPosition(useWrapper, 0);
+                               }
+                       } else {
+                               document.getSelection().setPosition(document.body.firstChild, 0);
+                       }
+
+                       node = document.getSelection().baseNode;
+
+                       if (node) {
+                               node.scrollIntoViewIfNeeded();
+                       }
+               }
+       } finally {
+               EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_GROUP, "InsertSignature");
+       }
+
        var res = [];
 
        res["fromMessage"] = fromMessage;
diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c
index cd49e51f3f..79af858b8d 100644
--- a/src/modules/webkit-editor/e-webkit-editor.c
+++ b/src/modules/webkit-editor/e-webkit-editor.c
@@ -2710,10 +2710,17 @@ webkit_editor_insert_signature (EContentEditor *editor,
                                 gboolean *ignore_next_signature_change)
 {
        JSCValue *jsc_value;
-       gchar *res = NULL;
+       gchar *res = NULL, *tmp = NULL;
 
        g_return_val_if_fail (E_IS_WEBKIT_EDITOR (editor), NULL);
 
+       if (!is_html && content && *content) {
+               tmp = camel_text_to_html (content, CAMEL_MIME_FILTER_TOHTML_PRE, 0);
+
+               if (tmp)
+                       content = tmp;
+       }
+
        jsc_value = webkit_editor_call_jsc_sync (E_WEBKIT_EDITOR (editor),
                "EvoEditor.InsertSignature(%s, %x, %s, %x, %x, %x, %x, %x, %x);",
                content ? content : "",
@@ -2726,6 +2733,8 @@ webkit_editor_insert_signature (EContentEditor *editor,
                e_webkit_editor_three_state_to_bool (e_content_editor_get_top_signature (editor), 
"composer-top-signature"),
                !e_webkit_editor_three_state_to_bool (E_THREE_STATE_INCONSISTENT, 
"composer-no-signature-delim"));
 
+       g_free (tmp);
+
        if (jsc_value) {
                *set_signature_from_message = e_web_view_jsc_get_object_property_boolean (jsc_value, 
"fromMessage", FALSE);
                *check_if_signature_is_changed = e_web_view_jsc_get_object_property_boolean (jsc_value, 
"checkChanged", FALSE);
@@ -2815,22 +2824,13 @@ webkit_editor_replace (EContentEditor *editor,
                        const gchar *replacement)
 {
        EWebKitEditor *wk_editor;
-       GVariant *result;
 
-       wk_editor = E_WEBKIT_EDITOR (editor);
-       if (!wk_editor->priv->web_extension_proxy) {
-               printf ("EHTMLEditorWebExtension not ready at %s!\n", G_STRFUNC);
-               return;
-       }
+       g_return_if_fail (E_IS_WEBKIT_EDITOR (editor));
 
-       result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-               wk_editor->priv->web_extension_proxy,
-               "DOMSelectionReplace",
-               g_variant_new ("(ts)", current_page_id (wk_editor), replacement),
-               wk_editor->priv->cancellable);
+       wk_editor = E_WEBKIT_EDITOR (editor);
 
-       if (result)
-               g_variant_unref (result);
+       e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (wk_editor), wk_editor->priv->cancellable,
+               "EvoEditor.ReplaceSelection(%s);", replacement);
 }
 
 static gboolean
@@ -2855,11 +2855,8 @@ webkit_find_controller_found_text_cb (WebKitFindController *find_controller,
                /* Repeatedly search for 'word', then replace selection by
                 * 'replacement'. Repeat until there's at least one occurrence of
                 * 'word' in the document */
-               e_util_invoke_g_dbus_proxy_call_with_error_check (
-                       wk_editor->priv->web_extension_proxy,
-                       "DOMSelectionReplace",
-                       g_variant_new ("(ts)", current_page_id (wk_editor), wk_editor->priv->replace_with),
-                       wk_editor->priv->cancellable);
+               e_web_view_jsc_run_script (WEBKIT_WEB_VIEW (wk_editor), wk_editor->priv->cancellable,
+                       "EvoEditor.ReplaceSelection(%s);", wk_editor->priv->replace_with);
 
                g_idle_add ((GSourceFunc) search_next_on_idle, wk_editor);
        } else {
@@ -2876,26 +2873,6 @@ webkit_find_controller_failed_to_find_text_cb (WebKitFindController *find_contro
        if (wk_editor->priv->performing_replace_all) {
                guint replaced_count = wk_editor->priv->replaced_count;
 
-               if (replaced_count > 0) {
-                       if (!wk_editor->priv->web_extension_proxy) {
-                               printf ("EHTMLEditorWebExtension not ready at %s!\n", G_STRFUNC);
-                       } else {
-                               GVariant *result;
-
-                               result = e_util_invoke_g_dbus_proxy_call_sync_wrapper_with_error_check (
-                                       wk_editor->priv->web_extension_proxy,
-                                       "DOMInsertReplaceAllHistoryEvent",
-                                       g_variant_new ("(tss)",
-                                               current_page_id (wk_editor),
-                                               webkit_find_controller_get_search_text (find_controller),
-                                               wk_editor->priv->replace_with),
-                                       NULL);
-
-                               if (result)
-                                       g_variant_unref (result);
-                       }
-               }
-
                webkit_editor_finish_search (wk_editor);
                e_content_editor_emit_replace_all_done (E_CONTENT_EDITOR (wk_editor), replaced_count);
        } else {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]