diff --git a/CHANGES.md b/CHANGES.md index 520c2af07..a138453cc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,11 @@ # CHANGELOG +## 2.4.2 + +### :bug: Bugs fixed + +- Fix detach when top copy is dangling and nested copy is not [Taiga #9699](https://tree.taiga.io/project/penpot/issue/9699) + ## 2.4.1 ### :bug: Bugs fixed diff --git a/common/src/app/common/logic/libraries.cljc b/common/src/app/common/logic/libraries.cljc index bc9ab68b0..669fdbd63 100644 --- a/common/src/app/common/logic/libraries.cljc +++ b/common/src/app/common/logic/libraries.cljc @@ -304,7 +304,12 @@ (and (some? (ctk/get-swap-slot ref-shape)) (nil? (ctk/get-swap-slot shape)) (not= (:id shape) shape-id)) - (pcb/update-shapes [(:id shape)] #(ctk/set-swap-slot % (ctk/get-swap-slot ref-shape))))))] + (pcb/update-shapes [(:id shape)] #(ctk/set-swap-slot % (ctk/get-swap-slot ref-shape))) + + ;; If we can't get the ref-shape (e.g. it's in an external library not linked), + ;: we can't do a suitable advance. So it's better to detach the shape + (nil? ref-shape) + (pcb/update-shapes [(:id shape)] ctk/detach-shape))))] (reduce skip-near changes children))) diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 739bca6d1..8236631ef 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -738,16 +738,20 @@ (:component-id shape) "@" :else "-") - (when (and (:component-file shape) component-file) + (when (:component-file shape) (str/format "<%s> " - (if (= (:id component-file) (:id file)) - "local" - (:name component-file)))) + (if component-file + (if (= (:id component-file) (:id file)) + "local" + (:name component-file)) + (if show-ids + (str/format "¿%s?" (:component-file shape)) + "?")))) (or (:name component-shape) - (str/format "?%s" - (when show-ids - (str " " (:shape-ref shape))))) + (if show-ids + (str/format "¿%s?" (:shape-ref shape)) + "?")) (when (and show-ids component-shape) (str/format " %s" (:id component-shape))) diff --git a/common/src/app/common/types/shape.cljc b/common/src/app/common/types/shape.cljc index fa0de5359..b483c5fe4 100644 --- a/common/src/app/common/types/shape.cljc +++ b/common/src/app/common/types/shape.cljc @@ -154,6 +154,7 @@ [:main-instance {:optional true} :boolean] [:remote-synced {:optional true} :boolean] [:shape-ref {:optional true} ::sm/uuid] + [:touched {:optional true} [:maybe [:set :keyword]]] [:blocked {:optional true} :boolean] [:collapsed {:optional true} :boolean] [:locked {:optional true} :boolean] @@ -191,8 +192,7 @@ [:grow-type {:optional true} [::sm/one-of grow-types]] [:applied-tokens {:optional true} ::cto/applied-tokens] - [:plugin-data {:optional true} ::ctpg/plugin-data] - [:touched {:optional true} [:maybe [:set :keyword]]]]) + [:plugin-data {:optional true} ::ctpg/plugin-data]]) (def schema:group-attrs [:map {:title "GroupAttrs"} diff --git a/common/test/common_tests/logic/comp_detach_with_nested_test.cljc b/common/test/common_tests/logic/comp_detach_with_nested_test.cljc index d7b999db3..ac7d62d11 100644 --- a/common/test/common_tests/logic/comp_detach_with_nested_test.cljc +++ b/common/test/common_tests/logic/comp_detach_with_nested_test.cljc @@ -103,6 +103,83 @@ (t/is (= (:shape-ref copy-nested-ellipse) (thi/id :nested-ellipse))) (t/is (nil? (ctk/get-swap-slot copy-nested-ellipse))))) +(t/deftest test-advance-in-library + (let [;; ==== Setup + library (setup-file) + file (-> (thf/sample-file :file2) + (thc/instantiate-component :c-big-board + :copy-big-board + :library library + :children-labels [:copy-h-board-with-ellipse + :copy-nested-h-ellipse + :copy-nested-ellipse])) + page (thf/current-page file) + + ;; ==== Action + changes (cll/generate-detach-instance (-> (pcb/empty-changes nil) + (pcb/with-page page) + (pcb/with-objects (:objects page))) + page + {(:id file) file + (:id library) library} + (thi/id :copy-big-board)) + file' (thf/apply-changes file changes) + + ;; ==== Get + copy-h-board-with-ellipse (ths/get-shape file' :copy-h-board-with-ellipse) + copy-nested-h-ellipse (ths/get-shape file' :copy-nested-h-ellipse) + copy-nested-ellipse (ths/get-shape file' :copy-nested-ellipse)] + + ;; ==== Check + + ;; It should the same as above, but in an external library. + (thf/dump-file file) + (t/is (ctk/instance-root? copy-h-board-with-ellipse)) + (t/is (= (:shape-ref copy-h-board-with-ellipse) (thi/id :board-with-ellipse))) + (t/is (nil? (ctk/get-swap-slot copy-h-board-with-ellipse))) + + (t/is (ctk/instance-head? copy-nested-h-ellipse)) + (t/is (= (:shape-ref copy-nested-h-ellipse) (thi/id :nested-h-ellipse))) + (t/is (nil? (ctk/get-swap-slot copy-nested-h-ellipse))) + + (t/is (not (ctk/instance-head? copy-nested-ellipse))) + (t/is (= (:shape-ref copy-nested-ellipse) (thi/id :nested-ellipse))) + (t/is (nil? (ctk/get-swap-slot copy-nested-ellipse))))) + +(t/deftest test-advance-in-broken-library + (let [;; ==== Setup + library (setup-file) + file (-> (thf/sample-file :file2) + (thc/instantiate-component :c-big-board + :copy-big-board + :library library + :children-labels [:copy-h-board-with-ellipse + :copy-nested-h-ellipse + :copy-nested-ellipse])) + page (thf/current-page file) + + ;; ==== Action + changes (cll/generate-detach-instance (-> (pcb/empty-changes nil) + (pcb/with-page page) + (pcb/with-objects (:objects page))) + page + {(:id file) file} + (thi/id :copy-big-board)) + file' (thf/apply-changes file changes) + + ;; ==== Get + copy-h-board-with-ellipse (ths/get-shape file' :copy-h-board-with-ellipse) + copy-nested-h-ellipse (ths/get-shape file' :copy-nested-h-ellipse) + copy-nested-ellipse (ths/get-shape file' :copy-nested-ellipse)] + + ;; ==== Check + + ;; If the main component cannot be found, because it's in a library that is + ;; not available, the nested copies should be detached too. + (t/is (not (ctk/in-component-copy? copy-h-board-with-ellipse))) + (t/is (not (ctk/in-component-copy? copy-nested-h-ellipse))) + (t/is (not (ctk/in-component-copy? copy-nested-ellipse))))) + (t/deftest test-dont-advance-when-swapped-copy (let [;; ==== Setup file (-> (setup-file)