0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-23 23:18:48 -05:00

Improved performance for hover shapes

This commit is contained in:
alonso.torres 2024-01-23 15:39:37 +01:00 committed by Andrey Antukh
parent 4f09688af7
commit 9e24ba7b39
2 changed files with 105 additions and 81 deletions

View file

@ -176,11 +176,11 @@
(->> (get-root-shapes objects)
(mapv :id)))
(defn get-base
[objects id-a id-b]
(defn- get-base
[id-a id-b id-parents]
(let [[parents-a parents-a-index] (cfh/get-parent-ids-with-index objects id-a)
[parents-b parents-b-index] (cfh/get-parent-ids-with-index objects id-b)
(let [[parents-a parents-a-index] (get id-parents id-a)
[parents-b parents-b-index] (get id-parents id-b)
parents-a (cons id-a parents-a)
parents-b (into #{id-b} parents-b)
@ -194,9 +194,9 @@
[base-id idx-a idx-b]))
(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
;; The base the base shape, so the other item is below (if not bottom-frames)
(= base-id base-shape-id)
@ -234,33 +234,37 @@
([objects ids {:keys [bottom-frames?] :as options
: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]
(cond
(= id-a id-b)
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
:else
-1))]
(sort comp ids))))
(sort comp ids)))))
(defn sort-z-index-objects
([objects items]
(sort-z-index-objects objects items nil))
([objects items {:keys [bottom-frames?]
: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
(fn [obj-a obj-b]
(let [id-a (dm/get-prop obj-a :id)
id-b (dm/get-prop obj-b :id)]
(if (= id-a id-b)
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))))
items)))
items))))
(defn get-frame-by-position
([objects position]

View file

@ -159,7 +159,6 @@
[group-id objects hover-ids]
(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
(->> hover-ids
(remove #(contains? #{:group :bool} (get-in objects [% :type])))
@ -253,6 +252,8 @@
(fn [_]
(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
over-shapes-stream
(mf/deps page-id objects show-measures?)
@ -260,12 +261,22 @@
(let [selected (mf/ref-val selected-ref)
focus (mf/ref-val focus-ref)
mod? (mf/ref-val mod-ref)
cached-ids (mf/ref-val sorted-ids-cache)
ids (into (d/ordered-set)
(remove #(dm/get-in objects [% :blocked]))
(ctt/sort-z-index objects ids {:bottom-frames? mod?}))
make-sorted-ids
(fn [mod? ids]
(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)
(not (cfh/mask-shape? objects id))))
@ -286,8 +297,14 @@
(filter grouped?)
(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? %)
(group-empty-space? % objects ids))))
(and (contains? #{:group :bool} (dm/get-in objects [% :type]))
(not (contains? child-parent? %)))))))
remove-id?
(into selected-with-parents remove-id-xf ids)
@ -303,7 +320,6 @@
(->> ids
(remove remove-id?)
(remove (partial cfh/hidden-parent? objects))
(remove (partial cfh/svg-raw-shape? objects))
(remove #(and mod? (no-fill-nested-frames? %)))
(filter #(or (empty? focus) (cpf/is-in-focus? objects focus %)))
(first)
@ -315,15 +331,19 @@
(->> ids
(remove #(group-empty-space? % objects ids))
(remove (partial cfh/hidden-parent? objects))
(remove (partial cfh/svg-raw-shape? objects))
(remove #(and mod? (no-fill-nested-frames? %)))
(filter #(or (empty? focus) (cpf/is-in-focus? objects focus %)))
(first)
(get objects)))]
(reset! hover 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
[modifiers objects]