0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-10 09:08:31 -05:00

🐛 Fix copy and paste components between files

This commit is contained in:
Pablo Alba 2023-04-13 19:23:00 +02:00 committed by Andrés Moya
parent da54557aab
commit 4ddd3811b2
5 changed files with 100 additions and 66 deletions

View file

@ -61,10 +61,14 @@
(assoc :objects objects))))))) (assoc :objects objects)))))))
(defn get-component (defn get-component
[file-data component-id] ([file-data component-id]
(get-component file-data component-id false))
([file-data component-id include-deleted?]
(let [component (get-in file-data [:components component-id])] (let [component (get-in file-data [:components component-id])]
(when-not (:deleted component) (when (or include-deleted?
component))) (not (:deleted component)))
component))))
(defn get-deleted-component (defn get-deleted-component
[file-data component-id] [file-data component-id]

View file

@ -171,6 +171,16 @@
(cph/get-children-with-self (:objects instance-page) (:main-instance-id component))) (cph/get-children-with-self (:objects instance-page) (:main-instance-id component)))
(vals (:objects component))))) (vals (:objects component)))))
;; Return true if the object is a component that exists on the file or its libraries (even a deleted one)
(defn is-known-component?
[shape libraries]
(let [main-instance? (ctk/main-instance? shape)
component-id (:component-id shape)
file-id (:component-file shape)
component (ctkl/get-component (dm/get-in libraries [file-id :data]) component-id true)]
(and main-instance?
component)))
(defn load-component-objects (defn load-component-objects
"Add an :objects property to the component, with only the shapes that belong to it" "Add an :objects property to the component, with only the shapes that belong to it"
[file-data component] [file-data component]
@ -356,7 +366,7 @@
(recur (add-main-instance file-data component position) (recur (add-main-instance file-data component position)
(rest components-seq) (rest components-seq)
(rest position-seq))))))) (rest position-seq)))))))
root-to-board root-to-board
(fn [shape] (fn [shape]
(cond-> shape (cond-> shape

View file

@ -1649,13 +1649,14 @@
process-shape process-shape
(fn [_ shape] (fn [_ shape]
(-> shape (-> shape
(assoc :frame-id frame-id) (assoc :frame-id frame-id :parent-id parent-id)
(assoc :parent-id parent-id)
;; if foreign instance, detach the shape ;; if foreign instance, detach the shape
(cond-> (foreign-instance? shape paste-objects state) (cond-> (foreign-instance? shape paste-objects state)
(dissoc :component-id :component-file :component-root? (->
:remote-synced? :shape-ref :touched)) (assoc :saved-component-root? (:component-root? shape)) ;; this is used later, if the paste needs to create a new component from the detached shape
(dissoc :component-id :component-file :component-root?
:remote-synced? :shape-ref :touched)))
;; if is a text, remove references to external typographies ;; if is a text, remove references to external typographies
(cond-> (= (:type shape) :text) (cond-> (= (:type shape) :text)
(ctt/remove-external-typographies file-id)))) (ctt/remove-external-typographies file-id))))
@ -1666,7 +1667,7 @@
library-data (wsh/get-file state file-id) library-data (wsh/get-file state file-id)
changes (-> (dws/prepare-duplicate-changes all-objects page selected delta it libraries library-data) changes (-> (dws/prepare-duplicate-changes all-objects page selected delta it libraries library-data file-id)
(pcb/amend-changes (partial process-rchange media-idx)) (pcb/amend-changes (partial process-rchange media-idx))
(pcb/amend-changes (partial change-add-obj-index paste-objects selected index))) (pcb/amend-changes (partial change-add-obj-index paste-objects selected index)))
@ -1927,7 +1928,7 @@
shape-grid shape-grid
(ctst/generate-shape-grid media-points start-pos grid-gap) (ctst/generate-shape-grid media-points start-pos grid-gap)
stoper (rx/filter (ptk/type? ::finalize-file) stream)] stoper (rx/filter (ptk/type? ::finalize-file) stream)]
(rx/concat (rx/concat

View file

@ -61,6 +61,33 @@
;; ---- Components and instances creation ---- ;; ---- Components and instances creation ----
(defn generate-add-component-changes
[changes root objects file-id page-id components-v2]
(let [name (:name root)
[path name] (cph/parse-path-name name)
[root-shape new-shapes updated-shapes]
(if-not components-v2
(ctn/make-component-shape root objects file-id components-v2)
(let [new-id (uuid/next)]
[(assoc root :id new-id)
nil
[(assoc root
:component-id new-id
:component-file file-id
:component-root? true
:main-instance? true)]]))
changes (-> changes
(pcb/add-component (:id root-shape)
path
name
new-shapes
updated-shapes
(:id root)
page-id))]
[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 component, "If there is exactly one id, and it's a frame (or a group in v1), and not already a component,
use it as root. Otherwise, create a frame (v2) or group (v1) that contains all ids. Then, make a use it as root. Otherwise, create a frame (v2) or group (v1) that contains all ids. Then, make a
@ -94,29 +121,7 @@
root-name root-name
true)))) true))))
name (:name root) [root-shape changes] (generate-add-component-changes changes root objects file-id page-id components-v2)]
[path name] (cph/parse-path-name name)
[root-shape new-shapes updated-shapes]
(if-not components-v2
(ctn/make-component-shape root objects file-id components-v2)
(let [new-id (uuid/next)]
[(assoc root :id new-id)
nil
[(assoc root
:component-id new-id
:component-file file-id
:component-root? true
:main-instance? true)]]))
changes (-> changes
(pcb/add-component (:id root-shape)
path
name
new-shapes
updated-shapes
(:id root)
page-id))]
[root (:id root-shape) changes])) [root (:id root-shape) changes]))
(defn duplicate-component (defn duplicate-component

View file

@ -7,6 +7,7 @@
(ns app.main.data.workspace.selection (ns app.main.data.workspace.selection
(:require (:require
[app.common.data :as d] [app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.math :as mth] [app.common.math :as mth]
@ -14,7 +15,6 @@
[app.common.pages.changes-builder :as pcb] [app.common.pages.changes-builder :as pcb]
[app.common.pages.helpers :as cph] [app.common.pages.helpers :as cph]
[app.common.spec :as us] [app.common.spec :as us]
[app.common.types.component :as ctk]
[app.common.types.file :as ctf] [app.common.types.file :as ctf]
[app.common.types.page :as ctp] [app.common.types.page :as ctp]
[app.common.types.shape.interactions :as ctsi] [app.common.types.shape.interactions :as ctsi]
@ -333,14 +333,14 @@
(defn prepare-duplicate-changes (defn prepare-duplicate-changes
"Prepare objects to duplicate: generate new id, give them unique names, "Prepare objects to duplicate: generate new id, give them unique names,
move to the desired position, and recalculate parents and frames as needed." move to the desired position, and recalculate parents and frames as needed."
([all-objects page ids delta it libraries library-data] ([all-objects page ids delta it libraries library-data file-id]
(let [init-changes (let [init-changes
(-> (pcb/empty-changes it) (-> (pcb/empty-changes it)
(pcb/with-page page) (pcb/with-page page)
(pcb/with-objects all-objects))] (pcb/with-objects all-objects))]
(prepare-duplicate-changes all-objects page ids delta it libraries library-data init-changes))) (prepare-duplicate-changes all-objects page ids delta it libraries library-data file-id init-changes)))
([all-objects page ids delta it libraries library-data init-changes] ([all-objects page ids delta it libraries library-data file-id init-changes]
(let [shapes (map (d/getf all-objects) ids) (let [shapes (map (d/getf all-objects) ids)
unames (volatile! (cp/retrieve-used-names (:objects page))) unames (volatile! (cp/retrieve-used-names (:objects page)))
update-unames! (fn [new-name] (vswap! unames conj new-name)) update-unames! (fn [new-name] (vswap! unames conj new-name))
@ -359,7 +359,8 @@
delta delta
libraries libraries
library-data library-data
it) it
file-id)
init-changes))] init-changes))]
(-> changes (-> changes
@ -367,42 +368,42 @@
(prepare-duplicate-guides shapes page ids-map delta))))) (prepare-duplicate-guides shapes page ids-map delta)))))
(defn- prepare-duplicate-component-change (defn- prepare-duplicate-component-change
([changes page component-root delta libraries library-data it] [changes page component-root delta libraries library-data it]
(let [component-id (:component-id component-root) (let [component-id (:component-id component-root)
file-id (:component-file component-root) file-id (:component-file component-root)
main-component (ctf/get-component libraries file-id component-id) main-component (ctf/get-component libraries file-id component-id)
moved-component (gsh/move component-root delta) moved-component (gsh/move component-root delta)
pos (gpt/point (:x moved-component) (:y moved-component)) pos (gpt/point (:x moved-component) (:y moved-component))
instantiate-component instantiate-component
#(dwlh/generate-instantiate-component changes #(dwlh/generate-instantiate-component changes
file-id file-id
(:component-id component-root) (:component-id component-root)
pos pos
page page
libraries libraries
(:id component-root)) (:id component-root))
restore-component restore-component
#(let [restore (dwlh/prepare-restore-component library-data (:component-id component-root) it page delta (:id component-root) changes)] #(let [restore (dwlh/prepare-restore-component library-data (:component-id component-root) it page delta (:id component-root) changes)]
[(:shape restore) (:changes restore)]) [(:shape restore) (:changes restore)])
[_shape changes] [_shape changes]
(if (nil? main-component) (if (nil? main-component)
(restore-component) (restore-component)
(instantiate-component))] (instantiate-component))]
changes))) changes))
(defn- prepare-duplicate-shape-change (defn- prepare-duplicate-shape-change
([changes objects page unames update-unames! ids-map obj delta libraries library-data it] ([changes objects page unames update-unames! ids-map obj delta libraries library-data it file-id]
(prepare-duplicate-shape-change changes objects page unames update-unames! ids-map obj delta libraries library-data it (:frame-id obj) (:parent-id obj))) (prepare-duplicate-shape-change changes objects page unames update-unames! ids-map obj delta libraries library-data it file-id (:frame-id obj) (:parent-id obj)))
([changes objects page unames update-unames! ids-map obj delta libraries library-data it frame-id parent-id] ([changes objects page unames update-unames! ids-map obj delta libraries library-data it file-id frame-id parent-id]
(cond (cond
(nil? obj) (nil? obj)
changes changes
(ctk/main-instance? obj) (ctf/is-known-component? obj libraries)
(prepare-duplicate-component-change changes page obj delta libraries library-data it) (prepare-duplicate-component-change changes page obj delta libraries library-data it)
:else :else
@ -411,6 +412,14 @@
parent-id (or parent-id frame-id) parent-id (or parent-id frame-id)
name (:name obj) name (:name obj)
is-component-root? (:saved-component-root? obj)
is-component-main? (:main-instance? obj)
regenerate-component
(fn [changes shape]
(let [components-v2 (dm/get-in library-data [:options :components-v2])
[_ changes] (dwlh/generate-add-component-changes changes shape objects file-id (:id page) components-v2)]
changes))
new-obj (-> obj new-obj (-> obj
(assoc :id new-id (assoc :id new-id
:name name :name name
@ -423,7 +432,11 @@
(d/update-when :interactions #(ctsi/remap-interactions % ids-map objects))) (d/update-when :interactions #(ctsi/remap-interactions % ids-map objects)))
changes (-> (pcb/add-object changes new-obj {:ignore-touched true}) changes (-> (pcb/add-object changes new-obj {:ignore-touched true})
(pcb/amend-last-change #(assoc % :old-id (:id obj))))] (pcb/amend-last-change #(assoc % :old-id (:id obj))))
changes (cond-> changes
(and is-component-root? is-component-main?)
(regenerate-component new-obj))]
(reduce (fn [changes child] (reduce (fn [changes child]
(prepare-duplicate-shape-change changes (prepare-duplicate-shape-change changes
@ -437,6 +450,7 @@
libraries libraries
library-data library-data
it it
file-id
(if frame? new-id frame-id) (if frame? new-id frame-id)
new-id)) new-id))
changes changes
@ -593,7 +607,7 @@
libraries (wsh/get-libraries state) libraries (wsh/get-libraries state)
library-data (wsh/get-file state file-id) library-data (wsh/get-file state file-id)
changes (->> (prepare-duplicate-changes objects page selected delta it libraries library-data) changes (->> (prepare-duplicate-changes objects page selected delta it libraries library-data file-id)
(duplicate-changes-update-indices objects selected)) (duplicate-changes-update-indices objects selected))
tags (or (:tags changes) #{}) tags (or (:tags changes) #{})