From 42cd9a59b9e108f7504dbaaabb471f0057e68bac Mon Sep 17 00:00:00 2001 From: Aitor Date: Thu, 18 May 2023 19:34:42 +0200 Subject: [PATCH] :bug: Fix color picker broken images --- .../ui/workspace/viewport/pixel_overlay.cljs | 48 +++++++++++++++---- frontend/src/app/util/webapi.cljs | 10 +++- 2 files changed, 46 insertions(+), 12 deletions(-) diff --git a/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs b/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs index ceab081f3..705bb7e15 100644 --- a/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/pixel_overlay.cljs @@ -7,6 +7,7 @@ (ns app.main.ui.workspace.viewport.pixel-overlay (:require [app.common.data :as d] + [app.common.data.macros :as dm] [app.common.pages.helpers :as cph] [app.common.uuid :as uuid] [app.main.data.modal :as modal] @@ -17,8 +18,10 @@ [app.main.ui.cursors :as cur] [app.main.ui.workspace.shapes :as shapes] [app.util.dom :as dom] + [app.util.http :as http] [app.util.keyboard :as kbd] [app.util.object :as obj] + [app.util.webapi :as wapi] [beicon.core :as rx] [cuerdas.core :as str] [goog.events :as events] @@ -26,6 +29,35 @@ [rumext.v2 :as mf]) (:import goog.events.EventType)) +(defn- resolve-svg-images! + [svg-node] + (let [image-nodes (dom/query-all svg-node "image:not([href^=data])") + noop-fn (constantly nil)] + (->> (rx/from image-nodes) + (rx/mapcat + (fn [image] + (let [href (dom/get-attribute image "href")] + (->> (http/fetch {:method :get :uri href}) + (rx/mapcat (fn [response] (.blob ^js response))) + (rx/mapcat wapi/read-file-as-data-url) + (rx/tap (fn [data] + (dom/set-attribute! image "href" data))) + (rx/reduce noop-fn)))))))) + +(defn- svg-as-data-url + "Transforms SVG as data-url resolving any blob, http or https url to + its data equivalent." + [svg] + (let [svg-clone (.cloneNode svg true)] + (->> (resolve-svg-images! svg-clone) + (rx/map (fn [_] + (let [xml (-> (js/XMLSerializer.) + (.serializeToString ^js svg-clone) + (js/encodeURIComponent) + (js/unescape) + (js/btoa))] + (dm/str "data:image/svg+xml;base64," xml))))))) + (defn format-viewbox [vbox] (str/join " " [(:x vbox 0) (:y vbox 0) @@ -92,8 +124,8 @@ x (- (.-clientX event) brx) y (- (.-clientY event) bry) - zoom-context (.getContext zoom-view-node "2d") - canvas-context (.getContext canvas-node "2d") + zoom-context (.getContext zoom-view-node "2d" #js {:willReadFrequently true}) + canvas-context (.getContext canvas-node "2d" #js {:willReadFrequently true}) pixel-data (.getImageData canvas-context x y 1 1) rgba (.-data pixel-data) r (obj/get rgba 0) @@ -140,14 +172,10 @@ (mf/deps img-ref) (fn [] (let [img-node (mf/ref-val img-ref) - svg-node (dom/get-element "render") - xml (-> (js/XMLSerializer.) - (.serializeToString svg-node) - js/encodeURIComponent - js/unescape - js/btoa) - img-src (str "data:image/svg+xml;base64," xml)] - (obj/set! img-node "src" img-src)))) + svg-node (dom/get-element "render")] + (->> (svg-as-data-url svg-node) + (rx/subs (fn [uri] + (obj/set! img-node "src" uri))))))) handle-svg-change (mf/use-callback diff --git a/frontend/src/app/util/webapi.cljs b/frontend/src/app/util/webapi.cljs index adf487c70..da5f8d30c 100644 --- a/frontend/src/app/util/webapi.cljs +++ b/frontend/src/app/util/webapi.cljs @@ -8,6 +8,7 @@ "HTML5 web api helpers." (:require [app.common.data :as d] + [app.common.exceptions :as ex] [app.common.logging :as log] [app.util.object :as obj] [beicon.core :as rx] @@ -21,10 +22,15 @@ (rx/create (fn [subs] (let [reader (js/FileReader.)] - (obj/set! reader "onload" #(do (rx/push! subs (.-result reader)) + (obj/set! reader "onload" #(do (rx/push! subs (.-result ^js reader)) (rx/end! subs))) + (obj/set! reader "onerror" #(rx/error! subs %)) + (obj/set! reader "onabort" #(rx/error! subs (ex/error :type :internal + :code :abort + :hint "operation aborted"))) (f reader) - (constantly nil))))) + (fn [] + (.abort ^js reader)))))) (defn read-file-as-text [file]