mirror of
https://github.com/penpot/penpot.git
synced 2026-10-29 14:00:37 +00:00
🐛 Create the swapped copy with its swap slot already set
generate-new-shape-for-swap set the swap slot after instantiating the new copy, through change-touched. The validation made when the copy is instantiated ran before that and reported :missing-slot. The slot only depends on the old shape, so compute it before the copy is created and pass it to generate-instantiate-component with the new :swap-slot option. The copy is added with its slot, and the validation sees it complete. The resulting file and its undo are the same as before. AI-assisted-by: claude-opus-5-5
This commit is contained in:
parent
b136097e18
commit
16c381ccef
@ -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
|
||||
|
||||
@ -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))))))
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user