From f8f92d77636e4dd2c7af89e1f7b86d08b2411d02 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Tue, 13 Oct 2026 10:43:11 +0200 Subject: [PATCH] :bug: Keep a swapped child when a variant switch is undone A variant switch with keep-touched moves a swapped child out of the old copy to the page root, then into the new copy, which takes the same id as the old one. The undo of the second move took the child back to that id, so it landed in the new copy and went away with it when the undo deleted the new copy. The undo now takes it back to the root, and from there into the old copy. AI-assisted-by: claude-opus-5-5 Co-Authored-By: Claude Opus 5.5 (1M context) --- common/src/app/common/logic/variants.cljc | 8 +++++-- .../common_tests/logic/swap_group_test.cljc | 22 +++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/common/src/app/common/logic/variants.cljc b/common/src/app/common/logic/variants.cljc index 612cc8f7a5..77276e3a95 100644 --- a/common/src/app/common/logic/variants.cljc +++ b/common/src/app/common/logic/variants.cljc @@ -90,8 +90,12 @@ (-> (pcb/concat-changes before-changes changes) - ;; Move the previous shape to the new parent - (pcb/change-parent (:parent-id related-shape-in-new) [orig-swapped-child] pos {:allow-altering-copies true}) + ;; Move the previous shape to the new parent. It comes from the root, + ;; where the undo must take it back before the new copy is deleted + (pcb/change-parent (:parent-id related-shape-in-new) + [(assoc orig-swapped-child :parent-id uuid/zero)] + pos + {:allow-altering-copies true}) ;; Take the place of the related shape; it stays a swap while its ;; component differs from that one diff --git a/common/test/common_tests/logic/swap_group_test.cljc b/common/test/common_tests/logic/swap_group_test.cljc index 61d7b629af..6fdb4aaefc 100644 --- a/common/test/common_tests/logic/swap_group_test.cljc +++ b/common/test/common_tests/logic/swap_group_test.cljc @@ -15,6 +15,7 @@ [app.common.geom.shapes :as gsh] [app.common.logic.libraries :as cll] [app.common.logic.shapes :as cls] + [app.common.logic.variants :as clv] [app.common.test-helpers.components :as thc] [app.common.test-helpers.compositions :as tho] [app.common.test-helpers.files :as thf] @@ -486,3 +487,24 @@ file' (tho/swap-component-in-shape file :copy01 :c02 {:keep-touched? true})] (t/is (ctk/swapped? (ths/get-shape file' :copy-child))) (t/is (= (rel file' :child2 :m02) (rel file' :copy-child :copy01))))) + +(t/deftest undo-of-a-switch-brings-the-swap-back + (let [file (-> (setup-variants) + (move-shape :child2 30 5)) + page (thf/current-page file) + shape (ths/get-shape file :copy01) + libraries {(:id file) file} + orig (cfh/get-children-with-self (:objects page) (:id shape)) + [new-shape _ changes] + (cll/generate-component-swap (pcb/empty-changes nil (:id page)) + (:objects page) shape (:data file) page libraries + (:id (thc/get-component file :c02)) 0 nil {} true) + [changes _] (clv/generate-keep-touched changes new-shape shape orig page libraries (:data file)) + file' (thf/apply-changes file changes) + file'' (thf/apply-undo-changes file' changes)] + (t/is (= [(thi/id :copy-child)] (:shapes (ths/get-shape file' :copy01)))) + (t/is (= [(thi/id :copy-child)] (:shapes (ths/get-shape file'' :copy01)))) + (t/is (= (thi/id :child1) (:shape-ref (ths/get-shape file'' :copy-child)))) + (t/is (ctk/swapped? (ths/get-shape file'' :copy-child))) + (t/is (not= (position file :copy-child) (position file' :copy-child))) + (t/is (= (position file :copy-child) (position file'' :copy-child)))))