From 286ccb03fa924af71c167347ddb8940f1d793401 Mon Sep 17 00:00:00 2001 From: Shlok Goyal Date: Thu, 10 Sep 2026 18:06:51 +0530 Subject: [PATCH] :bug: Preserve stroke dash and gap values on color change (#11557) Signed-off-by: Shlok Goyal --- .../src/app/main/data/workspace/colors.cljs | 5 ++- .../frontend_tests/basic_shapes_test.cljs | 45 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/frontend/src/app/main/data/workspace/colors.cljs b/frontend/src/app/main/data/workspace/colors.cljs index d4e7f587f8..433d9fea6f 100644 --- a/frontend/src/app/main/data/workspace/colors.cljs +++ b/frontend/src/app/main/data/workspace/colors.cljs @@ -333,13 +333,16 @@ [:stroke-style :stroke-alignment :stroke-width + :stroke-dash + :stroke-gap :stroke-per-side :stroke-width-top :stroke-width-right :stroke-width-bottom :stroke-width-left :stroke-cap-start - :stroke-cap-end]) + :stroke-cap-end + :hidden]) ;; FIXME: this function initializes an empty stroke, maybe we can move ;; it to common.types diff --git a/frontend/test/frontend_tests/basic_shapes_test.cljs b/frontend/test/frontend_tests/basic_shapes_test.cljs index 1082e2435e..de9bca248b 100644 --- a/frontend/test/frontend_tests/basic_shapes_test.cljs +++ b/frontend/test/frontend_tests/basic_shapes_test.cljs @@ -76,3 +76,48 @@ (t/is (= (:stroke-alignment stroke') :inner)) (t/is (= (:stroke-color stroke') "#FABADA")) (t/is (= (:stroke-width stroke') 2)))))))) +(t/deftest test-update-stroke-color-preserves-dash-gap + ;; Custom dash/gap on a dashed stroke describe stroke geometry, not color; + ;; a stroke color change must preserve them (issue #11549). + (t/async + done + (let [store (ths/setup-store + (-> (cthf/sample-file :file1 :page-label :page1) + (cths/add-sample-shape :shape1 :strokes + [{:stroke-color "#000000" + :stroke-opacity 1 + :stroke-width 2 + :stroke-style :dashed + :stroke-dash 4 + :stroke-gap 20}]) + (cths/add-sample-shape :shape2 :strokes + [{:stroke-color "#000000" + :stroke-opacity 1 + :stroke-width 2 + :stroke-style :dashed}]))) + events [(dc/change-stroke-color #{(cthi/id :shape1)} {:color "#FABADA"} 0) + (dc/change-stroke-color #{(cthi/id :shape2)} {:color "#FABADA"} 0)]] + (ths/run-store + store done events + (fn [new-state] + (let [objects (dsh/lookup-page-objects new-state) + shape1' (get objects (cthi/id :shape1)) + stroke1' (first (:strokes shape1')) + shape2' (get objects (cthi/id :shape2)) + stroke2' (first (:strokes shape2'))] + + ;; dashed stroke with custom dash/gap keeps them after color change + (t/is (some? shape1')) + (t/is (= (:stroke-color stroke1') "#FABADA")) + (t/is (= (:stroke-style stroke1') :dashed)) + (t/is (= (:stroke-width stroke1') 2)) + (t/is (= (:stroke-dash stroke1') 4)) + (t/is (= (:stroke-gap stroke1') 20)) + + ;; dashed stroke without explicit dash/gap stays unset: + ;; no implicit default is materialized into stored data + (t/is (some? shape2')) + (t/is (= (:stroke-color stroke2') "#FABADA")) + (t/is (= (:stroke-style stroke2') :dashed)) + (t/is (nil? (:stroke-dash stroke2'))) + (t/is (nil? (:stroke-gap stroke2'))))))))) \ No newline at end of file