🐛 Fix cut pasting a variant into its own parent (#7179)

This commit is contained in:
Pablo Alba 2025-08-26 09:25:52 +02:00 committed by GitHub
parent ffe469ce71
commit d80ef17623
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 28 additions and 23 deletions

View File

@ -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)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

View File

@ -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