mirror of
https://github.com/penpot/penpot.git
synced 2025-01-24 07:29:08 -05:00
⚡ Improved performance for hover shapes
This commit is contained in:
parent
4f09688af7
commit
9e24ba7b39
2 changed files with 105 additions and 81 deletions
|
@ -176,11 +176,11 @@
|
||||||
(->> (get-root-shapes objects)
|
(->> (get-root-shapes objects)
|
||||||
(mapv :id)))
|
(mapv :id)))
|
||||||
|
|
||||||
(defn get-base
|
(defn- get-base
|
||||||
[objects id-a id-b]
|
[id-a id-b id-parents]
|
||||||
|
|
||||||
(let [[parents-a parents-a-index] (cfh/get-parent-ids-with-index objects id-a)
|
(let [[parents-a parents-a-index] (get id-parents id-a)
|
||||||
[parents-b parents-b-index] (cfh/get-parent-ids-with-index objects id-b)
|
[parents-b parents-b-index] (get id-parents id-b)
|
||||||
|
|
||||||
parents-a (cons id-a parents-a)
|
parents-a (cons id-a parents-a)
|
||||||
parents-b (into #{id-b} parents-b)
|
parents-b (into #{id-b} parents-b)
|
||||||
|
@ -194,9 +194,9 @@
|
||||||
[base-id idx-a idx-b]))
|
[base-id idx-a idx-b]))
|
||||||
|
|
||||||
(defn- is-shape-over-shape?
|
(defn- is-shape-over-shape?
|
||||||
[objects base-shape-id over-shape-id bottom-frames?]
|
[objects base-shape-id over-shape-id bottom-frames? id-parents]
|
||||||
|
|
||||||
(let [[base-id index-a index-b] (get-base objects base-shape-id over-shape-id)]
|
(let [[base-id index-a index-b] (get-base base-shape-id over-shape-id id-parents)]
|
||||||
(cond
|
(cond
|
||||||
;; The base the base shape, so the other item is below (if not bottom-frames)
|
;; The base the base shape, so the other item is below (if not bottom-frames)
|
||||||
(= base-id base-shape-id)
|
(= base-id base-shape-id)
|
||||||
|
@ -234,33 +234,37 @@
|
||||||
|
|
||||||
([objects ids {:keys [bottom-frames?] :as options
|
([objects ids {:keys [bottom-frames?] :as options
|
||||||
:or {bottom-frames? false}}]
|
:or {bottom-frames? false}}]
|
||||||
|
;; Create an index of the parents of the shapes. This will speed the sorting because we use
|
||||||
|
;; this information down the line.
|
||||||
|
(let [id-parents (into {} (map #(vector % (cfh/get-parent-ids-with-index objects %))) ids)]
|
||||||
(letfn [(comp [id-a id-b]
|
(letfn [(comp [id-a id-b]
|
||||||
(cond
|
(cond
|
||||||
(= id-a id-b)
|
(= id-a id-b)
|
||||||
0
|
0
|
||||||
|
|
||||||
(is-shape-over-shape? objects id-a id-b bottom-frames?)
|
(is-shape-over-shape? objects id-a id-b bottom-frames? id-parents)
|
||||||
1
|
1
|
||||||
|
|
||||||
:else
|
:else
|
||||||
-1))]
|
-1))]
|
||||||
(sort comp ids))))
|
(sort comp ids)))))
|
||||||
|
|
||||||
(defn sort-z-index-objects
|
(defn sort-z-index-objects
|
||||||
([objects items]
|
([objects items]
|
||||||
(sort-z-index-objects objects items nil))
|
(sort-z-index-objects objects items nil))
|
||||||
([objects items {:keys [bottom-frames?]
|
([objects items {:keys [bottom-frames?]
|
||||||
:or {bottom-frames? false}}]
|
:or {bottom-frames? false}}]
|
||||||
|
(let [id-parents (into {} (map #(vector (dm/get-prop % :id) (cfh/get-parent-ids-with-index objects (dm/get-prop % :id)))) items)]
|
||||||
(d/unstable-sort
|
(d/unstable-sort
|
||||||
(fn [obj-a obj-b]
|
(fn [obj-a obj-b]
|
||||||
(let [id-a (dm/get-prop obj-a :id)
|
(let [id-a (dm/get-prop obj-a :id)
|
||||||
id-b (dm/get-prop obj-b :id)]
|
id-b (dm/get-prop obj-b :id)]
|
||||||
(if (= id-a id-b)
|
(if (= id-a id-b)
|
||||||
0
|
0
|
||||||
(if ^boolean (is-shape-over-shape? objects id-a id-b bottom-frames?)
|
(if ^boolean (is-shape-over-shape? objects id-a id-b bottom-frames? id-parents)
|
||||||
1
|
1
|
||||||
-1))))
|
-1))))
|
||||||
items)))
|
items))))
|
||||||
|
|
||||||
(defn get-frame-by-position
|
(defn get-frame-by-position
|
||||||
([objects position]
|
([objects position]
|
||||||
|
|
|
@ -159,7 +159,6 @@
|
||||||
[group-id objects hover-ids]
|
[group-id objects hover-ids]
|
||||||
|
|
||||||
(and (contains? #{:group :bool} (get-in objects [group-id :type]))
|
(and (contains? #{:group :bool} (get-in objects [group-id :type]))
|
||||||
|
|
||||||
;; If there are no children in the hover-ids we're in the empty side
|
;; If there are no children in the hover-ids we're in the empty side
|
||||||
(->> hover-ids
|
(->> hover-ids
|
||||||
(remove #(contains? #{:group :bool} (get-in objects [% :type])))
|
(remove #(contains? #{:group :bool} (get-in objects [% :type])))
|
||||||
|
@ -253,6 +252,8 @@
|
||||||
(fn [_]
|
(fn [_]
|
||||||
(reset! hover-top-frame-id (ctt/top-nested-frame objects (deref last-point-ref)))))
|
(reset! hover-top-frame-id (ctt/top-nested-frame objects (deref last-point-ref)))))
|
||||||
|
|
||||||
|
;; This ref is a cache of sorted ids. Sorting is expensive so we save the list
|
||||||
|
(let [sorted-ids-cache (mf/use-ref {})]
|
||||||
(hooks/use-stream
|
(hooks/use-stream
|
||||||
over-shapes-stream
|
over-shapes-stream
|
||||||
(mf/deps page-id objects show-measures?)
|
(mf/deps page-id objects show-measures?)
|
||||||
|
@ -260,12 +261,22 @@
|
||||||
(let [selected (mf/ref-val selected-ref)
|
(let [selected (mf/ref-val selected-ref)
|
||||||
focus (mf/ref-val focus-ref)
|
focus (mf/ref-val focus-ref)
|
||||||
mod? (mf/ref-val mod-ref)
|
mod? (mf/ref-val mod-ref)
|
||||||
|
cached-ids (mf/ref-val sorted-ids-cache)
|
||||||
|
|
||||||
ids (into (d/ordered-set)
|
make-sorted-ids
|
||||||
(remove #(dm/get-in objects [% :blocked]))
|
(fn [mod? ids]
|
||||||
(ctt/sort-z-index objects ids {:bottom-frames? mod?}))
|
(let [sorted-ids
|
||||||
|
(into (d/ordered-set)
|
||||||
|
(comp (remove #(dm/get-in objects [% :blocked]))
|
||||||
|
(remove (partial cfh/svg-raw-shape? objects)))
|
||||||
|
(ctt/sort-z-index objects ids {:bottom-frames? mod?}))]
|
||||||
|
(mf/set-ref-val! sorted-ids-cache (assoc cached-ids [mod? ids] sorted-ids))
|
||||||
|
sorted-ids))
|
||||||
|
|
||||||
grouped? (fn [id]
|
ids (or (get cached-ids [mod? ids]) (make-sorted-ids mod? ids))
|
||||||
|
|
||||||
|
grouped?
|
||||||
|
(fn [id]
|
||||||
(and (cfh/group-shape? objects id)
|
(and (cfh/group-shape? objects id)
|
||||||
(not (cfh/mask-shape? objects id))))
|
(not (cfh/mask-shape? objects id))))
|
||||||
|
|
||||||
|
@ -286,8 +297,14 @@
|
||||||
(filter grouped?)
|
(filter grouped?)
|
||||||
|
|
||||||
(not mod?)
|
(not mod?)
|
||||||
|
(let [child-parent?
|
||||||
|
(into #{}
|
||||||
|
(comp (remove #(cfh/group-like-shape? objects %))
|
||||||
|
(mapcat #(cfh/get-parent-ids objects %)))
|
||||||
|
ids)]
|
||||||
(filter #(or (root-frame-with-data? %)
|
(filter #(or (root-frame-with-data? %)
|
||||||
(group-empty-space? % objects ids))))
|
(and (contains? #{:group :bool} (dm/get-in objects [% :type]))
|
||||||
|
(not (contains? child-parent? %)))))))
|
||||||
|
|
||||||
remove-id?
|
remove-id?
|
||||||
(into selected-with-parents remove-id-xf ids)
|
(into selected-with-parents remove-id-xf ids)
|
||||||
|
@ -303,7 +320,6 @@
|
||||||
(->> ids
|
(->> ids
|
||||||
(remove remove-id?)
|
(remove remove-id?)
|
||||||
(remove (partial cfh/hidden-parent? objects))
|
(remove (partial cfh/hidden-parent? objects))
|
||||||
(remove (partial cfh/svg-raw-shape? objects))
|
|
||||||
(remove #(and mod? (no-fill-nested-frames? %)))
|
(remove #(and mod? (no-fill-nested-frames? %)))
|
||||||
(filter #(or (empty? focus) (cpf/is-in-focus? objects focus %)))
|
(filter #(or (empty? focus) (cpf/is-in-focus? objects focus %)))
|
||||||
(first)
|
(first)
|
||||||
|
@ -315,15 +331,19 @@
|
||||||
(->> ids
|
(->> ids
|
||||||
(remove #(group-empty-space? % objects ids))
|
(remove #(group-empty-space? % objects ids))
|
||||||
(remove (partial cfh/hidden-parent? objects))
|
(remove (partial cfh/hidden-parent? objects))
|
||||||
(remove (partial cfh/svg-raw-shape? objects))
|
|
||||||
(remove #(and mod? (no-fill-nested-frames? %)))
|
(remove #(and mod? (no-fill-nested-frames? %)))
|
||||||
(filter #(or (empty? focus) (cpf/is-in-focus? objects focus %)))
|
(filter #(or (empty? focus) (cpf/is-in-focus? objects focus %)))
|
||||||
(first)
|
(first)
|
||||||
(get objects)))]
|
(get objects)))]
|
||||||
|
|
||||||
|
|
||||||
(reset! hover hover-shape)
|
(reset! hover hover-shape)
|
||||||
(reset! measure-hover measure-hover-shape)
|
(reset! measure-hover measure-hover-shape)
|
||||||
(reset! hover-ids ids))))))
|
(reset! hover-ids ids)))
|
||||||
|
|
||||||
|
(fn []
|
||||||
|
;; Clean the cache
|
||||||
|
(mf/set-ref-val! sorted-ids-cache {}))))))
|
||||||
|
|
||||||
(defn setup-viewport-modifiers
|
(defn setup-viewport-modifiers
|
||||||
[modifiers objects]
|
[modifiers objects]
|
||||||
|
|
Loading…
Add table
Reference in a new issue