From 9d545004cb8d28845cfa77f2bd1a61626aff867b Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 27 Jul 2021 15:53:58 +0200 Subject: [PATCH] :bug: Fix problem with pasting text into text editor --- .../main/ui/workspace/shapes/text/editor.cljs | 18 +++++-- frontend/src/app/util/text_editor.cljs | 4 ++ frontend/src/app/util/text_editor_impl.js | 47 +++++++++++++++++-- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs index e2321b4de..1f74c8e28 100644 --- a/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/text/editor.cljs @@ -77,6 +77,7 @@ (let [old-blocks (js->clj (.toJS (.getBlockMap (.getCurrentContent ^js old-state))) :keywordize-keys false) new-blocks (js->clj (.toJS (.getBlockMap (.getCurrentContent ^js state))) + :keywordize-keys false)] (->> old-blocks (d/mapm @@ -173,8 +174,9 @@ handle-return (mf/use-callback (fn [_ state] - (let [state (ted/editor-split-block state) - state (handle-change state)] + (let [style (ted/get-editor-current-inline-styles state) + state (-> (ted/insert-text state "\n" style) + (handle-change))] (st/emit! (dwt/update-editor-state shape state))) "handled")) @@ -183,7 +185,16 @@ (fn [event] (when (dom/class? (dom/get-target event) "DraftEditor-root") (st/emit! (dwt/cursor-to-end shape))) - (st/emit! (dwt/focus-editor))))] + (st/emit! (dwt/focus-editor)))) + + handle-pasted-text + (fn [text _ editor] + (let [style (ted/get-editor-current-inline-styles state) + state (-> (ted/insert-text state text style) + (handle-change))] + (st/emit! (dwt/update-editor-state shape state))) + + "handled")] (mf/use-layout-effect on-mount) @@ -203,6 +214,7 @@ :on-focus on-focus :handle-return handle-return :strip-pasted-styles true + :handle-pasted-text handle-pasted-text :custom-style-fn styles-fn :block-renderer-fn #(render-block % shape) :ref on-editor diff --git a/frontend/src/app/util/text_editor.cljs b/frontend/src/app/util/text_editor.cljs index 790609f6f..06738d20e 100644 --- a/frontend/src/app/util/text_editor.cljs +++ b/frontend/src/app/util/text_editor.cljs @@ -126,3 +126,7 @@ (as-> state $ (reduce redfn $ blocks) (impl/setSelection $ selection))))) + +(defn insert-text [state text attrs] + (let [style (txt/attrs-to-styles attrs)] + (impl/insertText state text (clj->js attrs) (clj->js style)))) diff --git a/frontend/src/app/util/text_editor_impl.js b/frontend/src/app/util/text_editor_impl.js index 18de4ec8f..92b01533b 100644 --- a/frontend/src/app/util/text_editor_impl.js +++ b/frontend/src/app/util/text_editor_impl.js @@ -9,14 +9,17 @@ 'use strict'; import { + BlockMapBuilder, CharacterMetadata, - EditorState, CompositeDecorator, + EditorState, + Modifier, + RichTextEditorUtil, SelectionState, - Modifier } from "draft-js"; -import {Map} from "immutable"; +import DraftPasteProcessor from 'draft-js/lib/DraftPasteProcessor'; +import {Map, OrderedSet} from "immutable"; function isDefined(v) { return v !== undefined && v !== null; @@ -335,3 +338,41 @@ export function getInlineStyle(state, blockKey, offset) { const block = content.getBlockForKey(blockKey); return block.getInlineStyleAt(offset).toJS(); } + +const NEWLINE_REGEX = /\r\n?|\n/g; + +function splitTextIntoTextBlocks(text) { + return text.split(NEWLINE_REGEX); +} + +export function insertText(state, text, attrs, inlineStyles) { + const blocks = splitTextIntoTextBlocks(text); + + const character = CharacterMetadata.create({style: OrderedSet(inlineStyles)}); + + let blockArray = DraftPasteProcessor.processText( + blocks, + character, + "unstyled", + ); + + blockArray = blockArray.map((b) => { + if (b.getText() === "") { + return mergeBlockData(b, attrs) + } + return b; + }); + + const fragment = BlockMapBuilder.createFromArray(blockArray); + const content = state.getCurrentContent(); + const selection = state.getSelection(); + + const newContent = Modifier.replaceWithFragment( + content, + selection, + fragment + ); + + const resultSelection = SelectionState.createEmpty(selection.getStartKey()); + return EditorState.push(state, newContent, 'insert-fragment'); +}