From da55d6723c2e5da9312f891e259acf8ea0ce0378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Torr=C3=B3?= Date: Fri, 2 Oct 2026 12:24:04 +0200 Subject: [PATCH] :zap: Reduce per-frame CLJS work while dragging (#12027) Memoize snap points and frame titles on the base objects and compute the drag target frames once per gesture. --- .../app/main/data/workspace/transforms.cljs | 25 ++++++++++++++++--- .../src/app/main/ui/workspace/viewport.cljs | 2 ++ .../ui/workspace/viewport/snap_points.cljs | 5 ++-- .../main/ui/workspace/viewport/widgets.cljs | 6 +++-- .../app/main/ui/workspace/viewport_wasm.cljs | 2 ++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index 5e5c033329..e5bcaa1c8a 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -839,8 +839,9 @@ exclude-frames (into #{} - (filter (partial cfh/frame-shape? objects)) - (cfh/selected-with-children objects selected)) + (comp (mapcat #(cfh/get-children-ids-with-self objects %)) + (filter (partial cfh/frame-shape? objects))) + selected) exclude-frames-siblings (into exclude-frames @@ -848,6 +849,21 @@ (filter (partial ctl/any-layout-immediate-child-id? objects))) selected) + ;; Frame lookups per pointer move only test frames that can be a target + frames + (ctst/get-frames objects) + + with-target-frames + (fn [excluded] + (vary-meta objects assoc ::ctst/index-frames + (into [] (remove #(contains? excluded (:id %))) frames))) + + target-objects + (with-target-frames exclude-frames) + + target-objects-siblings + (with-target-frames exclude-frames-siblings) + position (->> ms/mouse-position (rx/map #(gpt/to-vec from-position %))) @@ -891,8 +907,9 @@ (rx/map (fn [[move-vector mod?]] (let [position (gpt/add from-position move-vector) - exclude-frames (if mod? exclude-frames exclude-frames-siblings) - target-frame (ctst/top-nested-frame objects position exclude-frames) + target-frame (if mod? + (ctst/top-nested-frame target-objects position) + (ctst/top-nested-frame target-objects-siblings position)) [target-frame _] (ctn/find-valid-parent-and-frame-ids target-frame objects shapes false libraries parent-validation-cache) flex-layout? (ctl/flex-layout? objects target-frame) grid-layout? (ctl/grid-layout? objects target-frame) diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index cd2ef3ca88..ad3e1b987f 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -592,6 +592,7 @@ [:> widgets/frame-titles* {:objects base-objects + :base-objects base-objects :selected selected :zoom zoom :is-show-artboard-names show-artboard-names? @@ -637,6 +638,7 @@ :page-id page-id :selected selected :objects objects-modified + :base-objects base-objects :focus focus}]) (when show-snap-distance? diff --git a/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs b/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs index 409a6ad153..063890d84e 100644 --- a/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/snap_points.cljs @@ -158,12 +158,13 @@ (mf/defc snap-points* {::mf/wrap [mf/memo]} - [{:keys [layout zoom objects selected page-id drawing focus]}] + [{:keys [layout zoom objects base-objects selected page-id drawing focus]}] (dm/assert! (set? selected)) (let [shapes (into [] (keep (d/getf objects)) selected) filter-shapes - (into selected (mapcat #(cfh/get-children-ids objects %)) selected) + (mf/with-memo [base-objects selected] + (into #{} (mapcat #(cfh/get-children-ids-with-self base-objects %)) selected)) remove-snap-base? (mf/with-memo [layout filter-shapes objects focus] diff --git a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs index aa83faf963..357f1faf34 100644 --- a/frontend/src/app/main/ui/workspace/viewport/widgets.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/widgets.cljs @@ -259,10 +259,12 @@ (mf/defc frame-titles* {::mf/wrap [mf/memo]} - [{:keys [objects zoom selected focus is-show-artboard-names + [{:keys [objects base-objects zoom selected focus is-show-artboard-names on-frame-enter on-frame-leave on-frame-select]}] (let [selected (or selected #{}) - shapes (ctt/get-frames objects {:skip-copies? true :ignore-index? true}) + frame-ids (mf/with-memo [base-objects] + (vec (ctt/get-frames-ids base-objects {:skip-copies? true :ignore-index? true}))) + shapes (into [] (keep (d/getf objects)) frame-ids) shapes (if (dbg/enabled? :shape-titles) (into (set shapes) (map (d/getf objects)) diff --git a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs index 3705839275..e338f2366b 100644 --- a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs @@ -870,6 +870,7 @@ (when-not shapes-loading? [:> widgets/frame-titles* {:objects objects-modified + :base-objects base-objects :selected selected :zoom zoom :is-show-artboard-names show-artboard-names? @@ -918,6 +919,7 @@ :page-id page-id :selected selected :objects objects-modified + :base-objects base-objects :focus focus}]) (when show-snap-distance?