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:
parent
da54557aab
commit
4ddd3811b2
5 changed files with 100 additions and 66 deletions
|
@ -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]
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) #{})
|
||||||
|
|
Loading…
Add table
Reference in a new issue