From 25ff15c62e93a8de5ae88cdda261fcb9063f039c Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Thu, 19 May 2022 14:14:55 +0200 Subject: [PATCH] :bug: Fix rendering thumbnail with pending images/fonts --- frontend/src/app/main/ui/shapes/fills.cljs | 6 +- .../app/main/ui/shapes/text/fontfaces.cljs | 5 +- .../shapes/frame/thumbnail_render.cljs | 79 +++++++++++++------ 3 files changed, 63 insertions(+), 27 deletions(-) diff --git a/frontend/src/app/main/ui/shapes/fills.cljs b/frontend/src/app/main/ui/shapes/fills.cljs index 2aee6e122..a3a8769e7 100644 --- a/frontend/src/app/main/ui/shapes/fills.cljs +++ b/frontend/src/app/main/ui/shapes/fills.cljs @@ -43,11 +43,15 @@ embed (embed/use-data-uris [uri]) transform (gsh/transform-matrix shape) + ;; When true the image has not loaded yet + loading? (and (some? uri) (not (contains? embed uri))) + pattern-attrs (cond-> #js {:patternUnits "userSpaceOnUse" :x x :y y :height height - :width width} + :width width + :data-loading loading?} (= :path (:type shape)) (obj/set! "patternTransform" transform))] diff --git a/frontend/src/app/main/ui/shapes/text/fontfaces.cljs b/frontend/src/app/main/ui/shapes/text/fontfaces.cljs index d08ebbb87..a470d5238 100644 --- a/frontend/src/app/main/ui/shapes/text/fontfaces.cljs +++ b/frontend/src/app/main/ui/shapes/text/fontfaces.cljs @@ -64,14 +64,17 @@ (mf/deps fonts-css) #(fonts/extract-fontface-urls fonts-css)) + ;; Calculate the data-uris for these fonts fonts-embed (embed/use-data-uris fonts-urls) + loading? (d/seek #(not (contains? fonts-embed %)) fonts-urls) + ;; Creates a style tag by replacing the urls with the data uri style (replace-embeds fonts-css fonts-urls fonts-embed)] (when (d/not-empty? style) - [:style style]))) + [:style {:data-loading loading?} style]))) (defn shape->fonts [shape objects] diff --git a/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs b/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs index f6926234a..e6096c18b 100644 --- a/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs +++ b/frontend/src/app/main/ui/workspace/shapes/frame/thumbnail_render.cljs @@ -43,16 +43,18 @@ (.error js/console err) nil))) -(defn- remove-embed-images-changes +(defn- remove-image-loading "Remove the changes related to change a url for its embed value. This is necessary so we don't have to recalculate the thumbnail when the image loads." [value] (if (.isArray js/Array value) (->> value (remove (fn [change] - (and (= "attributes" (.-type change)) - (= "href" (.-attributeName change)) - (str/starts-with? (.-oldValue change) "http"))))) + (or + (= "data-loading" (.-attributeName change)) + (and (= "attributes" (.-type change)) + (= "href" (.-attributeName change)) + (str/starts-with? (.-oldValue change) "http")))))) [value])) (defn use-render-thumbnail @@ -64,6 +66,8 @@ disable-ref? (mf/use-var disable?) + regenerate-thumbnail (mf/use-var false) + fixed-width (mth/clamp (:width shape) 250 2000) fixed-height (/ (* (:height shape) fixed-width) (:width shape)) @@ -85,26 +89,42 @@ (st/emit! (dw/update-thumbnail page-id id thumb-data)) (reset! image-url nil)))))) + generate-thumbnail + (mf/use-callback + (fn [] + (let [node @node-ref + frame-html (dom/node->xml node) + {:keys [x y width height]} @shape-ref + + style-node (dom/query (dm/str "#frame-container-" (:id shape) " style")) + style-str (or (-> style-node dom/node->xml) "") + + svg-node + (-> (dom/make-node "http://www.w3.org/2000/svg" "svg") + (dom/set-property! "version" "1.1") + (dom/set-property! "viewBox" (dm/str x " " y " " width " " height)) + (dom/set-property! "width" width) + (dom/set-property! "height" height) + (dom/set-property! "fill" "none") + (obj/set! "innerHTML" (dm/str style-str frame-html))) + img-src (-> svg-node dom/node->xml dom/svg->data-uri)] + (reset! image-url img-src)))) + + on-change-frame + (mf/use-callback + (fn [] + (when (and (some? @node-ref) @regenerate-thumbnail) + (let [loading-images? (some? (dom/query @node-ref "[data-loading='true']")) + loading-fonts? (some? (dom/query (dm/str "#frame-container-" (:id shape) " style[data-loading='true']")))] + (when (and (not loading-images?) (not loading-fonts?)) + (generate-thumbnail) + (reset! regenerate-thumbnail false)))))) + on-update-frame - (fn [] - (when (and (some? @node-ref) (not @disable-ref?)) - (let [node @node-ref - frame-html (dom/node->xml node) - {:keys [x y width height]} @shape-ref - - style-node (dom/query (dm/str "#frame-container-" (:id shape) " style")) - style-str (or (-> style-node dom/node->xml) "") - - svg-node - (-> (dom/make-node "http://www.w3.org/2000/svg" "svg") - (dom/set-property! "version" "1.1") - (dom/set-property! "viewBox" (dm/str x " " y " " width " " height)) - (dom/set-property! "width" width) - (dom/set-property! "height" height) - (dom/set-property! "fill" "none") - (obj/set! "innerHTML" (dm/str style-str frame-html))) - img-src (-> svg-node dom/node->xml dom/svg->data-uri)] - (reset! image-url img-src)))) + (mf/use-callback + (fn [] + (when (not @disable-ref?) + (reset! regenerate-thumbnail true)))) on-load-frame-dom (mf/use-callback @@ -120,13 +140,22 @@ (mf/use-effect (fn [] (let [subid (->> updates-str - (rx/map remove-embed-images-changes) + (rx/map remove-image-loading) (rx/filter d/not-empty?) - (rx/debounce 400) (rx/catch (fn [err] (.error js/console err))) (rx/subs on-update-frame))] #(rx/dispose! subid)))) + ;; on-change-frame will get every change in the frame + (mf/use-effect + (fn [] + (let [subid (->> updates-str + (rx/debounce 400) + (rx/observe-on :af) + (rx/catch (fn [err] (.error js/console err))) + (rx/subs on-change-frame))] + #(rx/dispose! subid)))) + (mf/use-effect (mf/deps disable?) (fn []