mirror of
https://github.com/penpot/penpot.git
synced 2025-02-13 02:28:18 -05: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
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.pages.helpers :refer [get-children]]
|
||||
[clojure.spec.alpha :as s]))
|
||||
|
||||
;; --- Alignment
|
||||
|
@ -15,23 +17,13 @@
|
|||
|
||||
(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
|
||||
"Move the shape and all its recursive children."
|
||||
[shape dpoint objects]
|
||||
(let [children-ids (get-children (:id shape) objects)
|
||||
children (map #(get objects %) children-ids)]
|
||||
(map #(gsh/move % dpoint) (cons shape children))))
|
||||
(->> (get-children (:id shape) objects)
|
||||
(map (d/getf objects))
|
||||
(cons shape)
|
||||
(map #(gsh/move % dpoint))))
|
||||
|
||||
(defn align-to-rect
|
||||
"Move the shape so that it is aligned with the given rectangle
|
||||
|
|
|
@ -412,7 +412,7 @@
|
|||
{:rotation angle
|
||||
:displacement displacement}))
|
||||
|
||||
(defn merge-modifiers*
|
||||
(defn merge-modifiers
|
||||
[objects modifiers]
|
||||
|
||||
(let [set-modifier
|
||||
|
@ -422,8 +422,6 @@
|
|||
(->> modifiers
|
||||
(reduce set-modifier objects))))
|
||||
|
||||
(def merge-modifiers (memoize merge-modifiers*))
|
||||
|
||||
(defn modifiers->transform
|
||||
([modifiers]
|
||||
(modifiers->transform nil modifiers))
|
||||
|
|
|
@ -99,37 +99,10 @@
|
|||
[component]
|
||||
(get-in component [:objects (:id component)]))
|
||||
|
||||
;; Implemented with transient for performance
|
||||
(defn get-children*
|
||||
"Retrieve all children ids recursively for a given object. The
|
||||
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 [id objects]
|
||||
(if-let [shapes (-> (get objects id) :shapes (some-> vec))]
|
||||
(into shapes (mapcat #(get-children % objects)) shapes)
|
||||
[]))
|
||||
|
||||
(defn get-children-objects
|
||||
"Retrieve all children objects recursively for a given object"
|
||||
|
@ -175,7 +148,7 @@
|
|||
shape
|
||||
(get objects (:frame-id shape))))
|
||||
|
||||
(defn clean-loops*
|
||||
(defn clean-loops
|
||||
"Clean a list of ids from circular references."
|
||||
[objects ids]
|
||||
|
||||
|
@ -192,8 +165,6 @@
|
|||
|
||||
(reduce add-element (d/ordered-set) ids)))
|
||||
|
||||
(def clean-loops (memoize clean-loops*))
|
||||
|
||||
(defn calculate-invalid-targets
|
||||
[shape-id objects]
|
||||
(let [result #{shape-id}
|
||||
|
|
|
@ -101,10 +101,12 @@
|
|||
bool-shape (bool/bool-shape shape-wrapper)]
|
||||
(mf/fnc bool-wrapper
|
||||
[{:keys [shape] :as props}]
|
||||
(let [childs (->> (cp/get-children (:id shape) objects)
|
||||
(select-keys objects))]
|
||||
[:& bool-shape {:shape shape
|
||||
:childs childs}]))))
|
||||
(let [childs (mf/use-memo
|
||||
(mf/deps (:id shape) objects)
|
||||
(fn []
|
||||
(->> (cp/get-children (:id shape) objects)
|
||||
(select-keys objects))))]
|
||||
[:& bool-shape {:shape shape :childs childs}]))))
|
||||
|
||||
(defn svg-raw-wrapper-factory
|
||||
[objects]
|
||||
|
@ -221,26 +223,39 @@
|
|||
(mf/defc frame-svg
|
||||
{::mf/wrap [mf/memo]}
|
||||
[{:keys [objects frame zoom] :or {zoom 1} :as props}]
|
||||
(let [modifier (-> (gpt/point (:x frame) (:y frame))
|
||||
(gpt/negate)
|
||||
(gmt/translate-matrix))
|
||||
|
||||
frame-id (:id frame)
|
||||
|
||||
(let [frame-id (:id frame)
|
||||
include-metadata? (mf/use-ctx export/include-metadata-ctx)
|
||||
|
||||
modifier-ids (concat [frame-id] (cp/get-children frame-id objects))
|
||||
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
|
||||
objects (reduce update-fn objects modifier-ids)
|
||||
frame (assoc-in frame [:modifiers :displacement] modifier)
|
||||
modifier
|
||||
(mf/use-memo
|
||||
(mf/deps (:x frame) (:y frame))
|
||||
(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)
|
||||
height (* (:height frame) zoom)
|
||||
vbox (format-viewbox {:width (:width frame 0) :height (:height frame 0)})
|
||||
|
||||
wrapper (mf/use-memo
|
||||
(mf/deps objects)
|
||||
#(frame-wrapper-factory objects))]
|
||||
vbox (format-viewbox {:width (:width frame 0) :height (:height frame 0)})]
|
||||
|
||||
[:svg {:view-box vbox
|
||||
:width (ust/format-precision width viewbox-decimal-precision)
|
||||
|
@ -254,19 +269,25 @@
|
|||
(mf/defc component-svg
|
||||
{::mf/wrap [mf/memo #(mf/deferred % ts/idle-then-raf)]}
|
||||
[{:keys [objects group zoom] :or {zoom 1} :as props}]
|
||||
(let [modifier (-> (gpt/point (:x group) (:y group))
|
||||
(gpt/negate)
|
||||
(gmt/translate-matrix))
|
||||
|
||||
group-id (:id group)
|
||||
|
||||
(let [group-id (:id group)
|
||||
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))))
|
||||
|
||||
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
|
||||
modifiers (reduce update-fn {} modifier-ids)
|
||||
objects (gsh/merge-modifiers objects modifiers)
|
||||
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)
|
||||
modifiers (reduce update-fn {} modifier-ids)]
|
||||
(gsh/merge-modifiers objects modifiers))))
|
||||
|
||||
group (get objects group-id)
|
||||
width (* (:width group) zoom)
|
||||
|
@ -276,7 +297,7 @@
|
|||
group-wrapper
|
||||
(mf/use-memo
|
||||
(mf/deps objects)
|
||||
#(group-wrapper-factory objects))]
|
||||
(fn [] (group-wrapper-factory objects)))]
|
||||
|
||||
[:svg {:view-box vbox
|
||||
:width (ust/format-precision width viewbox-decimal-precision)
|
||||
|
@ -285,31 +306,51 @@
|
|||
:xmlns "http://www.w3.org/2000/svg"
|
||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||
:xmlns:penpot (when include-metadata? "https://penpot.app/xmlns")}
|
||||
|
||||
[:> shape-container {:shape group}
|
||||
[:& group-wrapper {:shape group :view-box vbox}]]]))
|
||||
|
||||
(mf/defc component-symbol
|
||||
[{:keys [id data] :as props}]
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
(let [id (obj/get props "id")
|
||||
data (obj/get props "data")
|
||||
name (:name data)
|
||||
path (:path data)
|
||||
objects (:objects data)
|
||||
root (get objects id)
|
||||
selrect (:selrect root)
|
||||
|
||||
(let [{:keys [name path objects]} data
|
||||
root (get objects id)
|
||||
vbox
|
||||
(format-viewbox
|
||||
{:width (:width selrect)
|
||||
:height (:height selrect)})
|
||||
|
||||
{:keys [width height]} (:selrect root)
|
||||
vbox (format-viewbox {:width width :height height})
|
||||
modifier
|
||||
(mf/use-memo
|
||||
(mf/deps (:x root) (:y root))
|
||||
(fn []
|
||||
(-> (gpt/point (:x root) (:y root))
|
||||
(gpt/negate)
|
||||
(gmt/translate-matrix))))
|
||||
|
||||
modifier (-> (gpt/point (:x root) (:y root))
|
||||
(gpt/negate)
|
||||
(gmt/translate-matrix))
|
||||
objects
|
||||
(mf/use-memo
|
||||
(mf/deps modifier id objects)
|
||||
(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))))
|
||||
|
||||
modifier-ids (concat [id] (cp/get-children id objects))
|
||||
update-fn #(assoc-in %1 [%2 :modifiers :displacement] modifier)
|
||||
objects (reduce update-fn objects modifier-ids)
|
||||
root (assoc-in root [:modifiers :displacement] modifier)
|
||||
root
|
||||
(mf/use-memo
|
||||
(mf/deps modifier root)
|
||||
(fn [] (assoc-in root [:modifiers :displacement] modifier)))
|
||||
|
||||
group-wrapper
|
||||
(mf/use-memo
|
||||
(mf/deps objects)
|
||||
#(group-wrapper-factory objects))]
|
||||
(fn [] (group-wrapper-factory objects)))]
|
||||
|
||||
[:> "symbol" #js {:id (str id)
|
||||
:viewBox vbox
|
||||
|
@ -321,10 +362,9 @@
|
|||
(mf/defc components-sprite-svg
|
||||
{::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [data (obj/get props "data")
|
||||
children (obj/get props "children")
|
||||
embed? (obj/get props "embed?")
|
||||
(let [data (obj/get props "data")
|
||||
children (obj/get props "children")
|
||||
embed? (obj/get props "embed?")
|
||||
include-metadata? (obj/get props "include-metadata?")]
|
||||
[:& (mf/provider embed/context) {:value embed?}
|
||||
[:& (mf/provider export/include-metadata-ctx) {:value include-metadata?}
|
||||
|
|
|
@ -96,18 +96,21 @@
|
|||
::mf/wrap-props false}
|
||||
[props]
|
||||
|
||||
(let [shape (unchecked-get props "shape")
|
||||
objects (unchecked-get props "objects")
|
||||
thumbnail? (unchecked-get props "thumbnail?")
|
||||
(when-let [shape (unchecked-get props "shape")]
|
||||
(let [objects (unchecked-get props "objects")
|
||||
thumbnail? (unchecked-get props "thumbnail?")
|
||||
|
||||
children (-> (mapv (d/getf objects) (:shapes shape))
|
||||
(hooks/use-equal-memo))
|
||||
all-children (-> (cp/get-children-objects (:id shape) objects)
|
||||
(hooks/use-equal-memo))
|
||||
children
|
||||
(-> (mapv (d/getf objects) (:shapes shape))
|
||||
(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")}
|
||||
[:> shape-container {:shape shape}
|
||||
[:& ff/fontfaces-style {:shapes all-children}]
|
||||
|
|
Loading…
Add table
Reference in a new issue