mirror of
https://github.com/penpot/penpot.git
synced 2025-01-25 07:58:49 -05:00
Merge pull request #1428 from penpot/performance
⚡ Improved thumbnails handling
This commit is contained in:
commit
d3a83142ae
8 changed files with 124 additions and 97 deletions
|
@ -81,32 +81,32 @@
|
|||
(obj/set! js/window "onbeforeunload" nil)
|
||||
(st/emit! (update-persistence-status {:status :saved})))]
|
||||
(->> (rx/merge
|
||||
(->> stream
|
||||
(rx/filter dch/commit-changes?)
|
||||
(rx/map deref)
|
||||
(rx/filter local-file?)
|
||||
(rx/tap on-dirty)
|
||||
(rx/buffer-until notifier)
|
||||
(rx/filter (complement empty?))
|
||||
(rx/map (fn [buf]
|
||||
(->> (into [] (comp (map #(assoc % :id (uuid/next)))
|
||||
(map #(assoc % :file-id file-id)))
|
||||
buf)
|
||||
(persist-changes file-id))))
|
||||
(rx/tap on-saving)
|
||||
(rx/take-until (rx/delay 100 stoper)))
|
||||
(->> stream
|
||||
(rx/filter dch/commit-changes?)
|
||||
(rx/map deref)
|
||||
(rx/filter library-file?)
|
||||
(rx/filter (complement #(empty? (:changes %))))
|
||||
(rx/map persist-synchronous-changes)
|
||||
(rx/take-until (rx/delay 100 stoper)))
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::changes-persisted))
|
||||
(rx/tap on-saved)
|
||||
(rx/ignore)
|
||||
(rx/take-until stoper)))
|
||||
(->> stream
|
||||
(rx/filter dch/commit-changes?)
|
||||
(rx/map deref)
|
||||
(rx/filter local-file?)
|
||||
(rx/tap on-dirty)
|
||||
(rx/buffer-until notifier)
|
||||
(rx/filter (complement empty?))
|
||||
(rx/map (fn [buf]
|
||||
(->> (into [] (comp (map #(assoc % :id (uuid/next)))
|
||||
(map #(assoc % :file-id file-id)))
|
||||
buf)
|
||||
(persist-changes file-id))))
|
||||
(rx/tap on-saving)
|
||||
(rx/take-until (rx/delay 100 stoper)))
|
||||
(->> stream
|
||||
(rx/filter dch/commit-changes?)
|
||||
(rx/map deref)
|
||||
(rx/filter library-file?)
|
||||
(rx/filter (complement #(empty? (:changes %))))
|
||||
(rx/map persist-synchronous-changes)
|
||||
(rx/take-until (rx/delay 100 stoper)))
|
||||
(->> stream
|
||||
(rx/filter (ptk/type? ::changes-persisted))
|
||||
(rx/tap on-saved)
|
||||
(rx/ignore)
|
||||
(rx/take-until stoper)))
|
||||
(rx/subs #(st/emit! %)
|
||||
(constantly nil)
|
||||
(fn []
|
||||
|
@ -520,25 +520,25 @@
|
|||
(defn clone-media-object
|
||||
[{:keys [file-id object-id] :as params}]
|
||||
(us/assert ::clone-media-objects-params params)
|
||||
(ptk/reify ::clone-media-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity
|
||||
on-error identity}} (meta params)
|
||||
params {:is-local true
|
||||
:file-id file-id
|
||||
:id object-id}]
|
||||
(ptk/reify ::clone-media-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity
|
||||
on-error identity}} (meta params)
|
||||
params {:is-local true
|
||||
:file-id file-id
|
||||
:id object-id}]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (dm/show {:content (tr "media.loading")
|
||||
:type :info
|
||||
:timeout nil
|
||||
:tag :media-loading}))
|
||||
(->> (rp/mutation! :clone-file-media-object params)
|
||||
(rx/do on-success)
|
||||
(rx/catch on-error)
|
||||
(rx/finalize #(st/emit! (dm/hide-tag :media-loading)))))))))
|
||||
(rx/concat
|
||||
(rx/of (dm/show {:content (tr "media.loading")
|
||||
:type :info
|
||||
:timeout nil
|
||||
:tag :media-loading}))
|
||||
(->> (rp/mutation! :clone-file-media-object params)
|
||||
(rx/do on-success)
|
||||
(rx/catch on-error)
|
||||
(rx/finalize #(st/emit! (dm/hide-tag :media-loading)))))))))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
|
@ -555,12 +555,17 @@
|
|||
[ids]
|
||||
(ptk/reify ::remove-thumbnails
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(watch [_ state _]
|
||||
;; Removes the thumbnail while it's regenerated
|
||||
(rx/of (dch/update-shapes
|
||||
ids
|
||||
#(dissoc % :thumbnail)
|
||||
{:save-undo? false})))))
|
||||
(let [moving? (= :move (get-in state [:workspace-local :transform]))
|
||||
selected? (wsh/lookup-selected state)
|
||||
;; When we're moving the current frame it's safe to keep the thumbnail
|
||||
;; if it's resize we need to remove it immeditely
|
||||
ids (cond->> ids moving? (remove selected?))]
|
||||
|
||||
(if (empty? ids)
|
||||
(rx/empty)
|
||||
(rx/of (dch/update-shapes ids #(dissoc % :thumbnail) {:save-undo? false})))))))
|
||||
|
||||
(defn update-frame-thumbnail
|
||||
[frame-id]
|
||||
|
@ -607,7 +612,8 @@
|
|||
xform (comp (mapcat extract-ids)
|
||||
(map get-frame-id)
|
||||
(remove nil?)
|
||||
(filter #(not= uuid/zero %)))]
|
||||
(filter #(not= uuid/zero %))
|
||||
(filter #(contains? new-objects %)))]
|
||||
|
||||
(into #{} xform changes)))
|
||||
|
||||
|
@ -647,7 +653,8 @@
|
|||
(rx/filter dch/commit-changes?)
|
||||
(rx/filter (comp not thumbnail-change?))
|
||||
(rx/with-latest-from objects-stream)
|
||||
(rx/map extract-frame-changes))
|
||||
(rx/map extract-frame-changes)
|
||||
(rx/share))
|
||||
|
||||
frames (-> state wsh/lookup-page-objects cp/select-frames)
|
||||
no-thumb-frames (->> frames
|
||||
|
|
|
@ -449,7 +449,7 @@
|
|||
(ptk/reify ::duplicate-selected
|
||||
ptk/WatchEvent
|
||||
(watch [it state _]
|
||||
(when (nil? (get-in state [:workspace-local :transform]))
|
||||
(when (or (not move-delta?) (nil? (get-in state [:workspace-local :transform])))
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (wsh/lookup-page-objects state page-id)
|
||||
selected (wsh/lookup-selected state)
|
||||
|
@ -475,10 +475,10 @@
|
|||
|
||||
id-duplicated (when (= (count selected) 1) (first selected))]
|
||||
|
||||
(rx/of (dch/commit-changes {:redo-changes rchanges
|
||||
(rx/of (select-shapes selected)
|
||||
(dch/commit-changes {:redo-changes rchanges
|
||||
:undo-changes uchanges
|
||||
:origin it})
|
||||
(select-shapes selected)
|
||||
(memorize-duplicated id-original id-duplicated)))))))
|
||||
|
||||
(defn change-hover-state
|
||||
|
|
|
@ -510,6 +510,11 @@
|
|||
(defn- start-move-duplicate
|
||||
[from-position]
|
||||
(ptk/reify ::start-move-duplicate
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(-> state
|
||||
(assoc-in [:workspace-local :transform] :move)))
|
||||
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ stream]
|
||||
(->> stream
|
||||
|
|
|
@ -90,41 +90,46 @@
|
|||
(mf/create-element component props)
|
||||
(mf/create-element frame-placeholder props)))))
|
||||
|
||||
(defn frame-wrapper-factory
|
||||
;; Draw the frame proper as a deferred component
|
||||
(defn deferred-frame-shape-factory
|
||||
[shape-wrapper]
|
||||
(let [frame-shape (frame/frame-shape shape-wrapper)]
|
||||
(mf/fnc defered-frame-wrapper
|
||||
{::mf/wrap-props false
|
||||
::mf/wrap [#(mf/memo' % (mf/check-props ["shape" "childs"]))
|
||||
custom-deferred]}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
childs (unchecked-get props "childs")]
|
||||
[:& frame-shape {:shape shape
|
||||
:childs childs}]))))
|
||||
|
||||
(defn frame-wrapper-factory
|
||||
[shape-wrapper]
|
||||
(let [deferred-frame-shape (deferred-frame-shape-factory shape-wrapper)]
|
||||
(mf/fnc frame-wrapper
|
||||
{::mf/wrap [#(mf/memo' % check-frame-props) custom-deferred]
|
||||
{::mf/wrap [#(mf/memo' % check-frame-props)]
|
||||
::mf/wrap-props false}
|
||||
[props]
|
||||
(let [shape (unchecked-get props "shape")
|
||||
objects (unchecked-get props "objects")
|
||||
thumbnail? (unchecked-get props "thumbnail?")
|
||||
|
||||
children (-> (mapv (d/getf objects) (:shapes shape))
|
||||
(hooks/use-equal-memo))
|
||||
(let [shape (unchecked-get props "shape")
|
||||
objects (unchecked-get props "objects")
|
||||
thumbnail? (unchecked-get props "thumbnail?")
|
||||
|
||||
all-children (-> (cp/get-children-objects (:id shape) objects)
|
||||
(hooks/use-equal-memo))
|
||||
children (-> (mapv (d/getf objects) (:shapes shape))
|
||||
(hooks/use-equal-memo))
|
||||
all-children (-> (cp/get-children-objects (:id shape) objects)
|
||||
(hooks/use-equal-memo))
|
||||
|
||||
rendered? (mf/use-state false)
|
||||
|
||||
show-thumbnail? (and thumbnail? (some? (:thumbnail shape)))
|
||||
|
||||
on-dom
|
||||
(mf/use-callback
|
||||
(fn [node]
|
||||
(ts/schedule-on-idle #(reset! rendered? (some? node)))))]
|
||||
show-thumbnail? (and thumbnail? (some? (:thumbnail shape)))]
|
||||
|
||||
(when (some? shape)
|
||||
[:g.frame-wrapper {:display (when (:hidden shape) "none")}
|
||||
|
||||
(when-not show-thumbnail?
|
||||
[:> shape-container {:shape shape :ref on-dom}
|
||||
[:& ff/fontfaces-style {:shapes all-children}]
|
||||
[:& frame-shape {:shape shape
|
||||
:childs children}]])
|
||||
|
||||
(when (or (not @rendered?) show-thumbnail?)
|
||||
[:& thumbnail {:shape shape}])])))))
|
||||
[:> shape-container {:shape shape}
|
||||
[:& ff/fontfaces-style {:shapes all-children}]
|
||||
(if show-thumbnail?
|
||||
[:& thumbnail {:shape shape}]
|
||||
[:& deferred-frame-shape
|
||||
{:shape shape
|
||||
:childs children}])]])))))
|
||||
|
||||
|
|
|
@ -28,10 +28,14 @@
|
|||
(when node
|
||||
(let [img-node (mf/ref-val thumbnail-img)]
|
||||
(timers/schedule-on-idle
|
||||
#(let [frame-node (dom/get-element (str "shape-" (:id shape)))
|
||||
loading-node (when frame-node
|
||||
(dom/query frame-node "[data-loading=\"true\"]"))]
|
||||
(if (and (some? frame-node) (not (some? loading-node)))
|
||||
#(let [frame-node (dom/get-element (str "shape-" (:id shape)))
|
||||
thumb-node (dom/query frame-node ".frame-thumbnail")
|
||||
loading-node (dom/query frame-node "[data-loading=\"true\"]")]
|
||||
(if (and (some? frame-node)
|
||||
;; Not render if the thumbnail is in display
|
||||
(nil? thumb-node)
|
||||
;; Not render if some image is still loading
|
||||
(nil? loading-node))
|
||||
(let [frame-html (-> (js/XMLSerializer.)
|
||||
(.serializeToString frame-node))
|
||||
|
||||
|
@ -125,7 +129,9 @@
|
|||
;; after a time
|
||||
(reset! shape-id nil)
|
||||
(rx/push! next :next)
|
||||
(timers/schedule-on-idle (st/emitf (dwp/update-frame-thumbnail frame-id)))))]
|
||||
(timers/schedule-on-idle
|
||||
100
|
||||
(st/emitf (dwp/update-frame-thumbnail frame-id)))))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps render-frame)
|
||||
|
|
|
@ -52,17 +52,16 @@
|
|||
|
||||
;; When the shape is a frame we maybe need to move its thumbnail
|
||||
thumb-node (when frame? (dom/get-element (str "thumbnail-" id)))]
|
||||
(cond
|
||||
(some? thumb-node)
|
||||
[(.-parentNode thumb-node)]
|
||||
|
||||
(and (some? shape-node) frame?)
|
||||
[(dom/query shape-node ".frame-background")
|
||||
(cond
|
||||
frame?
|
||||
[thumb-node
|
||||
(dom/query shape-node ".frame-background")
|
||||
(dom/query shape-node ".frame-clip")]
|
||||
|
||||
;; For groups we don't want to transform the whole group but only
|
||||
;; its filters/masks
|
||||
(and (some? shape-node) mask?)
|
||||
mask?
|
||||
[(dom/query shape-node ".mask-clip-path")
|
||||
(dom/query shape-node ".mask-shape")]
|
||||
|
||||
|
|
|
@ -186,7 +186,8 @@
|
|||
|
||||
(defn query
|
||||
[el query]
|
||||
(.querySelector el query))
|
||||
(when (some? el)
|
||||
(.querySelector el query)))
|
||||
|
||||
(defn get-client-position
|
||||
[event]
|
||||
|
|
|
@ -44,11 +44,15 @@
|
|||
(def ^:private cancel-idle-callback #(js/clearTimeout %))))
|
||||
|
||||
(defn schedule-on-idle
|
||||
[func]
|
||||
(let [sem (request-idle-callback #(func))]
|
||||
(reify rx/IDisposable
|
||||
(-dispose [_]
|
||||
(cancel-idle-callback sem)))))
|
||||
([ms func]
|
||||
;; Schedule on idle after `ms` time
|
||||
(schedule ms #(schedule-on-idle func)))
|
||||
|
||||
([func]
|
||||
(let [sem (request-idle-callback #(func))]
|
||||
(reify rx/IDisposable
|
||||
(-dispose [_]
|
||||
(cancel-idle-callback sem))))))
|
||||
|
||||
(def ^:private request-animation-frame
|
||||
(or (and (exists? js/window) (.-requestAnimationFrame js/window))
|
||||
|
|
Loading…
Add table
Reference in a new issue