mirror of
https://github.com/penpot/penpot.git
synced 2025-02-12 18:18:24 -05:00
⚡ Performance improvements
This commit is contained in:
parent
91fe0b0985
commit
b2e01cd52b
7 changed files with 122 additions and 139 deletions
|
@ -174,9 +174,17 @@
|
|||
"Checks if the given rect overlaps with the path in any point"
|
||||
[shape rect]
|
||||
|
||||
(let [rect-points (gpr/rect->points rect)
|
||||
(let [;; If paths are too complex the intersection is too expensive
|
||||
;; we fallback to check its bounding box otherwise the performance penalty
|
||||
;; is too big
|
||||
;; TODO: Look for ways to optimize this operation
|
||||
simple? (> (count (:content shape)) 100)
|
||||
|
||||
rect-points (gpr/rect->points rect)
|
||||
rect-lines (points->lines rect-points)
|
||||
path-lines (gpp/path->lines shape)
|
||||
path-lines (if simple?
|
||||
(points->lines (:points shape))
|
||||
(gpp/path->lines shape))
|
||||
start-point (-> shape :content (first) :params (gpt/point))]
|
||||
|
||||
(or (is-point-inside-nonzero? (first rect-points) path-lines)
|
||||
|
|
|
@ -46,7 +46,7 @@ http {
|
|||
listen 3449 default_server;
|
||||
server_name _;
|
||||
|
||||
client_max_body_size 5M;
|
||||
client_max_body_size 20M;
|
||||
charset utf-8;
|
||||
|
||||
proxy_http_version 1.1;
|
||||
|
|
|
@ -1164,11 +1164,15 @@
|
|||
(ptk/reify ::update-shape-flags
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(letfn [(update-fn [obj]
|
||||
(cond-> obj
|
||||
(boolean? blocked) (assoc :blocked blocked)
|
||||
(boolean? hidden) (assoc :hidden hidden)))]
|
||||
(rx/of (dch/update-shapes-recursive [id] update-fn))))))
|
||||
(let [update-fn
|
||||
(fn [obj]
|
||||
(cond-> obj
|
||||
(boolean? blocked) (assoc :blocked blocked)
|
||||
(boolean? hidden) (assoc :hidden hidden)))
|
||||
|
||||
objects (wsh/lookup-page-objects state)
|
||||
ids (d/concat [id] (cp/get-children id objects))]
|
||||
(rx/of (dch/update-shapes ids update-fn))))))
|
||||
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[app.common.pages.spec :as spec]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.workspace.undo :as dwu]
|
||||
[app.main.data.workspace.state-helpers :as wsh]
|
||||
[app.main.worker :as uw]
|
||||
[app.main.store :as st]
|
||||
[app.util.logging :as log]
|
||||
|
@ -31,127 +32,75 @@
|
|||
|
||||
(def commit-changes? (ptk/type? ::commit-changes))
|
||||
|
||||
(defn- generate-operations
|
||||
([ma mb] (generate-operations ma mb false))
|
||||
([ma mb undo?]
|
||||
(let [ops (let [ma-keys (set (keys ma))
|
||||
mb-keys (set (keys mb))
|
||||
added (set/difference mb-keys ma-keys)
|
||||
removed (set/difference ma-keys mb-keys)
|
||||
both (set/intersection ma-keys mb-keys)]
|
||||
(d/concat
|
||||
(mapv #(array-map :type :set :attr % :val (get mb %)) added)
|
||||
(mapv #(array-map :type :set :attr % :val nil) removed)
|
||||
(loop [items (seq both)
|
||||
result []]
|
||||
(if items
|
||||
(let [k (first items)
|
||||
vma (get ma k)
|
||||
vmb (get mb k)]
|
||||
(if (= vma vmb)
|
||||
(recur (next items) result)
|
||||
(recur (next items)
|
||||
(conj result {:type :set
|
||||
:attr k
|
||||
:val vmb
|
||||
:ignore-touched undo?}))))
|
||||
result))))]
|
||||
(if undo?
|
||||
(conj ops {:type :set-touched :touched (:touched mb)})
|
||||
ops))))
|
||||
(defn- generate-operation
|
||||
"Given an object old and new versions and an attribute will append into changes
|
||||
the set and undo operations"
|
||||
[changes attr old new]
|
||||
(let [old-val (get old attr)
|
||||
new-val (get new attr)]
|
||||
(if (= old-val new-val)
|
||||
changes
|
||||
(-> changes
|
||||
(update :rops conj {:type :set :attr attr :val new-val})
|
||||
(update :uops conj {:type :set :attr attr :val old-val :ignore-touched true})))))
|
||||
|
||||
(defn- update-shape-changes
|
||||
"Calculate the changes and undos to be done when a function is applied to a
|
||||
single object"
|
||||
[changes page-id objects update-fn attrs id]
|
||||
(let [old-obj (get objects id)
|
||||
new-obj (update-fn old-obj)
|
||||
|
||||
attrs (or attrs (d/concat #{} (keys old-obj) (keys new-obj)))
|
||||
|
||||
{rops :rops uops :uops}
|
||||
(reduce #(generate-operation %1 %2 old-obj new-obj)
|
||||
{:rops [] :uops []}
|
||||
attrs)
|
||||
|
||||
uops (cond-> uops
|
||||
(not (empty? uops))
|
||||
(conj {:type :set-touched :touched (:touched old-obj)}))
|
||||
|
||||
change {:type :mod-obj :page-id page-id :id id}]
|
||||
|
||||
(cond-> changes
|
||||
(not (empty? rops))
|
||||
(update :rch conj (assoc change :operations rops))
|
||||
|
||||
(not (empty? uops))
|
||||
(update :uch conj (assoc change :operations uops)))))
|
||||
|
||||
(defn update-shapes
|
||||
([ids f] (update-shapes ids f nil))
|
||||
([ids f {:keys [reg-objects? save-undo?]
|
||||
:or {reg-objects? false save-undo? true}}]
|
||||
([ids f {:keys [reg-objects? save-undo? keys]
|
||||
:or {reg-objects? false save-undo? true attrs nil}}]
|
||||
|
||||
(us/assert ::coll-of-uuid ids)
|
||||
(us/assert fn? f)
|
||||
|
||||
(ptk/reify ::update-shapes
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
reg-objects {:type :reg-objects :page-id page-id :shapes (vec ids)}]
|
||||
(loop [ids (seq ids)
|
||||
rch []
|
||||
uch []]
|
||||
(if (nil? ids)
|
||||
(rx/of (let [has-rch? (not (empty? rch))
|
||||
has-uch? (not (empty? uch))
|
||||
rch (cond-> rch (and has-rch? reg-objects?) (conj reg-objects))
|
||||
uch (cond-> uch (and has-rch? reg-objects?) (conj reg-objects))]
|
||||
(when (and has-rch? has-uch?)
|
||||
(commit-changes {:redo-changes rch
|
||||
:undo-changes uch
|
||||
:origin it
|
||||
:save-undo? save-undo?}))))
|
||||
objects (wsh/lookup-page-objects state)
|
||||
reg-objects {:type :reg-objects :page-id page-id :shapes (vec ids)}
|
||||
|
||||
(let [id (first ids)
|
||||
obj1 (get objects id)
|
||||
obj2 (f obj1)
|
||||
rch-operations (generate-operations obj1 obj2)
|
||||
uch-operations (generate-operations obj2 obj1 true)
|
||||
rchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations rch-operations
|
||||
:id id}
|
||||
uchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations uch-operations
|
||||
:id id}]
|
||||
(recur (next ids)
|
||||
(if (empty? rch-operations) rch (conj rch rchg))
|
||||
(if (empty? uch-operations) uch (conj uch uchg)))))))))))
|
||||
{redo-changes :rch undo-changes :uch}
|
||||
(reduce #(update-shape-changes %1 page-id objects f keys %2)
|
||||
{:rch [] :uch []} ids)]
|
||||
|
||||
(defn update-shapes-recursive
|
||||
[ids f]
|
||||
(us/assert ::coll-of-uuid ids)
|
||||
(us/assert fn? f)
|
||||
(letfn [(impl-get-children [objects id]
|
||||
(cons id (cp/get-children id objects)))
|
||||
(when-not (empty? redo-changes)
|
||||
(let [redo-changes (cond-> redo-changes
|
||||
reg-objects? (conj reg-objects))
|
||||
|
||||
(impl-gen-changes [objects page-id ids]
|
||||
(loop [sids (seq ids)
|
||||
cids (seq (impl-get-children objects (first sids)))
|
||||
rchanges []
|
||||
uchanges []]
|
||||
(cond
|
||||
(nil? sids)
|
||||
[rchanges uchanges]
|
||||
undo-changes (cond-> undo-changes
|
||||
reg-objects? (conj reg-objects))]
|
||||
|
||||
(nil? cids)
|
||||
(recur (next sids)
|
||||
(seq (impl-get-children objects (first (next sids))))
|
||||
rchanges
|
||||
uchanges)
|
||||
|
||||
:else
|
||||
(let [id (first cids)
|
||||
obj1 (get objects id)
|
||||
obj2 (f obj1)
|
||||
rops (generate-operations obj1 obj2)
|
||||
uops (generate-operations obj2 obj1 true)
|
||||
rchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations rops
|
||||
:id id}
|
||||
uchg {:type :mod-obj
|
||||
:page-id page-id
|
||||
:operations uops
|
||||
:id id}]
|
||||
(recur sids
|
||||
(next cids)
|
||||
(conj rchanges rchg)
|
||||
(conj uchanges uchg))))))]
|
||||
(ptk/reify ::update-shapes-recursive
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(let [page-id (:current-page-id state)
|
||||
objects (get-in state [:workspace-data :pages-index page-id :objects])
|
||||
[rchanges uchanges] (impl-gen-changes objects page-id (seq ids))]
|
||||
(rx/of (commit-changes {:redo-changes rchanges
|
||||
:undo-changes uchanges
|
||||
:origin it})))))))
|
||||
(rx/of (commit-changes {:redo-changes redo-changes
|
||||
:undo-changes undo-changes
|
||||
:origin it
|
||||
:save-undo? save-undo?})))))))))
|
||||
|
||||
(defn update-indices
|
||||
[page-id changes]
|
||||
|
@ -222,4 +171,4 @@
|
|||
(when (and save-undo? (seq undo-changes))
|
||||
(let [entry {:undo-changes undo-changes
|
||||
:redo-changes redo-changes}]
|
||||
(rx/of (dwu/append-undo entry)))))))))))
|
||||
(rx/of (dwu/append-undo entry)))))))))))
|
||||
|
|
|
@ -320,8 +320,7 @@
|
|||
(rx/map snap/correct-snap-point)
|
||||
(rx/map start-local-displacement))
|
||||
|
||||
(rx/of (set-modifiers ids)
|
||||
(apply-modifiers ids)
|
||||
(rx/of (apply-modifiers ids {:set-modifiers? true})
|
||||
(calculate-frame-for-move ids)
|
||||
(finish-transform)))))))))
|
||||
|
||||
|
@ -390,8 +389,7 @@
|
|||
(rx/map start-local-displacement))
|
||||
(rx/of (move-selected direction shift?)))
|
||||
|
||||
(rx/of (set-modifiers selected)
|
||||
(apply-modifiers selected)
|
||||
(rx/of (apply-modifiers selected {:set-modifiers? true})
|
||||
(finish-transform))))
|
||||
(rx/empty))))))
|
||||
|
||||
|
@ -469,22 +467,46 @@
|
|||
(rx/of (apply-modifiers ids)))))))
|
||||
|
||||
(defn apply-modifiers
|
||||
[ids]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(ptk/reify ::apply-modifiers
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
children-ids (->> ids (mapcat #(cp/get-children % objects)))
|
||||
ids-with-children (d/concat [] children-ids ids)
|
||||
object-modifiers (get state :workspace-modifiers)]
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/update-shapes ids-with-children (fn [shape]
|
||||
(-> shape
|
||||
(merge (get object-modifiers (:id shape)))
|
||||
(gsh/transform-shape))) {:reg-objects? true})
|
||||
(clear-local-transform)
|
||||
(dwu/commit-undo-transaction))))))
|
||||
([ids]
|
||||
(apply-modifiers ids nil))
|
||||
|
||||
([ids {:keys [set-modifiers?]
|
||||
:or {set-modifiers? false}}]
|
||||
(us/verify (s/coll-of uuid?) ids)
|
||||
(ptk/reify ::apply-modifiers
|
||||
ptk/WatchEvent
|
||||
(watch [it state stream]
|
||||
(let [objects (wsh/lookup-page-objects state)
|
||||
children-ids (->> ids (mapcat #(cp/get-children % objects)))
|
||||
ids-with-children (d/concat [] children-ids ids)
|
||||
|
||||
state (if set-modifiers?
|
||||
(ptk/update (set-modifiers ids) state)
|
||||
state)
|
||||
object-modifiers (get state :workspace-modifiers)]
|
||||
|
||||
(rx/of (dwu/start-undo-transaction)
|
||||
(dch/update-shapes
|
||||
ids-with-children
|
||||
(fn [shape]
|
||||
(-> shape
|
||||
(merge (get object-modifiers (:id shape)))
|
||||
(gsh/transform-shape)))
|
||||
{:reg-objects? true
|
||||
;; Attributes that can change in the transform. This way we don't have to check
|
||||
;; all the attributes
|
||||
:attrs [:selrect :points
|
||||
:x :y
|
||||
:width :height
|
||||
:content
|
||||
:transform
|
||||
:transform-inverse
|
||||
:rotation
|
||||
:flip-x
|
||||
:flip-y]
|
||||
})
|
||||
(clear-local-transform)
|
||||
(dwu/commit-undo-transaction)))))))
|
||||
|
||||
;; --- Update Dimensions
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
(.-parentNode shape-node)
|
||||
|
||||
(and (some? thumb-node) (= :frame type))
|
||||
thumb-node
|
||||
(.-parentNode thumb-node)
|
||||
|
||||
:else
|
||||
shape-node)]
|
||||
|
|
|
@ -122,9 +122,9 @@
|
|||
(into []
|
||||
(comp (map #(unchecked-get % "data"))
|
||||
(filter match-criteria?)
|
||||
(filter overlaps?)
|
||||
(filter (comp overlaps? :frame))
|
||||
(filter (comp overlaps-masks? :masks))
|
||||
(filter overlaps?)
|
||||
(map add-z-index))
|
||||
result)
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue