diff --git a/common/src/app/common/types/container.cljc b/common/src/app/common/types/container.cljc index f1f67d058..a29d8b940 100644 --- a/common/src/app/common/types/container.cljc +++ b/common/src/app/common/types/container.cljc @@ -150,6 +150,22 @@ :else (get-head-shape objects (get objects (:parent-id shape)) options)))) +(defn get-parent-heads + "Get all component heads that are ancestors of the shape, in top-down order + (include self if it's also a head)." + [objects shape] + (->> (cfh/get-parents-with-self objects (:id shape)) + (filter ctk/instance-head?) + (reverse))) + +(defn get-parent-copy-heads + "Get all component heads that are ancestors of the shape, in top-down order, + excluding mains (include self if it's also a head)." + [objects shape] + (->> (cfh/get-parents-with-self objects (:id shape)) + (filter #(and (ctk/instance-head? %) (ctk/in-component-copy? %))) + (reverse))) + (defn get-instance-root "Get the parent shape at the top of the component instance (main or copy)." [objects shape] diff --git a/common/src/app/common/types/file.cljc b/common/src/app/common/types/file.cljc index eea620e33..9fe6831cf 100644 --- a/common/src/app/common/types/file.cljc +++ b/common/src/app/common/types/file.cljc @@ -117,6 +117,12 @@ [libraries component-id & {:keys [include-deleted?] :or {include-deleted? false}}] (some #(ctkl/get-component (:data %) component-id include-deleted?) (vals libraries))) +(defn find-component-file + [file libraries component-file] + (if (and (some? file) (= component-file (:id file))) + file + (get libraries component-file))) + (defn get-component "Retrieve a component from a library." [libraries library-id component-id & {:keys [include-deleted?] :or {include-deleted? false}}] @@ -188,21 +194,30 @@ "Locate the nearest component in the local file or libraries, and retrieve the shape referenced by the instance shape." [file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}] - (let [parent-heads (->> (cfh/get-parents-with-self (:objects page) (:id shape)) - (filter ctk/instance-head?) - (reverse)) - - find-ref-shape-in-head + (let [find-ref-shape-in-head (fn [head-shape] - (let [head-file (if (and (some? file) (= (:component-file head-shape) (:id file))) - file - (get libraries (:component-file head-shape))) + (let [head-file (find-component-file file libraries (:component-file head-shape)) head-component (when (some? head-file) (ctkl/get-component (:data head-file) (:component-id head-shape) include-deleted?))] (when (some? head-component) (get-ref-shape (:data head-file) head-component shape))))] - (some find-ref-shape-in-head parent-heads))) + (some find-ref-shape-in-head (ctn/get-parent-heads (:objects page) shape)))) + +(defn find-ref-component + "Locate the nearest component in the local file or libraries that is referenced by the + instance shape." + [file page libraries shape & {:keys [include-deleted?] :or {include-deleted? false}}] + (let [find-ref-component-in-head + (fn [head-shape] + (let [head-file (find-component-file file libraries (:component-file head-shape)) + head-component (when (some? head-file) + (ctkl/get-component (:data head-file) (:component-id head-shape) include-deleted?))] + (when (some? head-component) + (when (get-ref-shape (:data head-file) head-component shape) + head-component))))] + + (some find-ref-component-in-head (ctn/get-parent-copy-heads (:objects page) shape)))) (defn find-remote-shape "Recursively go back by the :shape-ref of the shape until find the correct shape of the original component" @@ -229,6 +244,13 @@ remote-shape (find-remote-shape component-container libraries remote-shape))))) +(defn direct-copy? + "Check if the shape is in a direct copy of the component (i.e. the shape-ref points to shapes inside + the component)." + [shape component page file libraries] + (let [ref-component (find-ref-component file page libraries shape :include-deleted? true)] + (true? (= (:id component) (:id ref-component))))) + (defn get-component-shapes "Retrieve all shapes of the component" [file-data component] diff --git a/frontend/src/app/main/data/workspace/libraries_helpers.cljs b/frontend/src/app/main/data/workspace/libraries_helpers.cljs index 47b805b09..84b429de4 100644 --- a/frontend/src/app/main/data/workspace/libraries_helpers.cljs +++ b/frontend/src/app/main/data/workspace/libraries_helpers.cljs @@ -599,15 +599,10 @@ library (dm/get-in libraries [(:component-file shape-inst) :data]) component (or (ctkl/get-component library (:component-id shape-inst)) (and reset? - (ctkl/get-deleted-component library (:component-id shape-inst)))) - component-shape (ctn/get-component-shape (:objects container) shape-inst)] + (ctkl/get-deleted-component library (:component-id shape-inst))))] (if (and (ctk/in-component-copy? shape-inst) - (or (= (:id component) (:component-id component-shape)) reset?)) ; In a normal sync, we don't want to sync remote mains, only near + (or (ctf/direct-copy? shape-inst component container nil libraries) reset?)) ; In a normal sync, we don't want to sync remote mains, only direct/near (let [redirect-shaperef (partial redirect-shaperef container libraries) - library (dm/get-in libraries [(:component-file shape-inst) :data]) - component (or (ctkl/get-component library (:component-id shape-inst)) - (and reset? - (ctkl/get-deleted-component library (:component-id shape-inst)))) shape-main (when component (if (and reset? components-v2)