mirror of
https://github.com/penpot/penpot.git
synced 2025-06-08 04:11:39 +02:00
✨ Revert some memoizes on page/helpers.
And improves base performance of get-children and remove duplicated code. Also optimize the use of get-children on react components with corresponding use-memo hook.
This commit is contained in:
parent
1b3b3b0ee6
commit
072e4a4f98
5 changed files with 111 additions and 107 deletions
|
@ -6,7 +6,9 @@
|
||||||
|
|
||||||
(ns app.common.geom.align
|
(ns app.common.geom.align
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.common.pages.helpers :refer [get-children]]
|
||||||
[clojure.spec.alpha :as s]))
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
;; --- Alignment
|
;; --- Alignment
|
||||||
|
@ -15,23 +17,13 @@
|
||||||
|
|
||||||
(declare calc-align-pos)
|
(declare calc-align-pos)
|
||||||
|
|
||||||
;; TODO: revisit on how to reuse code and dont have this function
|
|
||||||
;; duplicated because the implementation right now differs from the
|
|
||||||
;; original function.
|
|
||||||
|
|
||||||
;; Duplicated from pages/helpers to remove cyclic dependencies
|
|
||||||
(defn- get-children [id objects]
|
|
||||||
(let [shapes (vec (get-in objects [id :shapes]))]
|
|
||||||
(if shapes
|
|
||||||
(into shapes (mapcat #(get-children % objects)) shapes)
|
|
||||||
[])))
|
|
||||||
|
|
||||||
(defn- recursive-move
|
(defn- recursive-move
|
||||||
"Move the shape and all its recursive children."
|
"Move the shape and all its recursive children."
|
||||||
[shape dpoint objects]
|
[shape dpoint objects]
|
||||||
(let [children-ids (get-children (:id shape) objects)
|
(->> (get-children (:id shape) objects)
|
||||||
children (map #(get objects %) children-ids)]
|
(map (d/getf objects))
|
||||||
(map #(gsh/move % dpoint) (cons shape children))))
|
(cons shape)
|
||||||
|
(map #(gsh/move % dpoint))))
|
||||||
|
|
||||||
(defn align-to-rect
|
(defn align-to-rect
|
||||||
"Move the shape so that it is aligned with the given rectangle
|
"Move the shape so that it is aligned with the given rectangle
|
||||||
|
|
|
@ -412,7 +412,7 @@
|
||||||
{:rotation angle
|
{:rotation angle
|
||||||
:displacement displacement}))
|
:displacement displacement}))
|
||||||
|
|
||||||
(defn merge-modifiers*
|
(defn merge-modifiers
|
||||||
[objects modifiers]
|
[objects modifiers]
|
||||||
|
|
||||||
(let [set-modifier
|
(let [set-modifier
|
||||||
|
@ -422,8 +422,6 @@
|
||||||
(->> modifiers
|
(->> modifiers
|
||||||
(reduce set-modifier objects))))
|
(reduce set-modifier objects))))
|
||||||
|
|
||||||
(def merge-modifiers (memoize merge-modifiers*))
|
|
||||||
|
|
||||||
(defn modifiers->transform
|
(defn modifiers->transform
|
||||||
([modifiers]
|
([modifiers]
|
||||||
(modifiers->transform nil modifiers))
|
(modifiers->transform nil modifiers))
|
||||||
|
|
|
@ -99,37 +99,10 @@
|
||||||
[component]
|
[component]
|
||||||
(get-in component [:objects (:id component)]))
|
(get-in component [:objects (:id component)]))
|
||||||
|
|
||||||
;; Implemented with transient for performance
|
(defn get-children [id objects]
|
||||||
(defn get-children*
|
(if-let [shapes (-> (get objects id) :shapes (some-> vec))]
|
||||||
"Retrieve all children ids recursively for a given object. The
|
(into shapes (mapcat #(get-children % objects)) shapes)
|
||||||
children's order will be breadth first."
|
[]))
|
||||||
[id objects]
|
|
||||||
(loop [result (transient [])
|
|
||||||
pending (transient [])
|
|
||||||
next id]
|
|
||||||
(let [children (get-in objects [next :shapes] [])
|
|
||||||
[result pending]
|
|
||||||
;; Iterate through children and add them to the result
|
|
||||||
;; also add them in pending to check for their children
|
|
||||||
(loop [result result
|
|
||||||
pending pending
|
|
||||||
current (first children)
|
|
||||||
children (rest children)]
|
|
||||||
(if current
|
|
||||||
(recur (conj! result current)
|
|
||||||
(conj! pending current)
|
|
||||||
(first children)
|
|
||||||
(rest children))
|
|
||||||
[result pending]))
|
|
||||||
|
|
||||||
;; If we have still pending, advance the iterator
|
|
||||||
length (count pending)]
|
|
||||||
(if (pos? length)
|
|
||||||
(let [next (get pending (dec length))]
|
|
||||||
(recur result (pop! pending) next))
|
|
||||||
(persistent! result)))))
|
|
||||||
|
|
||||||
(def get-children (memoize get-children*))
|
|
||||||
|
|
||||||
(defn get-children-objects
|
(defn get-children-objects
|
||||||
"Retrieve all children objects recursively for a given object"
|
"Retrieve all children objects recursively for a given object"
|
||||||
|
@ -175,7 +148,7 @@
|
||||||
shape
|
shape
|
||||||
(get objects (:frame-id shape))))
|
(get objects (:frame-id shape))))
|
||||||
|
|
||||||
(defn clean-loops*
|
(defn clean-loops
|
||||||
"Clean a list of ids from circular references."
|
"Clean a list of ids from circular references."
|
||||||
[objects ids]
|
[objects ids]
|
||||||
|
|
||||||
|
@ -192,8 +165,6 @@
|
||||||
|
|
||||||
(reduce add-element (d/ordered-set) ids)))
|
(reduce add-element (d/ordered-set) ids)))
|
||||||
|
|
||||||
(def clean-loops (memoize clean-loops*))
|
|
||||||
|
|
||||||
(defn calculate-invalid-targets
|
(defn calculate-invalid-targets
|
||||||
[shape-id objects]
|
[shape-id objects]
|
||||||
(let [result #{shape-id}
|
(let [result #{shape-id}
|
||||||
|
|
|
@ -101,10 +101,12 @@
|
||||||
bool-shape (bool/bool-shape shape-wrapper)]
|
bool-shape (bool/bool-shape shape-wrapper)]
|
||||||
(mf/fnc bool-wrapper
|
(mf/fnc bool-wrapper
|
||||||
[{:keys [shape] :as props}]
|
[{:keys [shape] :as props}]
|
||||||
(let [childs (->> (cp/get-children (:id shape) objects)
|
(let [childs (mf/use-memo
|
||||||
(select-keys objects))]
|
(mf/deps (:id shape) objects)
|
||||||
[:& bool-shape {:shape shape
|
(fn []
|
||||||
:childs childs}]))))
|
(->> (cp/get-children (:id shape) objects)
|
||||||
|
(select-keys objects))))]
|
||||||
|
[:& bool-shape {:shape shape :childs childs}]))))
|
||||||
|
|
||||||
(defn svg-raw-wrapper-factory
|
(defn svg-raw-wrapper-factory
|
||||||
[objects]
|
[objects]
|
||||||
|
@ -221,26 +223,39 @@
|
||||||
(mf/defc frame-svg
|
(mf/defc frame-svg
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [objects frame zoom] :or {zoom 1} :as props}]
|
[{:keys [objects frame zoom] :or {zoom 1} :as props}]
|
||||||
(let [modifier (-> (gpt/point (:x frame) (:y frame))
|
(let [frame-id (:id frame)
|
||||||
(gpt/negate)
|
|
||||||
(gmt/translate-matrix))
|
|
||||||
|
|
||||||
frame-id (:id frame)
|
|
||||||
|
|
||||||
include-metadata? (mf/use-ctx export/include-metadata-ctx)
|
include-metadata? (mf/use-ctx export/include-metadata-ctx)
|
||||||
|
|
||||||
modifier-ids (concat [frame-id] (cp/get-children frame-id objects))
|
modifier
|
||||||
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
|
(mf/use-memo
|
||||||
objects (reduce update-fn objects modifier-ids)
|
(mf/deps (:x frame) (:y frame))
|
||||||
frame (assoc-in frame [:modifiers :displacement] modifier)
|
(fn []
|
||||||
|
(-> (gpt/point (:x frame) (:y frame))
|
||||||
|
(gpt/negate)
|
||||||
|
(gmt/translate-matrix))))
|
||||||
|
|
||||||
|
objects
|
||||||
|
(mf/use-memo
|
||||||
|
(mf/deps frame-id objects modifier)
|
||||||
|
(fn []
|
||||||
|
(let [update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)]
|
||||||
|
(->> (cp/get-children frame-id objects)
|
||||||
|
(into [frame-id])
|
||||||
|
(reduce update-fn objects)))))
|
||||||
|
|
||||||
|
frame
|
||||||
|
(mf/use-memo
|
||||||
|
(mf/deps modifier)
|
||||||
|
(fn [] (assoc-in frame [:modifiers :displacement] modifier)))
|
||||||
|
|
||||||
|
wrapper
|
||||||
|
(mf/use-memo
|
||||||
|
(mf/deps objects)
|
||||||
|
(fn [] (frame-wrapper-factory objects)))
|
||||||
|
|
||||||
width (* (:width frame) zoom)
|
width (* (:width frame) zoom)
|
||||||
height (* (:height frame) zoom)
|
height (* (:height frame) zoom)
|
||||||
vbox (format-viewbox {:width (:width frame 0) :height (:height frame 0)})
|
vbox (format-viewbox {:width (:width frame 0) :height (:height frame 0)})]
|
||||||
|
|
||||||
wrapper (mf/use-memo
|
|
||||||
(mf/deps objects)
|
|
||||||
#(frame-wrapper-factory objects))]
|
|
||||||
|
|
||||||
[:svg {:view-box vbox
|
[:svg {:view-box vbox
|
||||||
:width (ust/format-precision width viewbox-decimal-precision)
|
:width (ust/format-precision width viewbox-decimal-precision)
|
||||||
|
@ -254,19 +269,25 @@
|
||||||
(mf/defc component-svg
|
(mf/defc component-svg
|
||||||
{::mf/wrap [mf/memo #(mf/deferred % ts/idle-then-raf)]}
|
{::mf/wrap [mf/memo #(mf/deferred % ts/idle-then-raf)]}
|
||||||
[{:keys [objects group zoom] :or {zoom 1} :as props}]
|
[{:keys [objects group zoom] :or {zoom 1} :as props}]
|
||||||
(let [modifier (-> (gpt/point (:x group) (:y group))
|
(let [group-id (:id group)
|
||||||
(gpt/negate)
|
|
||||||
(gmt/translate-matrix))
|
|
||||||
|
|
||||||
group-id (:id group)
|
|
||||||
|
|
||||||
include-metadata? (mf/use-ctx export/include-metadata-ctx)
|
include-metadata? (mf/use-ctx export/include-metadata-ctx)
|
||||||
|
|
||||||
modifier-ids (concat [group-id] (cp/get-children group-id objects))
|
modifier
|
||||||
|
(mf/use-memo
|
||||||
|
(mf/deps (:x group) (:y group))
|
||||||
|
(fn []
|
||||||
|
(-> (gpt/point (:x group) (:y group))
|
||||||
|
(gpt/negate)
|
||||||
|
(gmt/translate-matrix))))
|
||||||
|
|
||||||
|
objects
|
||||||
|
(mf/use-memo
|
||||||
|
(mf/deps modifier objects group-id)
|
||||||
|
(fn []
|
||||||
|
(let [modifier-ids (concat [group-id] (cp/get-children group-id objects))
|
||||||
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
|
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
|
||||||
modifiers (reduce update-fn {} modifier-ids)
|
modifiers (reduce update-fn {} modifier-ids)]
|
||||||
objects (gsh/merge-modifiers objects modifiers)
|
(gsh/merge-modifiers objects modifiers))))
|
||||||
|
|
||||||
group (get objects group-id)
|
group (get objects group-id)
|
||||||
width (* (:width group) zoom)
|
width (* (:width group) zoom)
|
||||||
|
@ -276,7 +297,7 @@
|
||||||
group-wrapper
|
group-wrapper
|
||||||
(mf/use-memo
|
(mf/use-memo
|
||||||
(mf/deps objects)
|
(mf/deps objects)
|
||||||
#(group-wrapper-factory objects))]
|
(fn [] (group-wrapper-factory objects)))]
|
||||||
|
|
||||||
[:svg {:view-box vbox
|
[:svg {:view-box vbox
|
||||||
:width (ust/format-precision width viewbox-decimal-precision)
|
:width (ust/format-precision width viewbox-decimal-precision)
|
||||||
|
@ -285,31 +306,51 @@
|
||||||
:xmlns "http://www.w3.org/2000/svg"
|
:xmlns "http://www.w3.org/2000/svg"
|
||||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||||
:xmlns:penpot (when include-metadata? "https://penpot.app/xmlns")}
|
:xmlns:penpot (when include-metadata? "https://penpot.app/xmlns")}
|
||||||
|
|
||||||
[:> shape-container {:shape group}
|
[:> shape-container {:shape group}
|
||||||
[:& group-wrapper {:shape group :view-box vbox}]]]))
|
[:& group-wrapper {:shape group :view-box vbox}]]]))
|
||||||
|
|
||||||
(mf/defc component-symbol
|
(mf/defc component-symbol
|
||||||
[{:keys [id data] :as props}]
|
{::mf/wrap-props false}
|
||||||
|
[props]
|
||||||
(let [{:keys [name path objects]} data
|
(let [id (obj/get props "id")
|
||||||
|
data (obj/get props "data")
|
||||||
|
name (:name data)
|
||||||
|
path (:path data)
|
||||||
|
objects (:objects data)
|
||||||
root (get objects id)
|
root (get objects id)
|
||||||
|
selrect (:selrect root)
|
||||||
|
|
||||||
{:keys [width height]} (:selrect root)
|
vbox
|
||||||
vbox (format-viewbox {:width width :height height})
|
(format-viewbox
|
||||||
|
{:width (:width selrect)
|
||||||
|
:height (:height selrect)})
|
||||||
|
|
||||||
modifier (-> (gpt/point (:x root) (:y root))
|
modifier
|
||||||
|
(mf/use-memo
|
||||||
|
(mf/deps (:x root) (:y root))
|
||||||
|
(fn []
|
||||||
|
(-> (gpt/point (:x root) (:y root))
|
||||||
(gpt/negate)
|
(gpt/negate)
|
||||||
(gmt/translate-matrix))
|
(gmt/translate-matrix))))
|
||||||
|
|
||||||
modifier-ids (concat [id] (cp/get-children id objects))
|
objects
|
||||||
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
|
(mf/use-memo
|
||||||
objects (reduce update-fn objects modifier-ids)
|
(mf/deps modifier id objects)
|
||||||
root (assoc-in root [:modifiers :displacement] modifier)
|
(fn []
|
||||||
|
(let [modifier-ids (concat [id] (cp/get-children id objects))
|
||||||
|
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)]
|
||||||
|
(reduce update-fn objects modifier-ids))))
|
||||||
|
|
||||||
|
root
|
||||||
|
(mf/use-memo
|
||||||
|
(mf/deps modifier root)
|
||||||
|
(fn [] (assoc-in root [:modifiers :displacement] modifier)))
|
||||||
|
|
||||||
group-wrapper
|
group-wrapper
|
||||||
(mf/use-memo
|
(mf/use-memo
|
||||||
(mf/deps objects)
|
(mf/deps objects)
|
||||||
#(group-wrapper-factory objects))]
|
(fn [] (group-wrapper-factory objects)))]
|
||||||
|
|
||||||
[:> "symbol" #js {:id (str id)
|
[:> "symbol" #js {:id (str id)
|
||||||
:viewBox vbox
|
:viewBox vbox
|
||||||
|
@ -321,7 +362,6 @@
|
||||||
(mf/defc components-sprite-svg
|
(mf/defc components-sprite-svg
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
|
|
||||||
(let [data (obj/get props "data")
|
(let [data (obj/get props "data")
|
||||||
children (obj/get props "children")
|
children (obj/get props "children")
|
||||||
embed? (obj/get props "embed?")
|
embed? (obj/get props "embed?")
|
||||||
|
|
|
@ -96,18 +96,21 @@
|
||||||
::mf/wrap-props false}
|
::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
|
|
||||||
(let [shape (unchecked-get props "shape")
|
(when-let [shape (unchecked-get props "shape")]
|
||||||
objects (unchecked-get props "objects")
|
(let [objects (unchecked-get props "objects")
|
||||||
thumbnail? (unchecked-get props "thumbnail?")
|
thumbnail? (unchecked-get props "thumbnail?")
|
||||||
|
|
||||||
children (-> (mapv (d/getf objects) (:shapes shape))
|
children
|
||||||
(hooks/use-equal-memo))
|
(-> (mapv (d/getf objects) (:shapes shape))
|
||||||
all-children (-> (cp/get-children-objects (:id shape) objects)
|
|
||||||
(hooks/use-equal-memo))
|
(hooks/use-equal-memo))
|
||||||
|
|
||||||
show-thumbnail? (and thumbnail? (some? (:thumbnail shape)))]
|
all-children
|
||||||
|
(-> (cp/get-children-objects (:id shape) objects)
|
||||||
|
(hooks/use-equal-memo))
|
||||||
|
|
||||||
|
show-thumbnail?
|
||||||
|
(and thumbnail? (some? (:thumbnail shape)))]
|
||||||
|
|
||||||
(when (some? shape)
|
|
||||||
[:g.frame-wrapper {:display (when (:hidden shape) "none")}
|
[:g.frame-wrapper {:display (when (:hidden shape) "none")}
|
||||||
[:> shape-container {:shape shape}
|
[:> shape-container {:shape shape}
|
||||||
[:& ff/fontfaces-style {:shapes all-children}]
|
[:& ff/fontfaces-style {:shapes all-children}]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue