diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index 6d9070424..2d42ba1b1 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -182,7 +182,7 @@ [file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}] (let [root-shape (ctn/get-copy-root (:objects page) shape) component-file (when root-shape - (if (= (:component-file root-shape) (:id file)) + (if (and (some? file) (= (:component-file root-shape) (:id file))) file (get libraries (:component-file root-shape)))) component (when component-file @@ -193,7 +193,7 @@ (if (some? ref-shape) ; There is a case when we have a nested orphan copy. In this case there is no near ref-shape ; component for this copy, so shape-ref points to the remote main. (let [head-shape (ctn/get-head-shape (:objects page) shape) - head-file (if (= (:component-file head-shape) (:id file)) + head-file (if (and (some? file) (= (:component-file head-shape) (:id file))) file (get libraries (:component-file head-shape))) head-component (when (some? head-file) diff --git a/frontend/src/app/main/data/workspace/libraries.cljs b/frontend/src/app/main/data/workspace/libraries.cljs index 0548f137f..ae2d666e8 100644 --- a/frontend/src/app/main/data/workspace/libraries.cljs +++ b/frontend/src/app/main/data/workspace/libraries.cljs @@ -566,11 +566,12 @@ (let [file (wsh/get-local-file state) page-id (get state :current-page-id) container (cfh/get-container file :page page-id) + libraries (wsh/get-libraries state) changes (-> (pcb/empty-changes it) (pcb/with-container container) (pcb/with-objects (:objects container)) - (dwlh/generate-detach-instance container id))] + (dwlh/generate-detach-instance container libraries id))] (rx/of (dch/commit-changes changes)))))) @@ -595,13 +596,14 @@ objects (wsh/lookup-page-objects state page-id) file (wsh/get-local-file state) container (cfh/get-container file :page page-id) + libraries (wsh/get-libraries state) selected (->> state (wsh/lookup-selected) (cfh/clean-loops objects)) changes (reduce (fn [changes id] - (dwlh/generate-detach-instance changes container id)) + (dwlh/generate-detach-instance changes libraries container id)) (-> (pcb/empty-changes it) (pcb/with-container container) (pcb/with-objects objects)) diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 1d9c11318..b81f78e71 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -200,31 +200,46 @@ [new-shape changes]))) (declare generate-detach-recursive) +(declare generate-advance-nesting-level) (defn generate-detach-instance "Generate changes to remove the links between a shape and all its children with a component." - [changes container shape-id] + [changes container libraries shape-id] (let [shape (ctn/get-shape container shape-id)] (log/debug :msg "Detach instance" :shape-id shape-id :container (:id container)) - (generate-detach-recursive changes container shape-id true (true? (:component-root shape))))) + (generate-detach-recursive changes container libraries shape-id true (true? (:component-root shape))))) (defn- generate-detach-recursive - [changes container shape-id first component-root?] + [changes container libraries shape-id first component-root?] (let [shape (ctn/get-shape container shape-id)] (if (and (ctk/instance-head? shape) (not first)) - ;; Subinstances are not detached - (if component-root? - ;; if the original shape was component-root, the subinstances are converted in top instances - (pcb/update-shapes changes [(:id shape)] #(assoc % :component-root true)) - changes) + ; Subinstances are not detached + (cond-> changes + component-root? + ; If the initial shape was component-root, first level subinstances are converted in top instances + (pcb/update-shapes [shape-id] #(assoc % :component-root true)) + + :always + ; Near shape-refs need to be advanced one level + (generate-advance-nesting-level nil container libraries (:id shape))) ;; Otherwise, detach the shape and all children (let [children-ids (:shapes shape)] - (reduce #(generate-detach-recursive %1 container %2 false component-root?) + (reduce #(generate-detach-recursive %1 container libraries %2 false component-root?) (pcb/update-shapes changes [(:id shape)] ctk/detach-shape) children-ids))))) +(defn- generate-advance-nesting-level + [changes file container libraries shape-id] + (let [children (cfh/get-children-with-self (:objects container) shape-id) + skip-near (fn [changes shape] + (let [ref-shape (ctf/find-ref-shape file container libraries shape {:include-deleted? true})] + (if (some? (:shape-ref ref-shape)) + (pcb/update-shapes changes [(:id shape)] #(assoc % :shape-ref (:shape-ref ref-shape))) + changes)))] + (reduce skip-near changes children))) + (defn prepare-restore-component ([library-data component-id current-page it] (let [component (ctkl/get-deleted-component library-data component-id) @@ -604,7 +619,7 @@ ;; deleted or the library unlinked, do nothing in v2 or detach in v1. (if components-v2 changes - (generate-detach-instance changes container shape-id)))) + (generate-detach-instance changes libraries container shape-id)))) changes))) (defn- find-main-container @@ -634,7 +649,7 @@ ;; This should not occur, but protect against it in any case (if components-v2 changes - (generate-detach-instance changes container (:id shape-inst))) + (generate-detach-instance changes container {(:id library) library} (:id shape-inst))) (let [omit-touched? (not reset?) clear-remote-synced? (and initial-root? reset?) set-remote-synced? (and (not initial-root?) reset?)