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)))))))
|
||||
|
||||
(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])]
|
||||
(when-not (:deleted component)
|
||||
component)))
|
||||
(when (or include-deleted?
|
||||
(not (:deleted component)))
|
||||
component))))
|
||||
|
||||
(defn get-deleted-component
|
||||
[file-data component-id]
|
||||
|
|
|
@ -171,6 +171,16 @@
|
|||
(cph/get-children-with-self (:objects instance-page) (:main-instance-id 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
|
||||
"Add an :objects property to the component, with only the shapes that belong to it"
|
||||
[file-data component]
|
||||
|
|
|
@ -1649,13 +1649,14 @@
|
|||
process-shape
|
||||
(fn [_ shape]
|
||||
(-> shape
|
||||
(assoc :frame-id frame-id)
|
||||
(assoc :parent-id parent-id)
|
||||
(assoc :frame-id frame-id :parent-id parent-id)
|
||||
|
||||
;; if foreign instance, detach the shape
|
||||
(cond-> (foreign-instance? shape paste-objects state)
|
||||
(->
|
||||
(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))
|
||||
:remote-synced? :shape-ref :touched)))
|
||||
;; if is a text, remove references to external typographies
|
||||
(cond-> (= (:type shape) :text)
|
||||
(ctt/remove-external-typographies file-id))))
|
||||
|
@ -1666,7 +1667,7 @@
|
|||
|
||||
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 change-add-obj-index paste-objects selected index)))
|
||||
|
||||
|
|
|
@ -61,6 +61,33 @@
|
|||
|
||||
;; ---- 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
|
||||
"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
|
||||
|
@ -94,29 +121,7 @@
|
|||
root-name
|
||||
true))))
|
||||
|
||||
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] (generate-add-component-changes changes root objects file-id page-id components-v2)]
|
||||
[root (:id root-shape) changes]))
|
||||
|
||||
(defn duplicate-component
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.data.workspace.selection
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
|
@ -14,7 +15,6 @@
|
|||
[app.common.pages.changes-builder :as pcb]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.component :as ctk]
|
||||
[app.common.types.file :as ctf]
|
||||
[app.common.types.page :as ctp]
|
||||
[app.common.types.shape.interactions :as ctsi]
|
||||
|
@ -333,14 +333,14 @@
|
|||
(defn prepare-duplicate-changes
|
||||
"Prepare objects to duplicate: generate new id, give them unique names,
|
||||
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
|
||||
(-> (pcb/empty-changes it)
|
||||
(pcb/with-page page)
|
||||
(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)
|
||||
unames (volatile! (cp/retrieve-used-names (:objects page)))
|
||||
update-unames! (fn [new-name] (vswap! unames conj new-name))
|
||||
|
@ -359,7 +359,8 @@
|
|||
delta
|
||||
libraries
|
||||
library-data
|
||||
it)
|
||||
it
|
||||
file-id)
|
||||
init-changes))]
|
||||
|
||||
(-> changes
|
||||
|
@ -367,7 +368,7 @@
|
|||
(prepare-duplicate-guides shapes page ids-map delta)))))
|
||||
|
||||
(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)
|
||||
file-id (:component-file component-root)
|
||||
main-component (ctf/get-component libraries file-id component-id)
|
||||
|
@ -391,18 +392,18 @@
|
|||
(if (nil? main-component)
|
||||
(restore-component)
|
||||
(instantiate-component))]
|
||||
changes)))
|
||||
changes))
|
||||
|
||||
(defn- prepare-duplicate-shape-change
|
||||
([changes objects page unames update-unames! ids-map obj delta libraries library-data it]
|
||||
(prepare-duplicate-shape-change changes objects page unames update-unames! ids-map obj delta libraries library-data it (:frame-id obj) (:parent-id obj)))
|
||||
([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 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
|
||||
(nil? obj)
|
||||
changes
|
||||
|
||||
(ctk/main-instance? obj)
|
||||
(ctf/is-known-component? obj libraries)
|
||||
(prepare-duplicate-component-change changes page obj delta libraries library-data it)
|
||||
|
||||
:else
|
||||
|
@ -411,6 +412,14 @@
|
|||
parent-id (or parent-id frame-id)
|
||||
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
|
||||
(assoc :id new-id
|
||||
:name name
|
||||
|
@ -423,7 +432,11 @@
|
|||
(d/update-when :interactions #(ctsi/remap-interactions % ids-map objects)))
|
||||
|
||||
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]
|
||||
(prepare-duplicate-shape-change changes
|
||||
|
@ -437,6 +450,7 @@
|
|||
libraries
|
||||
library-data
|
||||
it
|
||||
file-id
|
||||
(if frame? new-id frame-id)
|
||||
new-id))
|
||||
changes
|
||||
|
@ -593,7 +607,7 @@
|
|||
libraries (wsh/get-libraries state)
|
||||
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))
|
||||
|
||||
tags (or (:tags changes) #{})
|
||||
|
|
Loading…
Add table
Reference in a new issue