diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index d029a4143..90a5d2091 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -9,6 +9,7 @@ (ns app.main.data.workspace (:require + [cuerdas.core :as str] [app.common.data :as d] [app.common.exceptions :as ex] [app.common.geom.matrix :as gmt] @@ -1236,22 +1237,80 @@ (with-meta params {:on-success image-uploaded}))))))) +(declare paste-text) + (def paste (ptk/reify ::paste ptk/WatchEvent (watch [_ state stream] - (->> (wapi/read-from-clipboard) - (rx/map t/decode) - (rx/filter #(= :copied-shapes (:type %))) - (rx/map #(select-keys % [:selected :objects])) - (rx/map paste-impl) - (rx/catch (partial instance? js/SyntaxError) - (fn [_] - (->> (wapi/read-image-from-clipboard) - (rx/map paste-image-impl)))) - (rx/catch (fn [err] - (js/console.error "Clipboard error:" err) - (rx/empty))))))) + (try + (let [clipboard-str (wapi/read-from-clipboard) + + paste-transit-str + (->> clipboard-str + (rx/filter t/transit?) + (rx/map t/decode) + (rx/filter #(= :copied-shapes (:type %))) + (rx/map #(select-keys % [:selected :objects])) + (rx/map paste-impl)) + + paste-plain-text-str + (->> clipboard-str + (rx/filter (comp not empty?)) + (rx/map paste-text)) + + paste-image-str + (->> (wapi/read-image-from-clipboard) + (rx/map paste-image-impl))] + + (->> (rx/concat paste-transit-str + paste-plain-text-str + paste-image-str) + (rx/first) + (rx/catch + (fn [err] + (js/console.error "Clipboard error:" err) + (rx/empty))))) + (catch :default e + (.error js/console "ERROR" e)))))) + +(defn as-content [text] + (let [paragraphs (->> (str/split text "\n") + (map str/trim) + (mapv #(hash-map :type "paragraph" + :children [{:text %}])))] + {:type "root" + :children [{:type "paragraph-set" :children paragraphs}]})) + +(defn paste-text [text] + (s/assert string? text) + (ptk/reify ::paste-text + ptk/WatchEvent + (watch [_ state stream] + (let [id (uuid/next) + {:keys [x y]} @ms/mouse-position + width (* 7 (count text)) + height 16 + shape {:id id + :type :text + :name "Text" + :x x + :y y + :selrect {:x1 x :y1 y + :x2 (+ x width) + :y2 (+ y height) + :x x :y y + :width width + :height height} + :width width + :height height + :grow-type :auto-width + :content (as-content text)}] + (rx/of dwc/start-undo-transaction + dws/deselect-all + (add-shape shape) + (dwc/rehash-shape-frame-relationship [id]) + dwc/commit-undo-transaction))))) (defn update-shape-flags [id {:keys [blocked hidden] :as flags}] diff --git a/frontend/src/app/util/transit.cljs b/frontend/src/app/util/transit.cljs index 79b619e65..3ffe3ae05 100644 --- a/frontend/src/app/util/transit.cljs +++ b/frontend/src/app/util/transit.cljs @@ -94,3 +94,10 @@ (t/write w data)) (catch :default e (throw e)))) + +(defn transit? + "Checks if a string can be decoded with transit" + [str] + (try + (-> str decode nil? not) + (catch js/SyntaxError e false)))