diff --git a/CHANGES.md b/CHANGES.md index 277ac1d57a..6c9eb8700e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,7 @@ - Fix problem with booleans selection [Taiga #11627](https://tree.taiga.io/project/penpot/issue/11627) - Fix missing font when copy&paste a chunk of text [Taiga #11522](https://tree.taiga.io/project/penpot/issue/11522) +- Fix bad swap slot after two swaps [Taiga #11659](https://tree.taiga.io/project/penpot/issue/11659) ## 2.9.0 (Unreleased) diff --git a/common/src/app/common/files/migrations.cljc b/common/src/app/common/files/migrations.cljc index 2af7b31f4d..1e1950f85e 100644 --- a/common/src/app/common/files/migrations.cljc +++ b/common/src/app/common/files/migrations.cljc @@ -1552,6 +1552,23 @@ (update data :pages-index d/update-vals update-page))) +(defmethod migrate-data "0010-fix-swap-slots-pointing-non-existent-shapes" + [data _] + (letfn [(fix-shape [page shape] + (if (ctk/get-swap-slot shape) + (let [libs (some-> (:libs data) deref) + ref-id (when libs (ctf/find-ref-id-for-swapped shape page libs))] + (if (nil? ref-id) + (ctk/remove-swap-slot shape) + shape)) + shape)) + + (update-page [page] + (d/update-when page :objects d/update-vals (partial fix-shape page)))] + (-> data + (update :pages-index d/update-vals update-page)))) + + (def available-migrations (into (d/ordered-set) ["legacy-2" @@ -1617,4 +1634,5 @@ "0007-clear-invalid-strokes-and-fills-v2" "0008-fix-library-colors-v4" "0009-clean-library-colors" - "0009-add-partial-text-touched-flags"])) + "0009-add-partial-text-touched-flags" + "0010-fix-swap-slots-pointing-non-existent-shapes"])) diff --git a/common/src/app/common/logic/libraries.cljc b/common/src/app/common/logic/libraries.cljc index 6f3ebfa772..e73b03aaee 100644 --- a/common/src/app/common/logic/libraries.cljc +++ b/common/src/app/common/logic/libraries.cljc @@ -2340,6 +2340,8 @@ inside-comp? (ctn/in-any-component? objects parent) [new-shape changes] + ;; When we make a swap of an item, there can be copies which swap-slot points to that item + ;; so we want to assign the item id to the new instanciated copy, to mantain that reference (generate-instantiate-component changes objects (:id file) @@ -2347,9 +2349,10 @@ position page libraries - nil + (:id shape) (:parent-id shape) (:frame-id shape) + {(:id shape) (:id shape)} ;; keep the id of the original shape {:force-frame? true}) new-shape (cond-> new-shape diff --git a/common/test/common_tests/logic/swap_keeps_id_test.cljc b/common/test/common_tests/logic/swap_keeps_id_test.cljc new file mode 100644 index 0000000000..6ecc3583b2 --- /dev/null +++ b/common/test/common_tests/logic/swap_keeps_id_test.cljc @@ -0,0 +1,37 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns common-tests.logic.swap-keeps-id-test + (:require + [app.common.test-helpers.components :as thc] + [app.common.test-helpers.compositions :as tho] + [app.common.test-helpers.files :as thf] + [app.common.test-helpers.shapes :as ths] + [clojure.test :as t])) + + +(t/deftest test-swap-keeps-id + (let [;; ==== Setup + file (-> (thf/sample-file :file1) + + (tho/add-frame :frame-rectangle) + (ths/add-sample-shape :rectangle-shape :parent-label :frame-rectangle :type :rect) + (thc/make-component :rectangle :frame-rectangle) + + (tho/add-frame :frame-circle) + (ths/add-sample-shape :circle :parent-label :frame-circle :type :circle) + (thc/make-component :circle :frame-circle) + + (thc/instantiate-component :rectangle :copy01)) + + copy (ths/get-shape file :copy01) + + ;; ==== Action + file' (tho/swap-component file copy :circle {:new-shape-label :copy02 :keep-touched? true}) + + copy' (ths/get-shape file' :copy02)] + ;; Both copies have the same id + (t/is (= (:id copy) (:id copy')))))