diff --git a/common/src/app/common/logic/libraries.cljc b/common/src/app/common/logic/libraries.cljc index de45c2efad..1ab4a099be 100644 --- a/common/src/app/common/logic/libraries.cljc +++ b/common/src/app/common/logic/libraries.cljc @@ -245,7 +245,7 @@ ([changes objects file-id component-id position page libraries old-id parent-id frame-id params] (generate-instantiate-component changes objects file-id component-id position page libraries old-id parent-id frame-id {} params)) ([changes objects file-id component-id position page libraries old-id parent-id frame-id ids-map - {:keys [force-frame?] + {:keys [force-frame? swap-slot] :or {force-frame? false}}] (let [component (ctf/get-component libraries file-id component-id) @@ -261,6 +261,13 @@ parent-id (d/nilv (:id parent) parent-id) frame-id (d/nilv (:frame-id parent) frame-id) + ;; A copy created by a swap keeps the slot of the shape it + ;; replaces. Set it from the start, so the validation below sees + ;; the copy complete + set-swap-slot #(cond-> % + (nil? (ctk/get-swap-slot %)) + (ctk/set-swap-slot swap-slot)) + [new-shape new-shapes] (ctn/make-component-instance page component @@ -273,8 +280,10 @@ force-frame? (assoc :force-frame-id frame-id))) + new-shape (set-swap-slot new-shape) + first-shape - (cond-> (first new-shapes) + (cond-> (set-swap-slot (first new-shapes)) (not (nil? parent-id)) (assoc :parent-id parent-id) (and (not (nil? parent)) (= :frame (:type parent))) @@ -2730,6 +2739,14 @@ parent (get objects (:parent-id shape)) inside-comp? (ctn/in-any-component? objects parent) + ;; if the shape isn't inside a main component, it shouldn't have a swap slot + swap-slot (when inside-comp? + (ctf/find-swap-slot shape + page + {:id (:id file) + :data file} + libraries)) + [new-shape changes] ;; When we make a swap of an item, there can be copies which swap-slot points to that item ;; so we want to assign the item id to the new instanciated copy, to mantain that reference @@ -2744,17 +2761,8 @@ (:parent-id shape) (:frame-id shape) {(:id shape) (:id shape)} ;; keep the id of the original shape - {:force-frame? true}) - - new-shape (cond-> new-shape - ;; if the shape isn't inside a main component, it shouldn't have a swap slot - (and (nil? (ctk/get-swap-slot new-shape)) - inside-comp?) - (ctk/set-swap-slot (ctf/find-swap-slot shape - page - {:id (:id file) - :data file} - libraries)))] + {:force-frame? true + :swap-slot swap-slot})] [new-shape (-> changes ;; Restore the properties diff --git a/common/test/common_tests/logic/swap_and_reset_test.cljc b/common/test/common_tests/logic/swap_and_reset_test.cljc index c9434a9090..e05cc1fd8a 100644 --- a/common/test/common_tests/logic/swap_and_reset_test.cljc +++ b/common/test/common_tests/logic/swap_and_reset_test.cljc @@ -142,3 +142,51 @@ (t/is (= :rect (:type (tho/bottom-shape-by-id file' (:id restored))))) (t/is (= rectangle-id (:component-id restored))) (t/is (nil? (ctk/get-swap-slot restored)))))) + +(t/deftest test-swap-creates-copy-with-slot + ;; The new copy is added with its swap slot already set, so the + ;; validation made when it is instantiated sees it complete + (let [;; ==== Setup + file (-> (thf/sample-file :file1) + + (tho/add-frame :frame-rectangle) + (ths/add-sample-shape :rectangle-shape :parent-label :frame-rectangle :type :rect) + (thc/make-component :rectangle :frame-rectangle) + + (tho/add-frame :frame-circle) + (ths/add-sample-shape :circle :parent-label :frame-circle :type :circle) + (thc/make-component :circle :frame-circle) + + (tho/add-frame :frame-main) + (thc/instantiate-component :rectangle :copy-rectangle :parent-label :frame-main) + (thc/make-component :main :frame-main)) + + page (thf/current-page file) + shape (ths/get-shape file :copy-rectangle) + + ;; ==== Action + [new-shape _ changes] + (cll/generate-component-swap (pcb/empty-changes nil (:id page)) + (:objects page) + shape + (:data file) + page + {(:id file) file} + (:id (thc/get-component file :circle)) + 0 + nil + {} + false) + + add-change (->> (:redo-changes changes) + (filter #(and (= :add-obj (:type %)) + (= (:id shape) (:id %)))) + first) + + file' (thf/apply-changes file changes) + copy' (ths/get-shape-by-id file' (:id shape))] + + ;; ==== Check + (t/is (some? (ctk/get-swap-slot copy'))) + (t/is (= (ctk/get-swap-slot copy') (ctk/get-swap-slot new-shape))) + (t/is (= (ctk/get-swap-slot copy') (ctk/get-swap-slot (:obj add-change))))))