mirror of
https://github.com/penpot/penpot.git
synced 2025-01-22 14:39:45 -05: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)
|
||||
: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
|
||||
(defmethod print-method clojure.lang.PersistentQueue [q, w]
|
||||
;; Overload the printer for queues so they look like fish
|
||||
|
|
|
@ -484,7 +484,7 @@
|
|||
(letfn [(red-fn [cur-idx id]
|
||||
(let [[prev-idx _] (first cur-idx)
|
||||
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]
|
||||
(let [object (get objects id)]
|
||||
|
@ -509,10 +509,11 @@
|
|||
|
||||
(defn order-by-indexed-shapes
|
||||
[objects ids]
|
||||
(let [ids (if (set? ids) ids (set ids))]
|
||||
(->> (indexed-shapes objects)
|
||||
(sort-by first)
|
||||
(filter (comp (into #{} ids) second))
|
||||
(map second)))
|
||||
(filter (fn [o] (contains? ids (val o))))
|
||||
(sort-by key)
|
||||
(map val))))
|
||||
|
||||
(defn get-index-replacement
|
||||
"Given a collection of shapes, calculate their positions
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
(ns app.common.files.libraries-helpers
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.files.changes-builder :as pcb]
|
||||
[app.common.files.helpers :as cfh]
|
||||
[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
|
||||
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]
|
||||
|
||||
(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]
|
||||
(if (and (= (count shapes) 1)
|
||||
(or (and (= (:type (first shapes)) :group) (not components-v2))
|
||||
(= (:type (first shapes)) :frame))
|
||||
(not (ctk/instance-head? (first shapes))))
|
||||
|
||||
[(first shapes)
|
||||
(if (and (= shapes-count 1)
|
||||
(or (and (cfh/group-shape? first-shape)
|
||||
(not components-v2))
|
||||
(cfh/frame-shape? first-shape))
|
||||
(not (ctk/instance-head? first-shape)))
|
||||
[first-shape
|
||||
(-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-objects objects))
|
||||
(:shapes (first shapes))]
|
||||
(:shapes first-shape)]
|
||||
|
||||
(let [root-name (if (= 1 (count shapes))
|
||||
(:name (first shapes))
|
||||
(let [root-name (if (= 1 shapes-count)
|
||||
(:name first-shape)
|
||||
"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
|
||||
objects ; to avoid a circular dependence
|
||||
page-id
|
||||
shapes
|
||||
root-name
|
||||
(not (ctk/instance-head? (first shapes))))
|
||||
(not (ctk/instance-head? first-shape)))
|
||||
(prepare-create-board changes
|
||||
(uuid/next)
|
||||
(:parent-id (first shapes))
|
||||
(:parent-id first-shape)
|
||||
objects
|
||||
(map :id shapes)
|
||||
shape-ids
|
||||
nil
|
||||
root-name
|
||||
true))]
|
||||
|
||||
[root changes (map :id shapes)]))
|
||||
[root changes shape-ids]))
|
||||
|
||||
changes
|
||||
(cond-> changes
|
||||
|
@ -79,8 +89,7 @@
|
|||
(pcb/update-shapes
|
||||
(:shapes root)
|
||||
(fn [shape]
|
||||
(-> shape
|
||||
(assoc :constraints-h :scale :constraints-v :scale)))))
|
||||
(assoc shape :constraints-h :scale :constraints-v :scale))))
|
||||
|
||||
objects' (assoc objects (:id root) root)
|
||||
|
||||
|
|
|
@ -39,16 +39,17 @@
|
|||
|
||||
(defn prepare-move-shapes-into-frame
|
||||
[changes frame-id shapes objects]
|
||||
(let [ordered-indexes (cfh/order-by-indexed-shapes objects shapes)
|
||||
parent-id (get-in objects [frame-id :parent-id])
|
||||
ordered-indexes (->> ordered-indexes (remove #(= % parent-id)))
|
||||
to-move-shapes (map (d/getf objects) ordered-indexes)]
|
||||
(if (d/not-empty? to-move-shapes)
|
||||
(let [parent-id (dm/get-in objects [frame-id :parent-id])
|
||||
shapes (remove #(= % parent-id) shapes)
|
||||
to-move (->> shapes
|
||||
(map (d/getf objects))
|
||||
(not-empty))]
|
||||
(if to-move
|
||||
(-> changes
|
||||
(cond-> (not (ctl/any-layout? objects frame-id))
|
||||
(pcb/update-shapes ordered-indexes ctl/remove-layout-item-data))
|
||||
(pcb/update-shapes ordered-indexes #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true)))
|
||||
(pcb/change-parent frame-id to-move-shapes 0)
|
||||
(pcb/update-shapes shapes ctl/remove-layout-item-data))
|
||||
(pcb/update-shapes shapes #(cond-> % (cfh/frame-shape? %) (assoc :hide-in-viewer true)))
|
||||
(pcb/change-parent frame-id to-move 0)
|
||||
(cond-> (ctl/grid-layout? objects frame-id)
|
||||
(-> (pcb/update-shapes [frame-id] ctl/assign-cells {:with-objects? true})
|
||||
(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? target-cell-id]
|
||||
(let [selected-objs (map #(get objects %) selected)
|
||||
new-index (or index
|
||||
(cfh/get-index-replacement selected objects))]
|
||||
(when (d/not-empty? selected)
|
||||
(let [srect (gsh/shapes->rect selected-objs)
|
||||
selected-id (first selected)
|
||||
(when-let [selected-objs (->> selected
|
||||
(map (d/getf objects))
|
||||
(not-empty))]
|
||||
|
||||
frame-id (dm/get-in objects [selected-id :frame-id])
|
||||
parent-id (or parent-id (dm/get-in objects [selected-id :parent-id]))
|
||||
(let [;; We calculate here the ordered selection because it is used
|
||||
;; 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)
|
||||
|
||||
layout-props
|
||||
(when (and (= 1 (count selected))
|
||||
(ctl/any-layout? base-parent))
|
||||
(let [shape (get objects selected-id)]
|
||||
(select-keys shape ctl/layout-item-props)))
|
||||
(select-keys selected-obj ctl/layout-item-props))
|
||||
|
||||
target-cell-id
|
||||
(if (and (nil? target-cell-id)
|
||||
|
@ -88,13 +98,15 @@
|
|||
:id))
|
||||
target-cell-id)
|
||||
|
||||
attrs {:type :frame
|
||||
attrs
|
||||
{:type :frame
|
||||
:x (:x srect)
|
||||
:y (:y srect)
|
||||
:width (:width srect)
|
||||
:height (:height srect)}
|
||||
|
||||
shape (cts/setup-shape
|
||||
shape
|
||||
(cts/setup-shape
|
||||
(cond-> attrs
|
||||
(some? id)
|
||||
(assoc :id id)
|
||||
|
@ -113,13 +125,14 @@
|
|||
(or (not= frame-id uuid/zero) without-fill?)
|
||||
(assoc :fills [] :hide-in-viewer true)))
|
||||
|
||||
shape (with-meta shape {:index new-index})
|
||||
shape
|
||||
(with-meta shape {:index new-index})
|
||||
|
||||
[shape changes]
|
||||
(prepare-add-shape changes shape objects)
|
||||
|
||||
changes
|
||||
(prepare-move-shapes-into-frame changes (:id shape) selected objects)
|
||||
(prepare-move-shapes-into-frame changes (:id shape) selected' objects)
|
||||
|
||||
changes
|
||||
(cond-> changes
|
||||
|
@ -143,7 +156,7 @@
|
|||
|
||||
(pcb/reorder-grid-children [(:parent-id shape)])))]
|
||||
|
||||
[shape changes])))))
|
||||
[shape changes]))))
|
||||
|
||||
|
||||
(defn prepare-create-empty-artboard
|
||||
|
|
|
@ -72,13 +72,15 @@
|
|||
(watch [it state _]
|
||||
(let [page-id (:current-page-id state)
|
||||
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)
|
||||
(pcb/with-objects objects))
|
||||
changes (cfsh/prepare-move-shapes-into-frame changes
|
||||
frame-id
|
||||
shapes
|
||||
objects)]
|
||||
|
||||
changes (cfsh/prepare-move-shapes-into-frame changes frame-id shapes objects)]
|
||||
|
||||
(if (some? changes)
|
||||
(rx/of (dch/commit-changes changes))
|
||||
(rx/empty))))))
|
||||
|
|
Loading…
Add table
Reference in a new issue