From fc038998d5408cea73981153b85943fc1f939ce6 Mon Sep 17 00:00:00 2001 From: Pablo Alba Date: Wed, 31 May 2023 13:20:32 +0200 Subject: [PATCH] :bug: Fix copy paste can produce nested components --- common/src/app/common/pages/changes.cljc | 19 ++++--------------- common/src/app/common/pages/helpers.cljc | 14 ++++++++++++++ frontend/src/app/main/data/workspace.cljs | 11 ++++++++++- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/common/src/app/common/pages/changes.cljc b/common/src/app/common/pages/changes.cljc index 3cb97a5b4..96336e386 100644 --- a/common/src/app/common/pages/changes.cljc +++ b/common/src/app/common/pages/changes.cljc @@ -75,7 +75,7 @@ [:parent-id {:optional true} ::sm/uuid] [:index {:optional true} [:maybe :int]] [:ignore-touched {:optional true} :boolean]]] - + [:mod-obj [:map {:title "ModObjChange"} @@ -216,7 +216,7 @@ [:type [:= :del-typography]] [:id ::sm/uuid]]]]]) - + (def change? (sm/pred-fn ::change)) @@ -388,18 +388,7 @@ (defmethod process-change :mov-objects [data {:keys [parent-id shapes index page-id component-id ignore-touched after-shape]}] - (letfn [(nested-components? [objects shape-id] - (let [children (cph/get-children-with-self objects shape-id) - xf-get-component-id (keep :component-id) - child-components (into #{} xf-get-component-id children) - - parents (cph/get-parents-with-self objects parent-id) - xf-get-main-id (comp (filter :main-instance?) - xf-get-component-id) - parent-components (into #{} xf-get-main-id parents)] - (seq (set/intersection child-components parent-components)))) - - (calculate-invalid-targets [objects shape-id] + (letfn [(calculate-invalid-targets [objects shape-id] (let [reduce-fn #(into %1 (calculate-invalid-targets objects %2))] (->> (get-in objects [shape-id :shapes]) (reduce reduce-fn #{shape-id})))) @@ -410,7 +399,7 @@ (let [invalid-targets (calculate-invalid-targets objects shape-id)] (and (contains? objects shape-id) (not (invalid-targets parent-id)) - (not (nested-components? objects shape-id)) + (not (cph/components-nesting-loop? objects shape-id parent-id)) #_(cph/valid-frame-target? objects parent-id shape-id)))) (insert-items [prev-shapes index shapes] diff --git a/common/src/app/common/pages/helpers.cljc b/common/src/app/common/pages/helpers.cljc index f4ba1b745..54c13a2e6 100644 --- a/common/src/app/common/pages/helpers.cljc +++ b/common/src/app/common/pages/helpers.cljc @@ -12,6 +12,7 @@ [app.common.types.pages-list :as ctpl] [app.common.types.shape.layout :as ctl] [app.common.uuid :as uuid] + [clojure.set :as set] [cuerdas.core :as str])) (declare reduce-objects) @@ -302,6 +303,19 @@ (ctkl/get-component file id)) (assoc :type type))) +(defn components-nesting-loop? + "Check if a nesting loop would be created if the given shape is moved below the given parent" + [objects shape-id parent-id] + (let [children (get-children-with-self objects shape-id) + xf-get-component-id (keep :component-id) + child-components (into #{} xf-get-component-id children) + + parents (get-parents-with-self objects parent-id) + xf-get-main-id (comp (filter :main-instance?) + xf-get-component-id) + parent-components (into #{} xf-get-main-id parents)] + (seq (set/intersection child-components parent-components)))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ALGORITHMS & TRANSFORMATIONS FOR SHAPES ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/frontend/src/app/main/data/workspace.cljs b/frontend/src/app/main/data/workspace.cljs index 4e8537420..49be3b641 100644 --- a/frontend/src/app/main/data/workspace.cljs +++ b/frontend/src/app/main/data/workspace.cljs @@ -1646,9 +1646,18 @@ tree-root (get-tree-root-shapes paste-objects) only-one-root-shape? (and (< 1 (count paste-objects)) - (= 1 (count tree-root)))] + (= 1 (count tree-root))) + all-objects (merge page-objects paste-objects) + comps-nesting-loop? (not (->> (keys paste-objects) + (map #(cph/components-nesting-loop? all-objects % (:id base))) + (every? nil?)))] (cond + comps-nesting-loop? + ;; Avoid placing a shape as a direct or indirect child of itself, + ;; or inside its main component if it's in a copy. + [uuid/zero uuid/zero (gpt/subtract mouse-pos orig-pos)] + (selected-frame? state) (if (or (any-same-frame-from-selected? state (keys paste-objects))