⚡ Group color updates in selections (#12875)

This commit is contained in:
Luke Lau 2026-11-09 19:08:36 +08:00 committed by GitHub
parent 9034e707bf
commit 943e63a99e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 11 deletions

View File

@ -683,18 +683,23 @@
(ptk/reify ::change-color-in-selected
ptk/WatchEvent
(watch [_ _ _]
(let [undo-id (js/Symbol)]
(let [undo-id (js/Symbol)
{text-ops true style-ops false} (group-by #(= :content (:prop %)) operations)
style-groups (group-by (juxt :prop :index) style-ops)]
(rx/concat
(rx/of (dwu/start-undo-transaction undo-id))
(->> (rx/from operations)
(rx/map (fn [{:keys [shape-id index] :as operation}]
(case (:prop operation)
:fill (change-fill [shape-id] new-color index)
:stroke (change-stroke-color [shape-id] new-color index)
:shadow (change-shadow [shape-id] new-color index)
:content (dwt/update-text-with-function
shape-id
(partial change-text-color old-color new-color index))))))
(->> (rx/from style-groups)
(rx/map (fn [[[prop index] operations]]
(let [ids (mapv :shape-id operations)]
(case prop
:fill (change-fill ids new-color index)
:stroke (change-stroke-color ids new-color index)
:shadow (change-shadow ids new-color index))))))
(->> (rx/from text-ops)
(rx/map (fn [{:keys [shape-id index]}]
(dwt/update-text-with-function
shape-id
(partial change-text-color old-color new-color index)))))
(rx/of (dwu/commit-undo-transaction undo-id)))))))
(defn apply-color-from-palette

View File

@ -8,7 +8,8 @@
(:require
[app.common.uuid :as uuid]
[app.main.data.workspace.colors :as dwc]
[clojure.test :as t]
[cljs.test :as t :include-macros true]
[frontend-tests.helpers.async :as async]
[potok.v2.core :as ptk]))
(t/deftest build-change-fill-event
@ -82,3 +83,26 @@
:current-color {:color "#ff0000" :opacity 1}}}
event (dwc/update-colorpicker-color {} true)]
(t/is (some? (ptk/watch event valid-state nil)))))
(t/deftest ^:async color-change-updates-the-shapes-of-a-property-in-one-event
;; Changing a color in a selection of many shapes must not commit once per
;; shape: each commit makes the page objects a new map, and everything that
;; derives from them runs again.
(let [[a b c d e] (repeatedly 5 uuid/next)
color {:color "#ff0000" :opacity 1}
old-color {:color "#000000" :opacity 1}
operations [{:prop :fill :shape-id a :index 0}
{:prop :fill :shape-id b :index 0}
{:prop :fill :shape-id c :index 1}
{:prop :stroke :shape-id a :index 0}
{:prop :stroke :shape-id d :index 0}
{:prop :stroke :shape-id e :index 0}]
types (atom [])]
(await (async/observe (ptk/watch (dwc/change-color-in-selected operations color old-color) {} nil)
:on-next #(swap! types conj (ptk/type %))))
(t/is (= {:app.main.data.workspace.undo/start-undo-transaction 1
:app.main.data.workspace.colors/change-fill 2
:app.main.data.workspace.colors/change-stroke-color 1
:app.main.data.workspace.undo/commit-undo-transaction 1}
(frequencies @types)))))