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:
parent
4f09688af7
commit
9e24ba7b39
2 changed files with 105 additions and 81 deletions
|
@ -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}}]
|
||||
(letfn [(comp [id-a id-b]
|
||||
(cond
|
||||
(= id-a id-b)
|
||||
0
|
||||
;; 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?)
|
||||
1
|
||||
(is-shape-over-shape? objects id-a id-b bottom-frames? id-parents)
|
||||
1
|
||||
|
||||
:else
|
||||
-1))]
|
||||
(sort comp ids))))
|
||||
:else
|
||||
-1))]
|
||||
(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}}]
|
||||
(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?)
|
||||
1
|
||||
-1))))
|
||||
items)))
|
||||
(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? id-parents)
|
||||
1
|
||||
-1))))
|
||||
items))))
|
||||
|
||||
(defn get-frame-by-position
|
||||
([objects position]
|
||||
|
|
|
@ -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,77 +252,98 @@
|
|||
(fn [_]
|
||||
(reset! hover-top-frame-id (ctt/top-nested-frame objects (deref last-point-ref)))))
|
||||
|
||||
(hooks/use-stream
|
||||
over-shapes-stream
|
||||
(mf/deps page-id objects show-measures?)
|
||||
(fn [ids]
|
||||
(let [selected (mf/ref-val selected-ref)
|
||||
focus (mf/ref-val focus-ref)
|
||||
mod? (mf/ref-val mod-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?)
|
||||
(fn [ids]
|
||||
(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]
|
||||
(and (cfh/group-shape? objects id)
|
||||
(not (cfh/mask-shape? objects id))))
|
||||
ids (or (get cached-ids [mod? ids]) (make-sorted-ids mod? ids))
|
||||
|
||||
selected-with-parents
|
||||
(into #{} (mapcat #(cfh/get-parent-ids objects %)) selected)
|
||||
grouped?
|
||||
(fn [id]
|
||||
(and (cfh/group-shape? objects id)
|
||||
(not (cfh/mask-shape? objects id))))
|
||||
|
||||
root-frame-with-data?
|
||||
#(as-> (get objects %) obj
|
||||
(and (cfh/root-frame? obj)
|
||||
(d/not-empty? (:shapes obj))
|
||||
(not (ctk/instance-head? obj))
|
||||
(not (ctk/main-instance? obj))))
|
||||
selected-with-parents
|
||||
(into #{} (mapcat #(cfh/get-parent-ids objects %)) selected)
|
||||
|
||||
;; Set with the elements to remove from the hover list
|
||||
remove-id-xf
|
||||
(cond
|
||||
mod?
|
||||
(filter grouped?)
|
||||
root-frame-with-data?
|
||||
#(as-> (get objects %) obj
|
||||
(and (cfh/root-frame? obj)
|
||||
(d/not-empty? (:shapes obj))
|
||||
(not (ctk/instance-head? obj))
|
||||
(not (ctk/main-instance? obj))))
|
||||
|
||||
(not mod?)
|
||||
(filter #(or (root-frame-with-data? %)
|
||||
(group-empty-space? % objects ids))))
|
||||
;; Set with the elements to remove from the hover list
|
||||
remove-id-xf
|
||||
(cond
|
||||
mod?
|
||||
(filter grouped?)
|
||||
|
||||
remove-id?
|
||||
(into selected-with-parents remove-id-xf ids)
|
||||
(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? %)
|
||||
(and (contains? #{:group :bool} (dm/get-in objects [% :type]))
|
||||
(not (contains? child-parent? %)))))))
|
||||
|
||||
no-fill-nested-frames?
|
||||
(fn [id]
|
||||
(let [shape (get objects id)]
|
||||
(and (cfh/frame-shape? shape)
|
||||
(not (cfh/is-direct-child-of-root? shape))
|
||||
(empty? (get shape :fills)))))
|
||||
remove-id?
|
||||
(into selected-with-parents remove-id-xf ids)
|
||||
|
||||
hover-shape
|
||||
(->> 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)
|
||||
(get objects))
|
||||
no-fill-nested-frames?
|
||||
(fn [id]
|
||||
(let [shape (get objects id)]
|
||||
(and (cfh/frame-shape? shape)
|
||||
(not (cfh/is-direct-child-of-root? shape))
|
||||
(empty? (get shape :fills)))))
|
||||
|
||||
;; We keep track of a diferent shape for measures
|
||||
measure-hover-shape
|
||||
(when show-measures?
|
||||
hover-shape
|
||||
(->> ids
|
||||
(remove #(group-empty-space? % objects 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)
|
||||
(get objects)))]
|
||||
(get objects))
|
||||
|
||||
(reset! hover hover-shape)
|
||||
(reset! measure-hover measure-hover-shape)
|
||||
(reset! hover-ids ids))))))
|
||||
;; We keep track of a diferent shape for measures
|
||||
measure-hover-shape
|
||||
(when show-measures?
|
||||
(->> ids
|
||||
(remove #(group-empty-space? % objects ids))
|
||||
(remove (partial cfh/hidden-parent? 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)))
|
||||
|
||||
(fn []
|
||||
;; Clean the cache
|
||||
(mf/set-ref-val! sorted-ids-cache {}))))))
|
||||
|
||||
(defn setup-viewport-modifiers
|
||||
[modifiers objects]
|
||||
|
|
Loading…
Add table
Reference in a new issue