Merge pull request #3758 from penpot/hiru-bugfix-validation

🐛 Fix component-root when createing new component
This commit is contained in:
Pablo Alba 2023-11-10 15:49:16 +01:00 committed by GitHub
commit 69435e32d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 106 additions and 67 deletions

View file

@ -211,22 +211,22 @@
transform-to-frames transform-to-frames
(fn [file-data] (fn [file-data]
; Transform components and copies to frames, and set the ; Transform component and copy heads to frames, and set the
; frame-id of its childrens ; frame-id of its childrens
(letfn [(fix-container (letfn [(fix-container
[container] [container]
(update container :objects update-vals fix-shape)) (update container :objects update-vals fix-shape))
(fix-shape (fix-shape
[shape] [shape]
(if (ctk/instance-head? shape) (if (ctk/instance-head? shape)
(assoc shape (assoc shape
:type :frame ; Old groups must be converted :type :frame ; Old groups must be converted
:fills [] ; to frames and conform to spec :fills [] ; to frames and conform to spec
:hide-in-viewer true :hide-in-viewer true
:rx 0 :rx 0
:ry 0) :ry 0)
shape))] shape))]
(-> file-data (-> file-data
(update :pages-index update-vals fix-container) (update :pages-index update-vals fix-container)
(update :components update-vals fix-container)))) (update :components update-vals fix-container))))
@ -236,15 +236,39 @@
; Remap the frame-ids of the primary childs of the head instances ; Remap the frame-ids of the primary childs of the head instances
; to point to the head instance. ; to point to the head instance.
(letfn [(fix-container (letfn [(fix-container
[container] [container]
(update container :objects update-vals (partial fix-shape container))) (update container :objects update-vals (partial fix-shape container)))
(fix-shape (fix-shape
[container shape] [container shape]
(let [parent (ctst/get-shape container (:parent-id shape))] (let [parent (ctst/get-shape container (:parent-id shape))]
(if (ctk/instance-head? parent) (if (ctk/instance-head? parent)
(assoc shape :frame-id (:id parent)) (assoc shape :frame-id (:id parent))
shape)))] shape)))]
(-> file-data
(update :pages-index update-vals fix-container)
(update :components update-vals fix-container))))
fix-frame-ids
(fn [file-data]
;; Ensure that frame-id of all shapes point to the parent or to the frame-id
;; of the parent, and that the destination is indeed a frame.
(letfn [(fix-container [container]
(update container :objects #(cph/reduce-objects % fix-shape %)))
(fix-shape [objects shape]
(let [parent (when (:parent-id shape)
(get objects (:parent-id shape)))
error? (when (some? parent)
(if (= (:type parent) :frame)
(not= (:frame-id shape) (:id parent))
(not= (:frame-id shape) (:frame-id parent))))]
(if error?
(let [nearest-frame (cph/get-frame objects (:parent-id shape))
frame-id (or (:id nearest-frame) uuid/zero)]
(update objects (:id shape) assoc :frame-id frame-id))
objects)))]
(-> file-data (-> file-data
(update :pages-index update-vals fix-container) (update :pages-index update-vals fix-container)
(update :components update-vals fix-container))))] (update :components update-vals fix-container))))]
@ -257,7 +281,8 @@
(remap-refs) (remap-refs)
(fix-copies-of-detached) (fix-copies-of-detached)
(transform-to-frames) (transform-to-frames)
(remap-frame-ids)))) (remap-frame-ids)
(fix-frame-ids))))
(defn- migrate-components (defn- migrate-components
"If there is any component in the file library, add a new 'Library "If there is any component in the file library, add a new 'Library
@ -312,8 +337,8 @@
(fn [page shape] (fn [page shape]
(let [parent (ctst/get-shape page (:parent-id shape))] (let [parent (ctst/get-shape page (:parent-id shape))]
(if (= :frame (:type parent)) (if (= :frame (:type parent))
(:parent-id shape) (:id parent)
(:frame-id shape)))) (:frame-id parent))))
add-shapes add-shapes
(fn [page] (fn [page]
@ -369,7 +394,7 @@
"Convert a media object that contains a bitmap image into shapes, "Convert a media object that contains a bitmap image into shapes,
one shape of type :image and one group that contains it." one shape of type :image and one group that contains it."
[{:keys [name width height id mtype]} position] [{:keys [name width height id mtype]} position]
(let [group-shape (cts/setup-shape (let [frame-shape (cts/setup-shape
{:type :frame {:type :frame
:x (:x position) :x (:x position)
:y (:y position) :y (:y position)
@ -390,9 +415,9 @@
:height height :height height
:mtype mtype} :mtype mtype}
:name name :name name
:frame-id uuid/zero :frame-id (:id frame-shape)
:parent-id (:id group-shape)})] :parent-id (:id frame-shape)})]
[group-shape [img-shape]])) [frame-shape [img-shape]]))
(defn- parse-datauri (defn- parse-datauri
[data] [data]
@ -549,7 +574,8 @@
cfsh/prepare-create-artboard-from-selection) cfsh/prepare-create-artboard-from-selection)
changes (pcb/concat-changes changes changes2)] changes (pcb/concat-changes changes changes2)]
(cp/process-changes fdata (:redo-changes changes) false))) (cp/process-changes (assoc-in fdata [:options :components-v2] true) ; Process component creation in v2 way
(:redo-changes changes) false)))
(defn- migrate-graphics (defn- migrate-graphics
[fdata] [fdata]

View file

@ -20,14 +20,7 @@
[root-shape new-shapes updated-shapes] [root-shape new-shapes updated-shapes]
(if-not components-v2 (if-not components-v2
(ctn/make-component-shape root objects file-id components-v2) (ctn/make-component-shape root objects file-id components-v2)
(let [new-id (uuid/next)] (ctn/convert-shape-in-component root objects file-id))
[(assoc root :id new-id)
nil
[(assoc root
:component-id new-id
:component-file file-id
:component-root true
:main-instance true)]]))
changes (-> changes changes (-> changes
(pcb/add-component (:id root-shape) (pcb/add-component (:id root-shape)
@ -39,12 +32,10 @@
page-id))] page-id))]
[root-shape changes])) [root-shape changes]))
(defn generate-add-component (defn generate-add-component
"If there is exactly one id, and it's a frame (or a group in v1), and not already a "If there is exactly one id, and it's a frame (or a group in v1), and not already a component,
component, use it as root. Otherwise, create a frame (v2) or group (v1) that contains use it as root. Otherwise, create a frame (v2) or group (v1) that contains all ids. Then, make a
all ids. Then, make a component with it, and link all shapes to their corresponding one component with it, and link all shapes to their corresponding one in the component."
in the component."
[it shapes objects page-id file-id components-v2 prepare-create-group prepare-create-board] [it shapes objects page-id file-id components-v2 prepare-create-group prepare-create-board]
(let [changes (pcb/empty-changes it page-id) (let [changes (pcb/empty-changes it page-id)
@ -81,7 +72,9 @@
[root changes (map :id shapes)])) [root changes (map :id shapes)]))
[root-shape changes] (generate-add-component-changes changes root objects file-id page-id components-v2) objects' (assoc objects (:id root) root)
[root-shape changes] (generate-add-component-changes changes root objects' file-id page-id components-v2)
changes (pcb/update-shapes changes changes (pcb/update-shapes changes
old-root-ids old-root-ids

View file

@ -86,7 +86,8 @@
:always :always
(assoc :frame-id frame-id (assoc :frame-id frame-id
:parent-id parent-id) :parent-id parent-id
:shapes (into [] selected))
:always :always
(with-meta {:index new-index}) (with-meta {:index new-index})

View file

@ -1604,6 +1604,7 @@
(watch [_ _ _] (watch [_ _ _]
(try (try
(let [clipboard-str (wapi/read-from-clipboard) (let [clipboard-str (wapi/read-from-clipboard)
paste-transit-str paste-transit-str
(->> clipboard-str (->> clipboard-str
(rx/filter t/transit?) (rx/filter t/transit?)

View file

@ -405,28 +405,29 @@
(ptk/reify ::duplicate-component (ptk/reify ::duplicate-component
ptk/WatchEvent ptk/WatchEvent
(watch [it state _] (watch [it state _]
(let [libraries (wsh/get-libraries state) (let [libraries (wsh/get-libraries state)
library (get libraries library-id) library (get libraries library-id)
component (ctkl/get-component (:data library) component-id) component (ctkl/get-component (:data library) component-id)
new-name (:name component) new-name (:name component)
components-v2 (features/active-feature? state "components/v2") components-v2 (features/active-feature? state "components/v2")
main-instance-page (when components-v2 main-instance-page (when components-v2
(ctf/get-component-page (:data library) component)) (ctf/get-component-page (:data library) component))
new-component (assoc component :id (uuid/next)) new-component-id (when components-v2
(uuid/next))
[new-component-shape new-component-shapes ; <- null in components-v2 [new-component-shape new-component-shapes ; <- null in components-v2
new-main-instance-shape new-main-instance-shapes] new-main-instance-shape new-main-instance-shapes]
(dwlh/duplicate-component new-component (:data library)) (dwlh/duplicate-component component new-component-id (:data library))
changes (-> (pcb/empty-changes it nil) changes (-> (pcb/empty-changes it nil)
(pcb/with-page main-instance-page) (pcb/with-page main-instance-page)
(pcb/with-objects (:objects main-instance-page)) (pcb/with-objects (:objects main-instance-page))
(pcb/add-objects new-main-instance-shapes {:ignore-touched true}) (pcb/add-objects new-main-instance-shapes {:ignore-touched true})
(pcb/add-component (if components-v2 (pcb/add-component (if components-v2
(:id new-component) new-component-id
(:id new-component-shape)) (:id new-component-shape))
(:path component) (:path component)
new-name new-name

View file

@ -65,26 +65,43 @@
(defn duplicate-component (defn duplicate-component
"Clone the root shape of the component and all children. Generate new "Clone the root shape of the component and all children. Generate new
ids from all of them." ids from all of them."
[component library-data] [component new-component-id library-data]
(let [components-v2 (dm/get-in library-data [:options :components-v2])] (let [components-v2 (dm/get-in library-data [:options :components-v2])]
(if components-v2 (if components-v2
(let [main-instance-page (ctf/get-component-page library-data component) (let [main-instance-page (ctf/get-component-page library-data component)
main-instance-shape (ctf/get-component-root library-data component) main-instance-shape (ctf/get-component-root library-data component)
position (gpt/point (+ (:x main-instance-shape) delta (gpt/point (+ (:width main-instance-shape) 50) 0)
(:width main-instance-shape)
50)
(:y main-instance-shape))
options (if components-v2 {:main-instance? true} {})
[new-instance-shape new-instance-shapes] ids-map (volatile! {})
(when (and (some? main-instance-page) (some? main-instance-shape))
(ctn/make-component-instance main-instance-page update-original-shape
component (fn [original-shape new-shape]
library-data (vswap! ids-map assoc (:id original-shape) (:id new-shape))
position original-shape)
true
options))] update-new-shape
(fn [shape]
(cond-> shape
(= (:component-id shape) (:id component))
(assoc :component-id new-component-id)
:always
(gsh/move delta)))
[new-instance-shape new-instance-shapes _]
(ctst/clone-object main-instance-shape
(:parent-id main-instance-shape)
(:objects main-instance-page)
update-new-shape
update-original-shape)
remap-frame
(fn [shape]
(update shape :frame-id
#(get @ids-map % (:frame-id shape))))
new-instance-shapes (map remap-frame new-instance-shapes)]
[nil nil new-instance-shape new-instance-shapes]) [nil nil new-instance-shape new-instance-shapes])