mirror of
https://github.com/penpot/penpot.git
synced 2025-05-18 23:56:11 +02:00
⚡ Improve performance on creating component from graphic
About 25% speed improvement on average on single file migration process
This commit is contained in:
parent
c70acb1570
commit
f104cc5477
5 changed files with 148 additions and 115 deletions
|
@ -57,6 +57,14 @@
|
||||||
#?(:cljs (instance? lkm/LinkedMap o)
|
#?(:cljs (instance? lkm/LinkedMap o)
|
||||||
:clj (instance? LinkedMap o)))
|
:clj (instance? LinkedMap o)))
|
||||||
|
|
||||||
|
(defn vec2
|
||||||
|
"Creates a optimized vector compatible type of length 2 backed
|
||||||
|
internally with MapEntry impl because it has faster access method
|
||||||
|
for its fields."
|
||||||
|
[o1 o2]
|
||||||
|
#?(:clj (clojure.lang.MapEntry. o1 o2)
|
||||||
|
:cljs (cljs.core/->MapEntry o1 o2 nil)))
|
||||||
|
|
||||||
#?(:clj
|
#?(:clj
|
||||||
(defmethod print-method clojure.lang.PersistentQueue [q, w]
|
(defmethod print-method clojure.lang.PersistentQueue [q, w]
|
||||||
;; Overload the printer for queues so they look like fish
|
;; Overload the printer for queues so they look like fish
|
||||||
|
|
|
@ -484,7 +484,7 @@
|
||||||
(letfn [(red-fn [cur-idx id]
|
(letfn [(red-fn [cur-idx id]
|
||||||
(let [[prev-idx _] (first cur-idx)
|
(let [[prev-idx _] (first cur-idx)
|
||||||
prev-idx (or prev-idx 0)
|
prev-idx (or prev-idx 0)
|
||||||
cur-idx (conj cur-idx [(inc prev-idx) id])]
|
cur-idx (conj cur-idx (d/vec2 (inc prev-idx) id))]
|
||||||
(rec-index cur-idx id)))
|
(rec-index cur-idx id)))
|
||||||
(rec-index [cur-idx id]
|
(rec-index [cur-idx id]
|
||||||
(let [object (get objects id)]
|
(let [object (get objects id)]
|
||||||
|
@ -509,10 +509,11 @@
|
||||||
|
|
||||||
(defn order-by-indexed-shapes
|
(defn order-by-indexed-shapes
|
||||||
[objects ids]
|
[objects ids]
|
||||||
|
(let [ids (if (set? ids) ids (set ids))]
|
||||||
(->> (indexed-shapes objects)
|
(->> (indexed-shapes objects)
|
||||||
(sort-by first)
|
(filter (fn [o] (contains? ids (val o))))
|
||||||
(filter (comp (into #{} ids) second))
|
(sort-by key)
|
||||||
(map second)))
|
(map val))))
|
||||||
|
|
||||||
(defn get-index-replacement
|
(defn get-index-replacement
|
||||||
"Given a collection of shapes, calculate their positions
|
"Given a collection of shapes, calculate their positions
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(ns app.common.files.libraries-helpers
|
(ns app.common.files.libraries-helpers
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data :as d]
|
||||||
[app.common.files.changes-builder :as pcb]
|
[app.common.files.changes-builder :as pcb]
|
||||||
[app.common.files.helpers :as cfh]
|
[app.common.files.helpers :as cfh]
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
|
@ -37,41 +38,50 @@
|
||||||
use it as root. Otherwise, create a frame (v2) or group (v1) that contains all ids. Then, make a
|
use it as root. Otherwise, create a frame (v2) or group (v1) that contains all ids. Then, make a
|
||||||
component with it, and link all shapes to their corresponding one in the component."
|
component with it, and link all shapes to their corresponding one in the component."
|
||||||
[it shapes objects page-id file-id components-v2 prepare-create-group prepare-create-board]
|
[it shapes objects page-id file-id components-v2 prepare-create-group prepare-create-board]
|
||||||
|
|
||||||
(let [changes (pcb/empty-changes it page-id)
|
(let [changes (pcb/empty-changes it page-id)
|
||||||
|
shapes-count (count shapes)
|
||||||
|
first-shape (first shapes)
|
||||||
|
|
||||||
|
from-singe-frame?
|
||||||
|
(and (= 1 shapes-count)
|
||||||
|
(cfh/frame-shape? first-shape))
|
||||||
|
|
||||||
from-singe-frame? (and (= 1 (count shapes)) (-> shapes first cfh/frame-shape?))
|
|
||||||
[root changes old-root-ids]
|
[root changes old-root-ids]
|
||||||
(if (and (= (count shapes) 1)
|
(if (and (= shapes-count 1)
|
||||||
(or (and (= (:type (first shapes)) :group) (not components-v2))
|
(or (and (cfh/group-shape? first-shape)
|
||||||
(= (:type (first shapes)) :frame))
|
(not components-v2))
|
||||||
(not (ctk/instance-head? (first shapes))))
|
(cfh/frame-shape? first-shape))
|
||||||
|
(not (ctk/instance-head? first-shape)))
|
||||||
[(first shapes)
|
[first-shape
|
||||||
(-> (pcb/empty-changes it page-id)
|
(-> (pcb/empty-changes it page-id)
|
||||||
(pcb/with-objects objects))
|
(pcb/with-objects objects))
|
||||||
(:shapes (first shapes))]
|
(:shapes first-shape)]
|
||||||
|
|
||||||
(let [root-name (if (= 1 (count shapes))
|
(let [root-name (if (= 1 shapes-count)
|
||||||
(:name (first shapes))
|
(:name first-shape)
|
||||||
"Component 1")
|
"Component 1")
|
||||||
|
|
||||||
[root changes] (if-not components-v2
|
shape-ids (into (d/ordered-set) (map :id) shapes)
|
||||||
|
|
||||||
|
[root changes]
|
||||||
|
(if-not components-v2
|
||||||
(prepare-create-group it ; These functions needs to be passed as argument
|
(prepare-create-group it ; These functions needs to be passed as argument
|
||||||
objects ; to avoid a circular dependence
|
objects ; to avoid a circular dependence
|
||||||
page-id
|
page-id
|
||||||
shapes
|
shapes
|
||||||
root-name
|
root-name
|
||||||
(not (ctk/instance-head? (first shapes))))
|
(not (ctk/instance-head? first-shape)))
|
||||||
(prepare-create-board changes
|
(prepare-create-board changes
|
||||||
(uuid/next)
|
(uuid/next)
|
||||||
(:parent-id (first shapes))
|
(:parent-id first-shape)
|
||||||
objects
|
objects
|
||||||
(map :id shapes)
|
shape-ids
|
||||||
nil
|
nil
|
||||||
root-name
|
root-name
|
||||||
true))]
|
true))]
|
||||||
|
|
||||||
[root changes (map :id shapes)]))
|
[root changes shape-ids]))
|
||||||
|
|
||||||
changes
|
changes
|
||||||
(cond-> changes
|
(cond-> changes
|
||||||
|
@ -79,8 +89,7 @@
|
||||||
(pcb/update-shapes
|
(pcb/update-shapes
|
||||||
(:shapes root)
|
(:shapes root)
|
||||||
(fn [shape]
|
(fn [shape]
|
||||||
(-> shape
|
(assoc shape :constraints-h :scale :constraints-v :scale))))
|
||||||
(assoc :constraints-h :scale :constraints-v :scale)))))
|
|
||||||
|
|
||||||
objects' (assoc objects (:id root) root)
|
objects' (assoc objects (:id root) root)
|
||||||
|
|
||||||
|
|
|
@ -39,16 +39,17 @@
|
||||||
|
|
||||||
(defn prepare-move-shapes-into-frame
|
(defn prepare-move-shapes-into-frame
|
||||||
[changes frame-id shapes objects]
|
[changes frame-id shapes objects]
|
||||||
(let [ordered-indexes (cfh/order-by-indexed-shapes objects shapes)
|
(let [parent-id (dm/get-in objects [frame-id :parent-id])
|
||||||
parent-id (get-in objects [frame-id :parent-id])
|
shapes (remove #(= % parent-id) shapes)
|
||||||
ordered-indexes (->> ordered-indexes (remove #(= % parent-id)))
|
to-move (->> shapes
|
||||||
to-move-shapes (map (d/getf objects) ordered-indexes)]
|
(map (d/getf objects))
|
||||||
(if (d/not-empty? to-move-shapes)
|
(not-empty))]
|
||||||
|
(if to-move
|
||||||
(-> changes
|
(-> changes
|
||||||
(cond-> (not (ctl/any-layout? objects frame-id))
|
(cond-> (not (ctl/any-layout? objects frame-id))
|
||||||
(pcb/update-shapes ordered-indexes ctl/remove-layout-item-data))
|
(pcb/update-shapes shapes ctl/remove-layout-item-data))
|
||||||
(pcb/update-shapes ordered-indexes #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true)))
|
(pcb/update-shapes shapes #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true)))
|
||||||
(pcb/change-parent frame-id to-move-shapes 0)
|
(pcb/change-parent frame-id to-move 0)
|
||||||
(cond-> (ctl/grid-layout? objects frame-id)
|
(cond-> (ctl/grid-layout? objects frame-id)
|
||||||
(-> (pcb/update-shapes [frame-id] ctl/assign-cells {:with-objects? true})
|
(-> (pcb/update-shapes [frame-id] ctl/assign-cells {:with-objects? true})
|
||||||
(pcb/reorder-grid-children [frame-id]))))
|
(pcb/reorder-grid-children [frame-id]))))
|
||||||
|
@ -60,22 +61,31 @@
|
||||||
changes id parent-id objects selected index frame-name without-fill? nil))
|
changes id parent-id objects selected index frame-name without-fill? nil))
|
||||||
|
|
||||||
([changes id parent-id objects selected index frame-name without-fill? target-cell-id]
|
([changes id parent-id objects selected index frame-name without-fill? target-cell-id]
|
||||||
(let [selected-objs (map #(get objects %) selected)
|
(when-let [selected-objs (->> selected
|
||||||
new-index (or index
|
(map (d/getf objects))
|
||||||
(cfh/get-index-replacement selected objects))]
|
(not-empty))]
|
||||||
(when (d/not-empty? selected)
|
|
||||||
(let [srect (gsh/shapes->rect selected-objs)
|
|
||||||
selected-id (first selected)
|
|
||||||
|
|
||||||
frame-id (dm/get-in objects [selected-id :frame-id])
|
(let [;; We calculate here the ordered selection because it is used
|
||||||
parent-id (or parent-id (dm/get-in objects [selected-id :parent-id]))
|
;; multiple times and this avoid the need of creating the index
|
||||||
|
;; manytimes for single operation.
|
||||||
|
selected' (cfh/order-by-indexed-shapes objects selected)
|
||||||
|
new-index (or index
|
||||||
|
(->> (first selected')
|
||||||
|
(cfh/get-position-on-parent objects)
|
||||||
|
(inc)))
|
||||||
|
|
||||||
|
srect (gsh/shapes->rect selected-objs)
|
||||||
|
selected-id (first selected)
|
||||||
|
selected-obj (get objects selected-id)
|
||||||
|
|
||||||
|
frame-id (get selected-obj :frame-id)
|
||||||
|
parent-id (or parent-id (get selected-obj :parent-id))
|
||||||
base-parent (get objects parent-id)
|
base-parent (get objects parent-id)
|
||||||
|
|
||||||
layout-props
|
layout-props
|
||||||
(when (and (= 1 (count selected))
|
(when (and (= 1 (count selected))
|
||||||
(ctl/any-layout? base-parent))
|
(ctl/any-layout? base-parent))
|
||||||
(let [shape (get objects selected-id)]
|
(select-keys selected-obj ctl/layout-item-props))
|
||||||
(select-keys shape ctl/layout-item-props)))
|
|
||||||
|
|
||||||
target-cell-id
|
target-cell-id
|
||||||
(if (and (nil? target-cell-id)
|
(if (and (nil? target-cell-id)
|
||||||
|
@ -88,13 +98,15 @@
|
||||||
:id))
|
:id))
|
||||||
target-cell-id)
|
target-cell-id)
|
||||||
|
|
||||||
attrs {:type :frame
|
attrs
|
||||||
|
{:type :frame
|
||||||
:x (:x srect)
|
:x (:x srect)
|
||||||
:y (:y srect)
|
:y (:y srect)
|
||||||
:width (:width srect)
|
:width (:width srect)
|
||||||
:height (:height srect)}
|
:height (:height srect)}
|
||||||
|
|
||||||
shape (cts/setup-shape
|
shape
|
||||||
|
(cts/setup-shape
|
||||||
(cond-> attrs
|
(cond-> attrs
|
||||||
(some? id)
|
(some? id)
|
||||||
(assoc :id id)
|
(assoc :id id)
|
||||||
|
@ -113,13 +125,14 @@
|
||||||
(or (not= frame-id uuid/zero) without-fill?)
|
(or (not= frame-id uuid/zero) without-fill?)
|
||||||
(assoc :fills [] :hide-in-viewer true)))
|
(assoc :fills [] :hide-in-viewer true)))
|
||||||
|
|
||||||
shape (with-meta shape {:index new-index})
|
shape
|
||||||
|
(with-meta shape {:index new-index})
|
||||||
|
|
||||||
[shape changes]
|
[shape changes]
|
||||||
(prepare-add-shape changes shape objects)
|
(prepare-add-shape changes shape objects)
|
||||||
|
|
||||||
changes
|
changes
|
||||||
(prepare-move-shapes-into-frame changes (:id shape) selected objects)
|
(prepare-move-shapes-into-frame changes (:id shape) selected' objects)
|
||||||
|
|
||||||
changes
|
changes
|
||||||
(cond-> changes
|
(cond-> changes
|
||||||
|
@ -143,7 +156,7 @@
|
||||||
|
|
||||||
(pcb/reorder-grid-children [(:parent-id shape)])))]
|
(pcb/reorder-grid-children [(:parent-id shape)])))]
|
||||||
|
|
||||||
[shape changes])))))
|
[shape changes]))))
|
||||||
|
|
||||||
|
|
||||||
(defn prepare-create-empty-artboard
|
(defn prepare-create-empty-artboard
|
||||||
|
|
|
@ -72,13 +72,15 @@
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
shapes (->> shapes (remove #(dm/get-in objects [% :blocked])))
|
shapes (->> shapes
|
||||||
|
(remove #(dm/get-in objects [% :blocked]))
|
||||||
|
(cfh/order-by-indexed-shapes objects))
|
||||||
|
|
||||||
changes (-> (pcb/empty-changes it page-id)
|
changes (-> (pcb/empty-changes it page-id)
|
||||||
(pcb/with-objects objects))
|
(pcb/with-objects objects))
|
||||||
changes (cfsh/prepare-move-shapes-into-frame changes
|
|
||||||
frame-id
|
changes (cfsh/prepare-move-shapes-into-frame changes frame-id shapes objects)]
|
||||||
shapes
|
|
||||||
objects)]
|
|
||||||
(if (some? changes)
|
(if (some? changes)
|
||||||
(rx/of (dch/commit-changes changes))
|
(rx/of (dch/commit-changes changes))
|
||||||
(rx/empty))))))
|
(rx/empty))))))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue