🐛 Fix rendering thumbnail with pending images/fonts

This commit is contained in:
alonso.torres 2022-05-19 14:14:55 +02:00 committed by Andrés Moya
parent 30bcdda90e
commit 25ff15c62e
3 changed files with 63 additions and 27 deletions

View file

@ -43,11 +43,15 @@
embed (embed/use-data-uris [uri]) embed (embed/use-data-uris [uri])
transform (gsh/transform-matrix shape) 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" pattern-attrs (cond-> #js {:patternUnits "userSpaceOnUse"
:x x :x x
:y y :y y
:height height :height height
:width width} :width width
:data-loading loading?}
(= :path (:type shape)) (= :path (:type shape))
(obj/set! "patternTransform" transform))] (obj/set! "patternTransform" transform))]

View file

@ -64,14 +64,17 @@
(mf/deps fonts-css) (mf/deps fonts-css)
#(fonts/extract-fontface-urls fonts-css)) #(fonts/extract-fontface-urls fonts-css))
;; Calculate the data-uris for these fonts ;; Calculate the data-uris for these fonts
fonts-embed (embed/use-data-uris fonts-urls) 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 ;; Creates a style tag by replacing the urls with the data uri
style (replace-embeds fonts-css fonts-urls fonts-embed)] style (replace-embeds fonts-css fonts-urls fonts-embed)]
(when (d/not-empty? style) (when (d/not-empty? style)
[:style style]))) [:style {:data-loading loading?} style])))
(defn shape->fonts (defn shape->fonts
[shape objects] [shape objects]

View file

@ -43,16 +43,18 @@
(.error js/console err) (.error js/console err)
nil))) 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 "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." so we don't have to recalculate the thumbnail when the image loads."
[value] [value]
(if (.isArray js/Array value) (if (.isArray js/Array value)
(->> value (->> value
(remove (fn [change] (remove (fn [change]
(and (= "attributes" (.-type change)) (or
(= "href" (.-attributeName change)) (= "data-loading" (.-attributeName change))
(str/starts-with? (.-oldValue change) "http"))))) (and (= "attributes" (.-type change))
(= "href" (.-attributeName change))
(str/starts-with? (.-oldValue change) "http"))))))
[value])) [value]))
(defn use-render-thumbnail (defn use-render-thumbnail
@ -64,6 +66,8 @@
disable-ref? (mf/use-var disable?) disable-ref? (mf/use-var disable?)
regenerate-thumbnail (mf/use-var false)
fixed-width (mth/clamp (:width shape) 250 2000) fixed-width (mth/clamp (:width shape) 250 2000)
fixed-height (/ (* (:height shape) fixed-width) (:width shape)) fixed-height (/ (* (:height shape) fixed-width) (:width shape))
@ -85,26 +89,42 @@
(st/emit! (dw/update-thumbnail page-id id thumb-data)) (st/emit! (dw/update-thumbnail page-id id thumb-data))
(reset! image-url nil)))))) (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 on-update-frame
(fn [] (mf/use-callback
(when (and (some? @node-ref) (not @disable-ref?)) (fn []
(let [node @node-ref (when (not @disable-ref?)
frame-html (dom/node->xml node) (reset! regenerate-thumbnail true))))
{: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-load-frame-dom on-load-frame-dom
(mf/use-callback (mf/use-callback
@ -120,13 +140,22 @@
(mf/use-effect (mf/use-effect
(fn [] (fn []
(let [subid (->> updates-str (let [subid (->> updates-str
(rx/map remove-embed-images-changes) (rx/map remove-image-loading)
(rx/filter d/not-empty?) (rx/filter d/not-empty?)
(rx/debounce 400)
(rx/catch (fn [err] (.error js/console err))) (rx/catch (fn [err] (.error js/console err)))
(rx/subs on-update-frame))] (rx/subs on-update-frame))]
#(rx/dispose! subid)))) #(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/use-effect
(mf/deps disable?) (mf/deps disable?)
(fn [] (fn []