From d80ef17623ca77436994f02612b968437e26e69c Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Tue, 26 Aug 2025 09:25:52 +0200 Subject: [PATCH] :bug: Fix cut pasting a variant into its own parent (#7179) --- common/src/app/common/files/helpers.cljc | 33 +++++++++++++--------- common/src/app/common/types/container.cljc | 18 ++++++------ 2 files changed, 28 insertions(+), 23 deletions(-) diff --git a/common/src/app/common/files/helpers.cljc b/common/src/app/common/files/helpers.cljc index 03a3744ca5..4a12b22f64 100644 --- a/common/src/app/common/files/helpers.cljc +++ b/common/src/app/common/files/helpers.cljc @@ -438,20 +438,25 @@ (defn variants-nesting-loop? "Check if a variants nesting loop would be created if the given shape is moved below the given parent" - [objects libraries shape-id parent-id] - (let [get-variant-id #(or (:variant-id %) - (when (:is-variant-container %) (:id %)) - (when (:component-id %) - (dm/get-in libraries [(:component-file %) - :data - :components - (:component-id %) - :variant-id]))) - child-variant-ids (into #{} (keep get-variant-id) - (get-children-with-self objects shape-id)) - parent-variant-ids (into #{} (keep get-variant-id) - (get-parents-with-self objects parent-id))] - (seq (set/intersection child-variant-ids parent-variant-ids)))) + [objects libraries shape parent pasting-cutted-mains?] + ;; If we are cut-pasting mains into its own variant, it is ok + (if (and pasting-cutted-mains? + (:is-variant-container parent) + (= (:variant-id shape) (:id parent))) + nil + (let [get-variant-id #(or (:variant-id %) + (when (:is-variant-container %) (:id %)) + (when (:component-id %) + (dm/get-in libraries [(:component-file %) + :data + :components + (:component-id %) + :variant-id]))) + child-variant-ids (into #{} (keep get-variant-id) + (get-children-with-self objects (:id shape))) + parent-variant-ids (into #{} (keep get-variant-id) + (get-parents-with-self objects (:id parent)))] + (seq (set/intersection child-variant-ids parent-variant-ids))))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc index 1ac6f89148..80200143f3 100644 --- a/common/src/app/common/types/container.cljc +++ b/common/src/app/common/types/container.cljc @@ -436,7 +436,7 @@ (defn- invalid-structure-for-component? "Check if the structure generated nesting children in parent is invalid in terms of nested components" - [objects parent children pasting? libraries] + [objects parent children pasting? all-comp-cut? libraries] (let [; If the original shapes had been cutted, and we are pasting them now, they aren't ; in objects. We can add them to locate later objects (merge objects @@ -460,7 +460,7 @@ (every? nil?))) variants-nesting-loop? (not (->> children - (map #(cfh/variants-nesting-loop? objects libraries (:id %) (:id parent))) + (map #(cfh/variants-nesting-loop? objects libraries % parent (and pasting? all-comp-cut?))) (every? nil?)))] (or ;;We don't want to change the structure of component copies @@ -481,17 +481,17 @@ (letfn [(get-frame [parent-id] (if (cfh/frame-shape? objects parent-id) parent-id (get-in objects [parent-id :frame-id])))] (let [parent (get objects parent-id) - ;; We can always move the children to the parent they already have. - ;; But if we are pasting, those are new items, so it is considered a change - no-changes? - (and (every? #(= parent-id (:parent-id %)) children) - (not pasting?)) - ;; When pasting frames, children have the frames and their children ;; We need to check only the top shapes children-ids (set (map :id children)) top-children (remove #(contains? children-ids (:parent-id %)) children) + ;; We can always move the children to the parent they already have. + ;; But if we are pasting, those are new items, so it is considered a change + no-changes? + (and (every? #(= parent-id (:parent-id %)) top-children) + (not pasting?)) + ;; Are all the top-children a main-instance of a component? all-main? (every? ctk/main-instance? top-children) @@ -511,7 +511,7 @@ true)) (every? :deleted)))] (if (or no-changes? - (and (not (invalid-structure-for-component? objects parent children pasting? libraries)) + (and (not (invalid-structure-for-component? objects parent children pasting? all-comp-cut? libraries)) ;; If we are moving into a main component, no descendant can be main (or (nil? any-main-descendant) (not (ctk/main-instance? parent))) ;; If we are moving into a variant-container, all the items should be main