mirror of
https://github.com/penpot/penpot.git
synced 2025-05-12 16:26:44 +02:00
🔧 Read component shapes from pages
This commit is contained in:
parent
a4dd5fccff
commit
0711fa700b
21 changed files with 588 additions and 403 deletions
|
@ -492,10 +492,13 @@
|
||||||
|
|
||||||
(library-summary [{:keys [id data] :as file}]
|
(library-summary [{:keys [id data] :as file}]
|
||||||
(binding [pmap/*load-fn* (partial load-pointer conn id)]
|
(binding [pmap/*load-fn* (partial load-pointer conn id)]
|
||||||
{:components (assets-sample (:components data) 4)
|
(let [components-sample (-> (assets-sample (:components data) 4)
|
||||||
:media (assets-sample (:media data) 3)
|
(update :sample
|
||||||
:colors (assets-sample (:colors data) 3)
|
#(map (partial ctf/load-component-objects data) %)))]
|
||||||
:typographies (assets-sample (:typographies data) 3)}))]
|
{:components components-sample
|
||||||
|
:media (assets-sample (:media data) 3)
|
||||||
|
:colors (assets-sample (:colors data) 3)
|
||||||
|
:typographies (assets-sample (:typographies data) 3)})))]
|
||||||
|
|
||||||
(->> (db/exec! conn [sql:team-shared-files team-id])
|
(->> (db/exec! conn [sql:team-shared-files team-id])
|
||||||
(into #{} (comp
|
(into #{} (comp
|
||||||
|
@ -552,7 +555,10 @@
|
||||||
(map (fn [{:keys [id] :as row}]
|
(map (fn [{:keys [id] :as row}]
|
||||||
(binding [pmap/*load-fn* (partial load-pointer conn id)]
|
(binding [pmap/*load-fn* (partial load-pointer conn id)]
|
||||||
(-> row
|
(-> row
|
||||||
(update :data dissoc :pages-index)
|
;; TODO: re-enable this dissoc and replace call
|
||||||
|
;; with other that gets files individually
|
||||||
|
;; See task https://tree.taiga.io/project/penpot/task/4904
|
||||||
|
;; (update :data dissoc :pages-index)
|
||||||
(handle-file-features client-features)))))
|
(handle-file-features client-features)))))
|
||||||
(vec)))
|
(vec)))
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
"A version parsing helper."
|
"A version parsing helper."
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
|
@ -664,9 +665,10 @@
|
||||||
[_ shapes]
|
[_ shapes]
|
||||||
(ctn/make-component-instance page
|
(ctn/make-component-instance page
|
||||||
component
|
component
|
||||||
(:id file)
|
(:data file)
|
||||||
(gpt/point main-instance-x
|
(gpt/point main-instance-x
|
||||||
main-instance-y)
|
main-instance-y)
|
||||||
|
true
|
||||||
{:main-instance? true
|
{:main-instance? true
|
||||||
:force-id main-instance-id})]
|
:force-id main-instance-id})]
|
||||||
(as-> file $
|
(as-> file $
|
||||||
|
@ -701,12 +703,15 @@
|
||||||
component (ctkl/get-component (:data file) component-id)
|
component (ctkl/get-component (:data file) component-id)
|
||||||
;; main-instance-id (:main-instance-id component)
|
;; main-instance-id (:main-instance-id component)
|
||||||
|
|
||||||
|
components-v2 (dm/get-in file [:options :components-v2])
|
||||||
|
|
||||||
[shape shapes]
|
[shape shapes]
|
||||||
(ctn/make-component-instance page
|
(ctn/make-component-instance page
|
||||||
component
|
component
|
||||||
(:id file)
|
(:id file)
|
||||||
(gpt/point x
|
(gpt/point x
|
||||||
y)
|
y)
|
||||||
|
components-v2
|
||||||
#_{:main-instance? true
|
#_{:main-instance? true
|
||||||
:force-id main-instance-id})]
|
:force-id main-instance-id})]
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.pages :as cp]
|
[app.common.pages :as cp]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.common.types.file :as ctf]
|
[app.common.types.file :as ctf]
|
||||||
[app.common.uuid :as uuid]))
|
[app.common.uuid :as uuid]))
|
||||||
|
|
||||||
|
@ -598,13 +599,14 @@
|
||||||
(update :redo-changes
|
(update :redo-changes
|
||||||
(fn [redo-changes]
|
(fn [redo-changes]
|
||||||
(-> redo-changes
|
(-> redo-changes
|
||||||
(conj {:type :add-component
|
(conj (cond-> {:type :add-component
|
||||||
:id id
|
:id id
|
||||||
:path path
|
:path path
|
||||||
:name name
|
:name name
|
||||||
:main-instance-id main-instance-id
|
:main-instance-id main-instance-id
|
||||||
:main-instance-page main-instance-page
|
:main-instance-page main-instance-page}
|
||||||
:shapes new-shapes})
|
(some? new-shapes) ;; this will be null in components-v2
|
||||||
|
(assoc :shapes new-shapes)))
|
||||||
(into (map mk-change) updated-shapes))))
|
(into (map mk-change) updated-shapes))))
|
||||||
(update :undo-changes
|
(update :undo-changes
|
||||||
(fn [undo-changes]
|
(fn [undo-changes]
|
||||||
|
@ -640,8 +642,9 @@
|
||||||
(defn delete-component
|
(defn delete-component
|
||||||
[changes id components-v2]
|
[changes id components-v2]
|
||||||
(assert-library changes)
|
(assert-library changes)
|
||||||
(let [library-data (::library-data (meta changes))
|
(let [library-data (::library-data (meta changes))
|
||||||
prev-component (get-in library-data [:components id])]
|
component (ctkl/get-component library-data id)
|
||||||
|
shapes (ctf/get-component-shapes library-data component)]
|
||||||
(-> changes
|
(-> changes
|
||||||
(update :redo-changes conj {:type :del-component
|
(update :redo-changes conj {:type :del-component
|
||||||
:id id})
|
:id id})
|
||||||
|
@ -655,11 +658,11 @@
|
||||||
:always
|
:always
|
||||||
(d/preconj {:type :add-component
|
(d/preconj {:type :add-component
|
||||||
:id id
|
:id id
|
||||||
:name (:name prev-component)
|
:name (:name component)
|
||||||
:path (:path prev-component)
|
:path (:path component)
|
||||||
:main-instance-id (:main-instance-id prev-component)
|
:main-instance-id (:main-instance-id component)
|
||||||
:main-instance-page (:main-instance-page prev-component)
|
:main-instance-page (:main-instance-page component)
|
||||||
:shapes (vals (:objects prev-component))})))))))
|
:shapes shapes})))))))
|
||||||
|
|
||||||
(defn restore-component
|
(defn restore-component
|
||||||
[changes id]
|
[changes id]
|
||||||
|
|
|
@ -153,8 +153,8 @@
|
||||||
(s/coll-of ::cts/shape))
|
(s/coll-of ::cts/shape))
|
||||||
|
|
||||||
(defmethod change-spec :add-component [_]
|
(defmethod change-spec :add-component [_]
|
||||||
(s/keys :req-un [::id ::name :internal.changes.add-component/shapes]
|
(s/keys :req-un [::id ::name]
|
||||||
:opt-un [::path]))
|
:opt-un [::path :internal.changes.add-component/shapes]))
|
||||||
|
|
||||||
(defmethod change-spec :mod-component [_]
|
(defmethod change-spec :mod-component [_]
|
||||||
(s/keys :req-un [::id]
|
(s/keys :req-un [::id]
|
||||||
|
|
|
@ -270,25 +270,6 @@
|
||||||
[shape group]
|
[shape group]
|
||||||
((or (:touched shape) #{}) group))
|
((or (:touched shape) #{}) group))
|
||||||
|
|
||||||
(defn get-component
|
|
||||||
"Retrieve a component from libraries, if no library-id is provided, we
|
|
||||||
iterate over all libraries and find the component on it."
|
|
||||||
([libraries component-id]
|
|
||||||
(some #(-> % :data :components (get component-id)) (vals libraries)))
|
|
||||||
([libraries library-id component-id]
|
|
||||||
(get-in libraries [library-id :data :components component-id])))
|
|
||||||
|
|
||||||
(defn get-component-shape
|
|
||||||
"Get the parent shape linked to a component for this shape, if any"
|
|
||||||
[objects shape]
|
|
||||||
(if-not (:shape-ref shape)
|
|
||||||
nil
|
|
||||||
(if (:component-id shape)
|
|
||||||
shape
|
|
||||||
(if-let [parent-id (:parent-id shape)]
|
|
||||||
(get-component-shape objects (get objects parent-id))
|
|
||||||
nil))))
|
|
||||||
|
|
||||||
(defn get-root-shape
|
(defn get-root-shape
|
||||||
"Get the root shape linked to a component for this shape, if any."
|
"Get the root shape linked to a component for this shape, if any."
|
||||||
[objects shape]
|
[objects shape]
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
(and (= shape-id (:main-instance-id component))
|
(and (= shape-id (:main-instance-id component))
|
||||||
(= page-id (:main-instance-page component))))
|
(= page-id (:main-instance-page component))))
|
||||||
|
|
||||||
|
;; Obsolete in components-v2
|
||||||
(defn get-component-root
|
(defn get-component-root
|
||||||
[component]
|
[component]
|
||||||
(get-in component [:objects (:id component)]))
|
(get-in component [:objects (:id component)]))
|
||||||
|
@ -45,12 +46,12 @@
|
||||||
(= (:component-file shape) library-id)))
|
(= (:component-file shape) library-id)))
|
||||||
|
|
||||||
(defn in-component-instance?
|
(defn in-component-instance?
|
||||||
"Check if the shape is inside a component instance."
|
"Check if the shape is inside a component non-main instance."
|
||||||
[shape]
|
[shape]
|
||||||
(some? (:shape-ref shape)))
|
(some? (:shape-ref shape)))
|
||||||
|
|
||||||
(defn in-component-instance-not-root?
|
(defn in-component-instance-not-root?
|
||||||
"Check if the shape is inside a component instance and
|
"Check if the shape is inside a component non-main instance and
|
||||||
is not the root shape."
|
is not the root shape."
|
||||||
[shape]
|
[shape]
|
||||||
(and (some? (:shape-ref shape))
|
(and (some? (:shape-ref shape))
|
||||||
|
|
|
@ -23,11 +23,13 @@
|
||||||
(assoc-in [:components id]
|
(assoc-in [:components id]
|
||||||
{:id id
|
{:id id
|
||||||
:name name
|
:name name
|
||||||
:path path
|
:path path})
|
||||||
:objects (->> shapes
|
|
||||||
(d/index-by :id)
|
|
||||||
(wrap-object-fn))})
|
|
||||||
|
|
||||||
|
(not components-v2)
|
||||||
|
(assoc-in [:components id :objects]
|
||||||
|
(->> shapes
|
||||||
|
(d/index-by :id)
|
||||||
|
(wrap-object-fn)))
|
||||||
components-v2
|
components-v2
|
||||||
(update-in [:components id] assoc
|
(update-in [:components id] assoc
|
||||||
:main-instance-id main-instance-id
|
:main-instance-id main-instance-id
|
||||||
|
@ -60,4 +62,3 @@
|
||||||
(defn delete-component
|
(defn delete-component
|
||||||
[file-data component-id]
|
[file-data component-id]
|
||||||
(update file-data :components dissoc component-id))
|
(update file-data :components dissoc component-id))
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.pages.common :as common]
|
[app.common.pages.common :as common]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
|
[app.common.types.pages-list :as ctpl]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
[clojure.spec.alpha :as s]))
|
[clojure.spec.alpha :as s]))
|
||||||
|
|
||||||
|
@ -62,6 +63,17 @@
|
||||||
[container shape-id f]
|
[container shape-id f]
|
||||||
(update-in container [:objects shape-id] f))
|
(update-in container [:objects shape-id] f))
|
||||||
|
|
||||||
|
(defn get-component-shape
|
||||||
|
"Get the parent shape linked to a component for this shape, if any"
|
||||||
|
[objects shape]
|
||||||
|
(if-not (:shape-ref shape)
|
||||||
|
nil
|
||||||
|
(if (:component-id shape)
|
||||||
|
shape
|
||||||
|
(if-let [parent-id (:parent-id shape)]
|
||||||
|
(get-component-shape objects (get objects parent-id))
|
||||||
|
nil))))
|
||||||
|
|
||||||
(defn make-component-shape
|
(defn make-component-shape
|
||||||
"Clone the shape and all children. Generate new ids and detach
|
"Clone the shape and all children. Generate new ids and detach
|
||||||
from parent and frame. Update the original shapes to have links
|
from parent and frame. Update the original shapes to have links
|
||||||
|
@ -117,15 +129,22 @@
|
||||||
[new-root-shape (map remap-frame-id new-shapes) updated-shapes]))
|
[new-root-shape (map remap-frame-id new-shapes) updated-shapes]))
|
||||||
|
|
||||||
(defn make-component-instance
|
(defn make-component-instance
|
||||||
"Clone the shapes of the component, generating new names and ids, and linking
|
"Generate a new instance of the component inside the given container.
|
||||||
|
|
||||||
|
Clone the shapes of the component, generating new names and ids, and linking
|
||||||
each new shape to the corresponding one of the component. Place the new instance
|
each new shape to the corresponding one of the component. Place the new instance
|
||||||
coordinates in the given position."
|
coordinates in the given position."
|
||||||
([container component component-file-id position]
|
([container component library-data position components-v2]
|
||||||
(make-component-instance container component component-file-id position {}))
|
(make-component-instance container component library-data position components-v2 {}))
|
||||||
|
|
||||||
([container component component-file-id position
|
([container component library-data position components-v2
|
||||||
{:keys [main-instance? force-id] :or {main-instance? false force-id nil}}]
|
{:keys [main-instance? force-id] :or {main-instance? false force-id nil}}]
|
||||||
(let [component-shape (get-shape component (:id component))
|
(let [component-page (when components-v2
|
||||||
|
(ctpl/get-page library-data (:main-instance-page component)))
|
||||||
|
component-shape (if components-v2
|
||||||
|
(-> (get-shape component-page (:main-instance-id component))
|
||||||
|
(assoc :parent-id nil))
|
||||||
|
(get-shape component (:id component)))
|
||||||
|
|
||||||
orig-pos (gpt/point (:x component-shape) (:y component-shape))
|
orig-pos (gpt/point (:x component-shape) (:y component-shape))
|
||||||
delta (gpt/subtract position orig-pos)
|
delta (gpt/subtract position orig-pos)
|
||||||
|
@ -147,20 +166,20 @@
|
||||||
(vswap! frame-ids-map assoc (:id original-shape) (:id new-shape)))
|
(vswap! frame-ids-map assoc (:id original-shape) (:id new-shape)))
|
||||||
|
|
||||||
(cond-> new-shape
|
(cond-> new-shape
|
||||||
true
|
:always
|
||||||
(-> (gsh/move delta)
|
(-> (gsh/move delta)
|
||||||
(dissoc :touched))
|
(dissoc :touched :main-instance?))
|
||||||
|
|
||||||
(nil? (:shape-ref original-shape))
|
(nil? (:shape-ref original-shape))
|
||||||
(assoc :shape-ref (:id original-shape))
|
(assoc :shape-ref (:id original-shape))
|
||||||
|
|
||||||
(nil? (:parent-id original-shape))
|
(nil? (:parent-id original-shape))
|
||||||
(assoc :component-id (:id original-shape)
|
(assoc :component-id (:id component)
|
||||||
:component-file component-file-id
|
:component-file (:id library-data)
|
||||||
:component-root? true
|
:component-root? true
|
||||||
:name new-name)
|
:name new-name)
|
||||||
|
|
||||||
(and (nil? (:parent-id original-shape)) main-instance?)
|
(and (nil? (:parent-id original-shape)) main-instance? components-v2)
|
||||||
(assoc :main-instance? true)
|
(assoc :main-instance? true)
|
||||||
|
|
||||||
(some? (:parent-id original-shape))
|
(some? (:parent-id original-shape))
|
||||||
|
@ -169,7 +188,7 @@
|
||||||
[new-shape new-shapes _]
|
[new-shape new-shapes _]
|
||||||
(ctst/clone-object component-shape
|
(ctst/clone-object component-shape
|
||||||
nil
|
nil
|
||||||
(get component :objects)
|
(if components-v2 (:objects component-page) (:objects component))
|
||||||
update-new-shape
|
update-new-shape
|
||||||
(fn [object _] object)
|
(fn [object _] object)
|
||||||
force-id)
|
force-id)
|
||||||
|
@ -177,10 +196,10 @@
|
||||||
;; If frame-id points to a shape inside the component, remap it to the
|
;; If frame-id points to a shape inside the component, remap it to the
|
||||||
;; corresponding new frame shape. If not, set it to the destination frame.
|
;; corresponding new frame shape. If not, set it to the destination frame.
|
||||||
;; Also fix empty parent-id.
|
;; Also fix empty parent-id.
|
||||||
remap-frame-id (fn [shape]
|
remap-frame-id (fn [shape]
|
||||||
(as-> shape $
|
(as-> shape $
|
||||||
(update $ :frame-id #(get @frame-ids-map % frame-id))
|
(update $ :frame-id #(get @frame-ids-map % frame-id))
|
||||||
(update $ :parent-id #(or % (:frame-id $)))))]
|
(update $ :parent-id #(or % (:frame-id $)))))]
|
||||||
|
|
||||||
[new-shape (map remap-frame-id new-shapes)])))
|
[new-shape (map remap-frame-id new-shapes)])))
|
||||||
|
|
||||||
|
|
|
@ -6,27 +6,27 @@
|
||||||
|
|
||||||
(ns app.common.types.file
|
(ns app.common.types.file
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.files.features :as ffeat]
|
[app.common.files.features :as ffeat]
|
||||||
[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.pages.common :refer [file-version]]
|
[app.common.pages.common :refer [file-version]]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.types.color :as ctc]
|
[app.common.types.color :as ctc]
|
||||||
[app.common.types.colors-list :as ctcl]
|
[app.common.types.colors-list :as ctcl]
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
[app.common.types.components-list :as ctkl]
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.common.types.container :as ctn]
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.file.media-object :as ctfm]
|
[app.common.types.file.media-object :as ctfm]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
[app.common.types.pages-list :as ctpl]
|
[app.common.types.pages-list :as ctpl]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
[app.common.types.typographies-list :as ctyl]
|
[app.common.types.typographies-list :as ctyl]
|
||||||
[app.common.types.typography :as cty]
|
[app.common.types.typography :as cty]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[clojure.spec.alpha :as s]
|
[clojure.spec.alpha :as s]
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]))
|
||||||
|
|
||||||
;; Specs
|
;; Specs
|
||||||
|
|
||||||
|
@ -116,6 +116,75 @@
|
||||||
([libraries library-id component-id]
|
([libraries library-id component-id]
|
||||||
(ctkl/get-component (dm/get-in libraries [library-id :data]) component-id)))
|
(ctkl/get-component (dm/get-in libraries [library-id :data]) component-id)))
|
||||||
|
|
||||||
|
(defn get-component-library
|
||||||
|
"Retrieve the library the component belongs to."
|
||||||
|
[libraries instance-root]
|
||||||
|
(get libraries (:component-file instance-root)))
|
||||||
|
|
||||||
|
(defn get-component-page
|
||||||
|
"Retrieve the page where the main instance of the component resides."
|
||||||
|
[file-data component]
|
||||||
|
(ctpl/get-page file-data (:main-instance-page component)))
|
||||||
|
|
||||||
|
(defn get-component-container
|
||||||
|
"Retrieve the container that holds the component shapes (the page in components-v2
|
||||||
|
or the component itself in v1)"
|
||||||
|
[file-data component]
|
||||||
|
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
||||||
|
(if components-v2
|
||||||
|
(let [component-page (get-component-page file-data component)]
|
||||||
|
(cph/make-container component-page :page))
|
||||||
|
(cph/make-container component :component))))
|
||||||
|
|
||||||
|
(defn get-component-root
|
||||||
|
"Retrieve the root shape of the component."
|
||||||
|
[file-data component]
|
||||||
|
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
||||||
|
(if components-v2
|
||||||
|
(-> file-data
|
||||||
|
(get-component-page component)
|
||||||
|
(ctn/get-shape (:main-instance-id component)))
|
||||||
|
(ctk/get-component-root component))))
|
||||||
|
|
||||||
|
(defn get-component-shapes
|
||||||
|
"Retrieve all shapes of the component"
|
||||||
|
[file-data component]
|
||||||
|
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
||||||
|
(if components-v2
|
||||||
|
(let [instance-page (get-component-page file-data component)]
|
||||||
|
(cph/get-children-with-self (:objects instance-page) (:main-instance-id component)))
|
||||||
|
(vals (:objects component)))))
|
||||||
|
|
||||||
|
(defn get-component-shape
|
||||||
|
"Retrieve one shape in the component."
|
||||||
|
[file-data component shape-id]
|
||||||
|
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
||||||
|
(if components-v2
|
||||||
|
(let [component-page (get-component-page file-data component)]
|
||||||
|
(ctn/get-shape component-page shape-id))
|
||||||
|
(dm/get-in component [:objects shape-id]))))
|
||||||
|
|
||||||
|
(defn get-ref-shape
|
||||||
|
"Retrieve the shape in the component that is referenced by the
|
||||||
|
instance shape."
|
||||||
|
[file-data component shape]
|
||||||
|
(when (:shape-ref shape)
|
||||||
|
(get-component-shape file-data component (:shape-ref shape))))
|
||||||
|
|
||||||
|
(defn load-component-objects
|
||||||
|
"Add an :objects property to the component, with only the shapes that belong to it"
|
||||||
|
[file-data component]
|
||||||
|
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
|
||||||
|
(if components-v2
|
||||||
|
(let [component-page (get-component-page file-data component)
|
||||||
|
page-objects (:objects component-page)
|
||||||
|
objects (->> (cons (:main-instance-id component)
|
||||||
|
(cph/get-children-ids page-objects (:main-instance-id component)))
|
||||||
|
(map #(get page-objects %))
|
||||||
|
(d/index-by :id))]
|
||||||
|
(assoc component :objects objects))
|
||||||
|
component)))
|
||||||
|
|
||||||
(defn delete-component
|
(defn delete-component
|
||||||
"Delete a component and store it to be able to be recovered later.
|
"Delete a component and store it to be able to be recovered later.
|
||||||
|
|
||||||
|
@ -123,26 +192,29 @@
|
||||||
([file-data component-id]
|
([file-data component-id]
|
||||||
(delete-component file-data component-id false))
|
(delete-component file-data component-id false))
|
||||||
|
|
||||||
([file-data component-id skip-undelete?]
|
([file-data component-id _skip-undelete?]
|
||||||
(let [components-v2 (dm/get-in file-data [:options :components-v2])
|
(let [_components-v2 (dm/get-in file-data [:options :components-v2])
|
||||||
|
|
||||||
add-to-deleted-components
|
;; TODO: replace :deleted-components with a :deleted? flag in normal shapes
|
||||||
(fn [file-data]
|
;; see task https://tree.taiga.io/project/penpot/task/4998
|
||||||
(let [component (ctkl/get-component file-data component-id)]
|
;;
|
||||||
(if (some? component)
|
;; add-to-deleted-components
|
||||||
(let [page (ctpl/get-page file-data (:main-instance-page component))
|
;; (fn [file-data]
|
||||||
main-instance (ctn/get-shape page (:main-instance-id component))
|
;; (let [component (ctkl/get-component file-data component-id)]
|
||||||
component (assoc component
|
;; (if (some? component)
|
||||||
:main-instance-x (:x main-instance) ; An instance root is always a group,
|
;; (let [main-instance (get-component-root file-data component)
|
||||||
:main-instance-y (:y main-instance))] ; so it will have :x and :y
|
;; component (assoc component
|
||||||
(when (nil? main-instance)
|
;; :main-instance-x (:x main-instance) ; An instance root is always a group,
|
||||||
(throw (ex-info "Cannot delete the main instance before the component" {:component-id component-id})))
|
;; :main-instance-y (:y main-instance))] ; or a frame, so it will have :x and :y
|
||||||
(assoc-in file-data [:deleted-components component-id] component))
|
;; (when (nil? main-instance)
|
||||||
file-data)))]
|
;; (throw (ex-info "Cannot delete the main instance before the component" {:component-id component-id})))
|
||||||
|
;; (assoc-in file-data [:deleted-components component-id] component))
|
||||||
|
;; file-data)))
|
||||||
|
]
|
||||||
|
|
||||||
(cond-> file-data
|
(cond-> file-data
|
||||||
(and components-v2 (not skip-undelete?))
|
;; (and components-v2 (not skip-undelete?))
|
||||||
(add-to-deleted-components)
|
;; (add-to-deleted-components)
|
||||||
|
|
||||||
:always
|
:always
|
||||||
(ctkl/delete-component component-id)))))
|
(ctkl/delete-component component-id)))))
|
||||||
|
@ -243,8 +315,9 @@
|
||||||
[(ctpl/add-page file-data library-page) (:id library-page) (gpt/point 0 0)]))))
|
[(ctpl/add-page file-data library-page) (:id library-page) (gpt/point 0 0)]))))
|
||||||
|
|
||||||
(defn migrate-to-components-v2
|
(defn migrate-to-components-v2
|
||||||
"If there is any component in the file library, add a new 'Library backup' and generate
|
"If there is any component in the file library, add a new 'Library backup', generate
|
||||||
main instances for all components there. Mark the file with the :components-v2 option."
|
main instances for all components there and remove shapes from library components.
|
||||||
|
Mark the file with the :components-v2 option."
|
||||||
[file-data]
|
[file-data]
|
||||||
(let [components (ctkl/components-seq file-data)]
|
(let [components (ctkl/components-seq file-data)]
|
||||||
(if (or (empty? components)
|
(if (or (empty? components)
|
||||||
|
@ -262,8 +335,9 @@
|
||||||
[new-shape new-shapes]
|
[new-shape new-shapes]
|
||||||
(ctn/make-component-instance page
|
(ctn/make-component-instance page
|
||||||
component
|
component
|
||||||
(:id file-data)
|
file-data
|
||||||
position
|
position
|
||||||
|
false
|
||||||
{:main-instance? true})
|
{:main-instance? true})
|
||||||
|
|
||||||
add-shapes
|
add-shapes
|
||||||
|
@ -281,9 +355,10 @@
|
||||||
|
|
||||||
update-component
|
update-component
|
||||||
(fn [component]
|
(fn [component]
|
||||||
(assoc component
|
(-> component
|
||||||
:main-instance-id (:id new-shape)
|
(assoc :main-instance-id (:id new-shape)
|
||||||
:main-instance-page page-id))]
|
:main-instance-page page-id)
|
||||||
|
(dissoc :objects)))]
|
||||||
|
|
||||||
(-> file-data
|
(-> file-data
|
||||||
(ctpl/update-page page-id add-shapes)
|
(ctpl/update-page page-id add-shapes)
|
||||||
|
@ -292,9 +367,9 @@
|
||||||
add-instance-grid
|
add-instance-grid
|
||||||
(fn [file-data components]
|
(fn [file-data components]
|
||||||
(let [position-seq (ctst/generate-shape-grid
|
(let [position-seq (ctst/generate-shape-grid
|
||||||
(map ctk/get-component-root components)
|
(map (partial get-component-root file-data) components)
|
||||||
start-pos
|
start-pos
|
||||||
grid-gap)]
|
grid-gap)]
|
||||||
(loop [file-data file-data
|
(loop [file-data file-data
|
||||||
components-seq (seq components)
|
components-seq (seq components)
|
||||||
position-seq position-seq]
|
position-seq position-seq]
|
||||||
|
@ -311,7 +386,7 @@
|
||||||
(assoc-in [:options :components-v2] true))))))
|
(assoc-in [:options :components-v2] true))))))
|
||||||
|
|
||||||
(defn- absorb-components
|
(defn- absorb-components
|
||||||
[file-data used-components]
|
[file-data used-components library-data]
|
||||||
(let [grid-gap 50
|
(let [grid-gap 50
|
||||||
|
|
||||||
; Search for the library page. If not exists, create it.
|
; Search for the library page. If not exists, create it.
|
||||||
|
@ -326,10 +401,17 @@
|
||||||
[main-instance-shape main-instance-shapes]
|
[main-instance-shape main-instance-shapes]
|
||||||
(ctn/make-component-instance page
|
(ctn/make-component-instance page
|
||||||
component
|
component
|
||||||
(:id file-data)
|
library-data
|
||||||
position
|
position
|
||||||
|
(dm/get-in file-data [:options :components-v2])
|
||||||
{:main-instance? true})
|
{:main-instance? true})
|
||||||
|
|
||||||
|
main-instance-shapes
|
||||||
|
(map #(cond-> %
|
||||||
|
(some? (:component-file %))
|
||||||
|
(assoc :component-file (:id file-data)))
|
||||||
|
main-instance-shapes)
|
||||||
|
|
||||||
; Add all shapes of the main instance to the library page
|
; Add all shapes of the main instance to the library page
|
||||||
add-main-instance-shapes
|
add-main-instance-shapes
|
||||||
(fn [page]
|
(fn [page]
|
||||||
|
@ -353,7 +435,7 @@
|
||||||
:path (:path component)
|
:path (:path component)
|
||||||
:main-instance-id (:id main-instance-shape)
|
:main-instance-id (:id main-instance-shape)
|
||||||
:main-instance-page page-id
|
:main-instance-page page-id
|
||||||
:shapes (vals (:objects component))}))
|
:shapes (get-component-shapes library-data component)}))
|
||||||
|
|
||||||
; Change all existing instances to point to the local file
|
; Change all existing instances to point to the local file
|
||||||
remap-instances
|
remap-instances
|
||||||
|
@ -378,9 +460,9 @@
|
||||||
add-component-grid
|
add-component-grid
|
||||||
(fn [data used-components]
|
(fn [data used-components]
|
||||||
(let [position-seq (ctst/generate-shape-grid
|
(let [position-seq (ctst/generate-shape-grid
|
||||||
(map #(ctk/get-component-root (first %)) used-components)
|
(map #(get-component-root library-data (first %)) used-components)
|
||||||
start-pos
|
start-pos
|
||||||
grid-gap)]
|
grid-gap)]
|
||||||
(loop [data data
|
(loop [data data
|
||||||
components-seq (seq used-components)
|
components-seq (seq used-components)
|
||||||
position-seq position-seq]
|
position-seq position-seq]
|
||||||
|
@ -410,9 +492,9 @@
|
||||||
remap-shape))
|
remap-shape))
|
||||||
%
|
%
|
||||||
shapes)))]
|
shapes)))]
|
||||||
(as-> file-data $
|
(as-> file-data $
|
||||||
(ctcl/add-color $ color)
|
(ctcl/add-color $ color)
|
||||||
(reduce remap-shapes $ usages))))]
|
(reduce remap-shapes $ usages))))]
|
||||||
|
|
||||||
(reduce absorb-color
|
(reduce absorb-color
|
||||||
file-data
|
file-data
|
||||||
|
@ -434,9 +516,9 @@
|
||||||
remap-shape))
|
remap-shape))
|
||||||
%
|
%
|
||||||
shapes)))]
|
shapes)))]
|
||||||
(as-> file-data $
|
(as-> file-data $
|
||||||
(ctyl/add-typography $ typography)
|
(ctyl/add-typography $ typography)
|
||||||
(reduce remap-shapes $ usages))))]
|
(reduce remap-shapes $ usages))))]
|
||||||
|
|
||||||
(reduce absorb-typography
|
(reduce absorb-typography
|
||||||
file-data
|
file-data
|
||||||
|
@ -452,7 +534,7 @@
|
||||||
|
|
||||||
(cond-> file-data
|
(cond-> file-data
|
||||||
(d/not-empty? used-components)
|
(d/not-empty? used-components)
|
||||||
(absorb-components used-components)
|
(absorb-components used-components library-data)
|
||||||
|
|
||||||
(d/not-empty? used-colors)
|
(d/not-empty? used-colors)
|
||||||
(absorb-colors used-colors)
|
(absorb-colors used-colors)
|
||||||
|
@ -477,69 +559,82 @@
|
||||||
root (d/seek #(nil? (:parent-id %)) (vals objects))]
|
root (d/seek #(nil? (:parent-id %)) (vals objects))]
|
||||||
|
|
||||||
(letfn [(show-shape [shape-id level objects]
|
(letfn [(show-shape [shape-id level objects]
|
||||||
(let [shape (get objects shape-id)]
|
(let [shape (get objects shape-id)]
|
||||||
(println (str/pad (str (str/repeat " " level)
|
(println (str/pad (str (str/repeat " " level)
|
||||||
(:name shape)
|
(when (:main-instance? shape) "{")
|
||||||
(when (seq (:touched shape)) "*")
|
(:name shape)
|
||||||
(when show-ids (str/format " <%s>" (:id shape))))
|
(when (:main-instance? shape) "}")
|
||||||
{:length 20
|
(when (seq (:touched shape)) "*")
|
||||||
:type :right})
|
(when show-ids (str/format " <%s>" (:id shape))))
|
||||||
(show-component shape objects))
|
{:length 20
|
||||||
(when show-touched
|
:type :right})
|
||||||
(when (seq (:touched shape))
|
(show-component-info shape objects))
|
||||||
(println (str (str/repeat " " level)
|
(when show-touched
|
||||||
" "
|
(when (seq (:touched shape))
|
||||||
(str (:touched shape)))))
|
(println (str (str/repeat " " level)
|
||||||
(when (:remote-synced? shape)
|
" "
|
||||||
(println (str (str/repeat " " level)
|
(str (:touched shape)))))
|
||||||
" (remote-synced)"))))
|
(when (:remote-synced? shape)
|
||||||
(when (:shapes shape)
|
(println (str (str/repeat " " level)
|
||||||
(dorun (for [shape-id (:shapes shape)]
|
" (remote-synced)"))))
|
||||||
(show-shape shape-id (inc level) objects))))))
|
(when (:shapes shape)
|
||||||
|
(dorun (for [shape-id (:shapes shape)]
|
||||||
|
(show-shape shape-id (inc level) objects))))))
|
||||||
|
|
||||||
(show-component [shape objects]
|
(show-component-info [shape objects]
|
||||||
(if (nil? (:shape-ref shape))
|
(if (nil? (:shape-ref shape))
|
||||||
""
|
(if (:component-root? shape) " #" "")
|
||||||
(let [root-shape (cph/get-component-shape objects shape)
|
(let [root-shape (ctn/get-component-shape objects shape)
|
||||||
component-id (when root-shape (:component-id root-shape))
|
component-id (when root-shape (:component-id root-shape))
|
||||||
component-file-id (when root-shape (:component-file root-shape))
|
component-file-id (when root-shape (:component-file root-shape))
|
||||||
component-file (when component-file-id (get libraries component-file-id nil))
|
component-file (when component-file-id (get libraries component-file-id nil))
|
||||||
component (when component-id
|
component (when component-id
|
||||||
(if component-file
|
(if component-file
|
||||||
(dm/get-in component-file [:data :components component-id])
|
(dm/get-in component-file [:data :components component-id])
|
||||||
(get components component-id)))
|
(get components component-id)))
|
||||||
component-shape (when (and component (:shape-ref shape))
|
component-shape (when component
|
||||||
(dm/get-in component [:objects (:shape-ref shape)]))]
|
(if component-file
|
||||||
(str/format " %s--> %s%s%s"
|
(get-ref-shape (:data component-file) component shape)
|
||||||
(cond (:component-root? shape) "#"
|
(get-ref-shape file-data component shape)))]
|
||||||
(:component-id shape) "@"
|
|
||||||
:else "-")
|
|
||||||
(when component-file (str/format "<%s> " (:name component-file)))
|
|
||||||
(or (:name component-shape) "?")
|
|
||||||
(if (or (:component-root? shape)
|
|
||||||
(nil? (:component-id shape))
|
|
||||||
true)
|
|
||||||
""
|
|
||||||
(let [component-id (:component-id shape)
|
|
||||||
component-file-id (:component-file shape)
|
|
||||||
component-file (when component-file-id (get libraries component-file-id nil))
|
|
||||||
component (if component-file
|
|
||||||
(dm/get-in component-file [:data :components component-id])
|
|
||||||
(get components component-id))]
|
|
||||||
(str/format " (%s%s)"
|
|
||||||
(when component-file (str/format "<%s> " (:name component-file)))
|
|
||||||
(:name component))))))))]
|
|
||||||
|
|
||||||
(println "[Page]")
|
(str/format " %s--> %s%s%s"
|
||||||
|
(cond (:component-root? shape) "#"
|
||||||
|
(:component-id shape) "@"
|
||||||
|
:else "-")
|
||||||
|
(when component-file (str/format "<%s> " (:name component-file)))
|
||||||
|
(or (:name component-shape) "?")
|
||||||
|
(if (or (:component-root? shape)
|
||||||
|
(nil? (:component-id shape))
|
||||||
|
true)
|
||||||
|
""
|
||||||
|
(let [component-id (:component-id shape)
|
||||||
|
component-file-id (:component-file shape)
|
||||||
|
component-file (when component-file-id (get libraries component-file-id nil))
|
||||||
|
component (if component-file
|
||||||
|
(dm/get-in component-file [:data :components component-id])
|
||||||
|
(get components component-id))]
|
||||||
|
(str/format " (%s%s)"
|
||||||
|
(when component-file (str/format "<%s> " (:name component-file)))
|
||||||
|
(:name component))))))))
|
||||||
|
|
||||||
|
(show-component-instance [component]
|
||||||
|
(let [page (get-component-page file-data component)
|
||||||
|
root (get-component-root file-data component)]
|
||||||
|
(if-not show-ids
|
||||||
|
(println (str " [" (:name page) "] / " (:name root)))
|
||||||
|
(do
|
||||||
|
(println (str " " (:name page) (str/format " <%s>" (:id page))))
|
||||||
|
(println (str " " (:name root) (str/format " <%s>" (:id root))))))))]
|
||||||
|
|
||||||
|
(println (str "[Page: " (:name page) "]"))
|
||||||
(show-shape (:id root) 0 objects)
|
(show-shape (:id root) 0 objects)
|
||||||
|
|
||||||
(dorun (for [component (vals components)]
|
(dorun (for [component (vals components)]
|
||||||
(do
|
(do
|
||||||
(println)
|
(println)
|
||||||
(println (str/format "[%s]" (:name component))
|
(println (str/format "[%s]" (:name component)))
|
||||||
(when show-ids
|
(when (:objects component)
|
||||||
(str/format " (main: %s/%s)"
|
(show-shape (:id component) 0 (:objects component)))
|
||||||
(:main-instance-page component)
|
(when (:main-instance-page component)
|
||||||
(:main-instance-id component))))
|
(show-component-instance component)))))))))
|
||||||
(show-shape (:id component) 0 (:objects component)))))))))
|
|
||||||
|
|
||||||
|
|
|
@ -359,4 +359,3 @@
|
||||||
(iterate next-pos
|
(iterate next-pos
|
||||||
(with-meta start-pos
|
(with-meta start-pos
|
||||||
{:counter 0}))))
|
{:counter 0}))))
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
[clojure.test :as t]
|
[clojure.test :as t]
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
[app.common.types.container :as ctn]))
|
[app.common.types.container :as ctn]
|
||||||
|
[app.common.types.file :as ctf]))
|
||||||
|
|
||||||
;; ---- Helpers to manage libraries and synchronization
|
;; ---- Helpers to manage libraries and synchronization
|
||||||
|
|
||||||
|
@ -81,7 +82,7 @@
|
||||||
[page root-inst-id libraries]
|
[page root-inst-id libraries]
|
||||||
(let [root-inst (ctn/get-shape page root-inst-id)
|
(let [root-inst (ctn/get-shape page root-inst-id)
|
||||||
|
|
||||||
component (cph/get-component libraries (:component-id root-inst))
|
component (ctf/get-component libraries (:component-id root-inst))
|
||||||
|
|
||||||
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
|
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
|
||||||
shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst))
|
shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst))
|
||||||
|
@ -90,10 +91,10 @@
|
||||||
|
|
||||||
main-exists? (fn [shape]
|
main-exists? (fn [shape]
|
||||||
(let [component-shape
|
(let [component-shape
|
||||||
(cph/get-component-shape (:objects page) shape)
|
(ctn/get-component-shape (:objects page) shape)
|
||||||
|
|
||||||
component
|
component
|
||||||
(cph/get-component libraries (:component-id component-shape))
|
(ctf/get-component libraries (:component-id component-shape))
|
||||||
|
|
||||||
main-shape
|
main-shape
|
||||||
(ctn/get-shape component (:shape-ref shape))]
|
(ctn/get-shape component (:shape-ref shape))]
|
||||||
|
@ -117,7 +118,7 @@
|
||||||
[page root-inst-id libraries]
|
[page root-inst-id libraries]
|
||||||
(let [root-inst (ctn/get-shape page root-inst-id)
|
(let [root-inst (ctn/get-shape page root-inst-id)
|
||||||
|
|
||||||
component (cph/get-component libraries (:component-id root-inst))
|
component (ctf/get-component libraries (:component-id root-inst))
|
||||||
|
|
||||||
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
|
shapes-inst (cph/get-children-with-self (:objects page) root-inst-id)
|
||||||
shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst))
|
shapes-main (cph/get-children-with-self (:objects component) (:shape-ref root-inst))
|
||||||
|
@ -126,10 +127,10 @@
|
||||||
|
|
||||||
main-exists? (fn [shape]
|
main-exists? (fn [shape]
|
||||||
(let [component-shape
|
(let [component-shape
|
||||||
(cph/get-component-shape (:objects page) shape)
|
(ctn/get-component-shape (:objects page) shape)
|
||||||
|
|
||||||
component
|
component
|
||||||
(cph/get-component libraries (:component-id component-shape))
|
(ctf/get-component libraries (:component-id component-shape))
|
||||||
|
|
||||||
main-shape
|
main-shape
|
||||||
(ctn/get-shape component (:shape-ref shape))]
|
(ctn/get-shape component (:shape-ref shape))]
|
||||||
|
@ -144,7 +145,7 @@
|
||||||
(defn resolve-component
|
(defn resolve-component
|
||||||
"Get the component with the given id and all its shapes."
|
"Get the component with the given id and all its shapes."
|
||||||
[page component-id libraries]
|
[page component-id libraries]
|
||||||
(let [component (cph/get-component libraries component-id)
|
(let [component (ctf/get-component libraries component-id)
|
||||||
root-main (ctk/get-component-root component)
|
root-main (ctk/get-component-root component)
|
||||||
shapes-main (cph/get-children-with-self (:objects component) (:id root-main))]
|
shapes-main (cph/get-children-with-self (:objects component) (:id root-main))]
|
||||||
|
|
||||||
|
|
|
@ -102,8 +102,9 @@
|
||||||
(let [[instance-shape instance-shapes]
|
(let [[instance-shape instance-shapes]
|
||||||
(ctn/make-component-instance (ctpl/get-page file-data page-id)
|
(ctn/make-component-instance (ctpl/get-page file-data page-id)
|
||||||
(ctkl/get-component (:data library) component-id)
|
(ctkl/get-component (:data library) component-id)
|
||||||
(:id library)
|
(:data library)
|
||||||
(gpt/point 0 0))]
|
(gpt/point 0 0)
|
||||||
|
true)]
|
||||||
|
|
||||||
(swap! idmap assoc label (:id instance-shape))
|
(swap! idmap assoc label (:id instance-shape))
|
||||||
(-> file-data
|
(-> file-data
|
||||||
|
|
|
@ -233,6 +233,19 @@
|
||||||
(->> (filter (comp t/pointer? val) data)
|
(->> (filter (comp t/pointer? val) data)
|
||||||
(resolve-pointers id)
|
(resolve-pointers id)
|
||||||
(rx/map #(update file :data merge %)))))
|
(rx/map #(update file :data merge %)))))
|
||||||
|
(rx/mapcat
|
||||||
|
(fn [{:keys [id data] :as file}]
|
||||||
|
;; Resolve all pages of each library, if needed
|
||||||
|
(->> (rx/from (seq (:pages-index data)))
|
||||||
|
(rx/merge-map
|
||||||
|
(fn [[_ page :as kp]]
|
||||||
|
(if (t/pointer? page)
|
||||||
|
(resolve-pointer id kp)
|
||||||
|
(rx/of kp))))
|
||||||
|
(rx/reduce conj {})
|
||||||
|
(rx/map
|
||||||
|
(fn [pages-index]
|
||||||
|
(assoc-in file [:data :pages-index] pages-index))))))
|
||||||
(rx/reduce conj [])
|
(rx/reduce conj [])
|
||||||
(rx/map libraries-fetched))))))))
|
(rx/map libraries-fetched))))))))
|
||||||
|
|
||||||
|
@ -808,8 +821,8 @@
|
||||||
(not (:component-root? shape)))
|
(not (:component-root? shape)))
|
||||||
|
|
||||||
parent (get objects parent-id)
|
parent (get objects parent-id)
|
||||||
component-shape (cph/get-component-shape objects shape)
|
component-shape (ctn/get-component-shape objects shape)
|
||||||
component-shape-parent (cph/get-component-shape objects parent)
|
component-shape-parent (ctn/get-component-shape objects parent)
|
||||||
|
|
||||||
detach? (and instance-part? (not= (:id component-shape)
|
detach? (and instance-part? (not= (:id component-shape)
|
||||||
(:id component-shape-parent)))
|
(:id component-shape-parent)))
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
[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.color :as ctc]
|
[app.common.types.color :as ctc]
|
||||||
|
[app.common.types.component :as ctk]
|
||||||
[app.common.types.components-list :as ctkl]
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.common.types.container :as ctn]
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.file :as ctf]
|
[app.common.types.file :as ctf]
|
||||||
|
@ -346,8 +347,9 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(when (and (some? new-name) (not= "" new-name))
|
(when (and (some? new-name) (not= "" new-name))
|
||||||
(let [data (get state :workspace-data)
|
(let [data (get state :workspace-data)
|
||||||
[path name] (cph/parse-path-name new-name)
|
[path name] (cph/parse-path-name new-name)
|
||||||
|
components-v2 (features/active-feature? state :components-v2)
|
||||||
|
|
||||||
update-fn
|
update-fn
|
||||||
(fn [component]
|
(fn [component]
|
||||||
|
@ -355,12 +357,15 @@
|
||||||
;; because there are small possibilities of race
|
;; because there are small possibilities of race
|
||||||
;; conditions with component deletion.
|
;; conditions with component deletion.
|
||||||
(when component
|
(when component
|
||||||
(-> component
|
(cond-> component
|
||||||
(assoc :path path)
|
:always
|
||||||
(assoc :name name)
|
(assoc :path path
|
||||||
(update :objects
|
:name name)
|
||||||
|
|
||||||
|
(not components-v2)
|
||||||
|
(update :objects
|
||||||
;; Give the same name to the root shape
|
;; Give the same name to the root shape
|
||||||
#(assoc-in % [id :name] name)))))
|
#(assoc-in % [id :name] name)))))
|
||||||
|
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
(pcb/with-library-data data)
|
(pcb/with-library-data data)
|
||||||
|
@ -370,30 +375,33 @@
|
||||||
|
|
||||||
(defn duplicate-component
|
(defn duplicate-component
|
||||||
"Create a new component copied from the one with the given id."
|
"Create a new component copied from the one with the given id."
|
||||||
[{:keys [id] :as params}]
|
[library-id component-id]
|
||||||
(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)
|
||||||
component (cph/get-component libraries id)
|
library (get libraries library-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
|
||||||
(wsh/lookup-page state (:main-instance-page component)))
|
(ctf/get-component-page (:data library) component))
|
||||||
main-instance-shape (when components-v2
|
|
||||||
(ctn/get-shape main-instance-page (:main-instance-id component)))
|
|
||||||
|
|
||||||
[new-component-shape new-component-shapes
|
new-component (assoc component :id (uuid/next))
|
||||||
|
|
||||||
|
[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 component main-instance-page main-instance-shape)
|
(dwlh/duplicate-component new-component (: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 (:id new-component-shape)
|
(pcb/add-component (if components-v2
|
||||||
|
(:id new-component)
|
||||||
|
(:id new-component-shape))
|
||||||
(:path component)
|
(:path component)
|
||||||
new-name
|
new-name
|
||||||
new-component-shapes
|
new-component-shapes
|
||||||
|
@ -429,17 +437,22 @@
|
||||||
(ptk/reify ::restore-component
|
(ptk/reify ::restore-component
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
|
(assert "Restore component not implemented") ; until we allow a :deleted flag in shapes
|
||||||
(let [file-data (wsh/get-file state library-id)
|
(let [file-data (wsh/get-file state library-id)
|
||||||
component (ctf/get-deleted-component file-data component-id)
|
component (ctf/get-deleted-component file-data component-id)
|
||||||
page (ctpl/get-page file-data (:main-instance-page component))
|
page (ctpl/get-page file-data (:main-instance-page component))
|
||||||
|
|
||||||
; Make a new main instance, with the same id of the original
|
components-v2
|
||||||
|
(features/active-feature? state :components-v2)
|
||||||
|
|
||||||
|
; Make a new main instance, with the same id of the original
|
||||||
[_main-instance shapes]
|
[_main-instance shapes]
|
||||||
(ctn/make-component-instance page
|
(ctn/make-component-instance page
|
||||||
component
|
component
|
||||||
(:id file-data)
|
file-data
|
||||||
(gpt/point (:main-instance-x component)
|
(gpt/point (:main-instance-x component)
|
||||||
(:main-instance-y component))
|
(:main-instance-y component))
|
||||||
|
components-v2
|
||||||
{:main-instance? true
|
{:main-instance? true
|
||||||
:force-id (:main-instance-id component)})
|
:force-id (:main-instance-id component)})
|
||||||
|
|
||||||
|
@ -600,53 +613,53 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(log/info :msg "UPDATE-COMPONENT of shape" :id (str id))
|
(log/info :msg "UPDATE-COMPONENT of shape" :id (str id))
|
||||||
(let [page-id (get state :current-page-id)
|
(let [page-id (get state :current-page-id)
|
||||||
|
local-file (wsh/get-local-file state)
|
||||||
|
container (cph/get-container local-file :page page-id)
|
||||||
|
shape (ctn/get-shape container id)]
|
||||||
|
|
||||||
local-file (wsh/get-local-file state)
|
(when (ctk/in-component-instance? shape)
|
||||||
libraries (wsh/get-libraries state)
|
(let [libraries (wsh/get-libraries state)
|
||||||
|
|
||||||
container (cph/get-container local-file :page page-id)
|
changes
|
||||||
shape (ctn/get-shape container id)
|
(-> (pcb/empty-changes it)
|
||||||
|
(pcb/with-container container)
|
||||||
|
(dwlh/generate-sync-shape-inverse libraries container id))
|
||||||
|
|
||||||
changes
|
file-id (:component-file shape)
|
||||||
(-> (pcb/empty-changes it)
|
file (wsh/get-file state file-id)
|
||||||
(pcb/with-container container)
|
|
||||||
(dwlh/generate-sync-shape-inverse libraries container id))
|
|
||||||
|
|
||||||
file-id (:component-file shape)
|
xf-filter (comp
|
||||||
file (wsh/get-file state file-id)
|
(filter :local-change?)
|
||||||
|
(map #(dissoc % :local-change?)))
|
||||||
|
|
||||||
xf-filter (comp
|
local-changes (-> changes
|
||||||
(filter :local-change?)
|
(update :redo-changes #(into [] xf-filter %))
|
||||||
(map #(dissoc % :local-change?)))
|
(update :undo-changes #(into [] xf-filter %)))
|
||||||
|
|
||||||
local-changes (-> changes
|
xf-remove (comp
|
||||||
(update :redo-changes #(into [] xf-filter %))
|
(remove :local-change?)
|
||||||
(update :undo-changes #(into [] xf-filter %)))
|
(map #(dissoc % :local-change?)))
|
||||||
|
|
||||||
xf-remove (comp
|
nonlocal-changes (-> changes
|
||||||
(remove :local-change?)
|
(update :redo-changes #(into [] xf-remove %))
|
||||||
(map #(dissoc % :local-change?)))
|
(update :undo-changes #(into [] xf-remove %)))]
|
||||||
|
|
||||||
nonlocal-changes (-> changes
|
(log/debug :msg "UPDATE-COMPONENT finished"
|
||||||
(update :redo-changes #(into [] xf-remove %))
|
:js/local-changes (log-changes
|
||||||
(update :undo-changes #(into [] xf-remove %)))]
|
(:redo-changes local-changes)
|
||||||
|
file)
|
||||||
|
:js/nonlocal-changes (log-changes
|
||||||
|
(:redo-changes nonlocal-changes)
|
||||||
|
file))
|
||||||
|
|
||||||
(log/debug :msg "UPDATE-COMPONENT finished"
|
(rx/of
|
||||||
:js/local-changes (log-changes
|
(when (seq (:redo-changes local-changes))
|
||||||
(:redo-changes local-changes)
|
(dch/commit-changes (assoc local-changes
|
||||||
file)
|
:file-id (:id local-file))))
|
||||||
:js/nonlocal-changes (log-changes
|
(when (seq (:redo-changes nonlocal-changes))
|
||||||
(:redo-changes nonlocal-changes)
|
(dch/commit-changes (assoc nonlocal-changes
|
||||||
file))
|
:file-id file-id))))))))))
|
||||||
|
|
||||||
(rx/of
|
|
||||||
(when (seq (:redo-changes local-changes))
|
|
||||||
(dch/commit-changes (assoc local-changes
|
|
||||||
:file-id (:id local-file))))
|
|
||||||
(when (seq (:redo-changes nonlocal-changes))
|
|
||||||
(dch/commit-changes (assoc nonlocal-changes
|
|
||||||
:file-id file-id))))))))
|
|
||||||
|
|
||||||
(defn update-component-sync
|
(defn update-component-sync
|
||||||
[shape-id file-id]
|
[shape-id file-id]
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(ns app.main.data.workspace.libraries-helpers
|
(ns app.main.data.workspace.libraries-helpers
|
||||||
(: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.logging :as log]
|
[app.common.logging :as log]
|
||||||
|
@ -17,10 +18,12 @@
|
||||||
[app.common.text :as txt]
|
[app.common.text :as txt]
|
||||||
[app.common.types.color :as ctc]
|
[app.common.types.color :as ctc]
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.common.types.container :as ctn]
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.file :as ctf]
|
[app.common.types.file :as ctf]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
[app.common.types.typography :as cty]
|
[app.common.types.typography :as cty]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace.groups :as dwg]
|
[app.main.data.workspace.groups :as dwg]
|
||||||
[app.main.data.workspace.state-helpers :as wsh]
|
[app.main.data.workspace.state-helpers :as wsh]
|
||||||
[cljs.spec.alpha :as s]
|
[cljs.spec.alpha :as s]
|
||||||
|
@ -84,54 +87,75 @@
|
||||||
name (:name group)
|
name (:name group)
|
||||||
[path name] (cph/parse-path-name name)
|
[path name] (cph/parse-path-name name)
|
||||||
|
|
||||||
[new-shape new-shapes updated-shapes]
|
[root-shape new-shapes updated-shapes]
|
||||||
(ctn/make-component-shape group objects file-id components-v2)
|
(if-not components-v2
|
||||||
|
(ctn/make-component-shape group objects file-id components-v2)
|
||||||
|
(let [new-id (uuid/next)]
|
||||||
|
[(assoc group :id new-id)
|
||||||
|
nil
|
||||||
|
[(assoc group
|
||||||
|
:component-id new-id
|
||||||
|
:component-file file-id
|
||||||
|
:component-root? true
|
||||||
|
:main-instance? true)]]))
|
||||||
|
|
||||||
changes (-> changes
|
changes (-> changes
|
||||||
(pcb/add-component (:id new-shape)
|
(pcb/add-component (:id root-shape)
|
||||||
path
|
path
|
||||||
name
|
name
|
||||||
new-shapes
|
new-shapes
|
||||||
updated-shapes
|
updated-shapes
|
||||||
(:id group)
|
(:id group)
|
||||||
page-id))]
|
page-id))]
|
||||||
[group new-shape changes]))
|
[group (:id root-shape) changes]))
|
||||||
|
|
||||||
(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 main-instance-page main-instance-shape]
|
[component library-data]
|
||||||
(let [position (gpt/add (gpt/point (:x main-instance-shape) (:y main-instance-shape))
|
(let [components-v2 (dm/get-in library-data [:options :components-v2])]
|
||||||
(gpt/point (+ (:width main-instance-shape) 50) 0))
|
(if components-v2
|
||||||
|
|
||||||
component-root (ctk/get-component-root component)
|
(let [main-instance-page (ctf/get-component-page library-data component)
|
||||||
|
main-instance-shape (ctf/get-component-root library-data component)
|
||||||
|
|
||||||
[new-component-shape new-component-shapes _]
|
position (gpt/add (gpt/point (:x main-instance-shape) (:y main-instance-shape))
|
||||||
(ctst/clone-object component-root
|
(gpt/point (+ (:width main-instance-shape) 50) 0))
|
||||||
nil
|
|
||||||
(get component :objects)
|
|
||||||
identity)
|
|
||||||
|
|
||||||
|
[new-instance-shape new-instance-shapes]
|
||||||
|
(when (and (some? main-instance-page) (some? main-instance-shape))
|
||||||
|
(ctn/make-component-instance main-instance-page
|
||||||
|
component
|
||||||
|
library-data
|
||||||
|
position
|
||||||
|
true))]
|
||||||
|
|
||||||
|
[nil nil new-instance-shape new-instance-shapes])
|
||||||
|
|
||||||
[new-instance-shape new-instance-shapes]
|
(let [component-root (d/seek #(nil? (:parent-id %)) (vals (:objects component)))
|
||||||
(when (and (some? main-instance-page) (some? main-instance-shape))
|
|
||||||
(ctn/make-component-instance main-instance-page
|
|
||||||
{:id (:id new-component-shape)
|
|
||||||
:name (:name new-component-shape)
|
|
||||||
:objects (d/index-by :id new-component-shapes)}
|
|
||||||
(:component-file main-instance-shape)
|
|
||||||
position))]
|
|
||||||
|
|
||||||
[new-component-shape new-component-shapes
|
[new-component-shape new-component-shapes _]
|
||||||
new-instance-shape new-instance-shapes]))
|
(ctst/clone-object component-root
|
||||||
|
nil
|
||||||
|
(get component :objects)
|
||||||
|
identity)]
|
||||||
|
|
||||||
|
[new-component-shape new-component-shapes nil nil]))))
|
||||||
|
|
||||||
(defn generate-instantiate-component
|
(defn generate-instantiate-component
|
||||||
"Generate changes to create a new instance from a component."
|
"Generate changes to create a new instance from a component."
|
||||||
[it file-id component-id position page libraries]
|
[it file-id component-id position page libraries]
|
||||||
(let [component (cph/get-component libraries file-id component-id)
|
(let [component (ctf/get-component libraries file-id component-id)
|
||||||
|
library (get libraries file-id)
|
||||||
|
|
||||||
|
components-v2 (dm/get-in library [:data :options :components-v2])
|
||||||
|
|
||||||
[new-shape new-shapes]
|
[new-shape new-shapes]
|
||||||
(ctn/make-component-instance page component file-id position)
|
(ctn/make-component-instance page
|
||||||
|
component
|
||||||
|
(:data library)
|
||||||
|
position
|
||||||
|
components-v2)
|
||||||
|
|
||||||
changes (reduce #(pcb/add-object %1 %2 {:ignore-touched true})
|
changes (reduce #(pcb/add-object %1 %2 {:ignore-touched true})
|
||||||
(pcb/empty-changes it (:id page))
|
(pcb/empty-changes it (:id page))
|
||||||
|
@ -447,47 +471,47 @@
|
||||||
;; but it's not touched.
|
;; but it's not touched.
|
||||||
|
|
||||||
(defn generate-sync-shape-direct
|
(defn generate-sync-shape-direct
|
||||||
"Generate changes to synchronize one shape that the root of a component
|
"Generate changes to synchronize one shape that is the root of a component
|
||||||
instance, and all its children, from the given component."
|
instance, and all its children, from the given component."
|
||||||
[changes libraries container shape-id reset? components-v2]
|
[changes libraries container shape-id reset? components-v2]
|
||||||
(log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?)
|
(log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?)
|
||||||
(let [shape-inst (ctn/get-shape container shape-id)
|
(let [shape-inst (ctn/get-shape container shape-id)]
|
||||||
component (cph/get-component libraries
|
(if (ctk/in-component-instance? shape-inst)
|
||||||
(:component-file shape-inst)
|
(let [library (dm/get-in libraries [(:component-file shape-inst) :data])
|
||||||
(:component-id shape-inst))
|
component (or (ctkl/get-component library (:component-id shape-inst))
|
||||||
component (or component
|
(and reset?
|
||||||
(and reset?
|
(ctf/get-deleted-component library (:component-id shape-inst))))
|
||||||
(ctf/get-deleted-component
|
|
||||||
(get-in libraries [(:component-file shape-inst) :data])
|
|
||||||
(:component-id shape-inst))))
|
|
||||||
shape-main (when component
|
|
||||||
(ctn/get-shape component (:shape-ref shape-inst)))
|
|
||||||
|
|
||||||
initial-root? (:component-root? shape-inst)
|
shape-main (when component
|
||||||
|
(ctf/get-ref-shape library component shape-inst))
|
||||||
|
|
||||||
root-inst shape-inst
|
initial-root? (:component-root? shape-inst)
|
||||||
root-main (when component
|
|
||||||
(ctk/get-component-root component))]
|
|
||||||
|
|
||||||
(if component
|
root-inst shape-inst
|
||||||
(generate-sync-shape-direct-recursive changes
|
root-main (when component
|
||||||
container
|
(ctf/get-component-root library component))]
|
||||||
shape-inst
|
|
||||||
component
|
(if component
|
||||||
shape-main
|
(generate-sync-shape-direct-recursive changes
|
||||||
root-inst
|
container
|
||||||
root-main
|
shape-inst
|
||||||
reset?
|
component
|
||||||
initial-root?
|
library
|
||||||
components-v2)
|
shape-main
|
||||||
|
root-inst
|
||||||
|
root-main
|
||||||
|
reset?
|
||||||
|
initial-root?
|
||||||
|
components-v2)
|
||||||
; If the component is not found, because the master component has been
|
; If the component is not found, because the master component has been
|
||||||
; deleted or the library unlinked, do nothing in v2 or detach in v1.
|
; deleted or the library unlinked, do nothing in v2 or detach in v1.
|
||||||
(if components-v2
|
(if components-v2
|
||||||
changes
|
changes
|
||||||
(generate-detach-instance changes container shape-id)))))
|
(generate-detach-instance changes container shape-id))))
|
||||||
|
changes)))
|
||||||
|
|
||||||
(defn- generate-sync-shape-direct-recursive
|
(defn- generate-sync-shape-direct-recursive
|
||||||
[changes container shape-inst component shape-main root-inst root-main reset? initial-root? components-v2]
|
[changes container shape-inst component library shape-main root-inst root-main reset? initial-root? components-v2]
|
||||||
(log/debug :msg "Sync shape direct recursive"
|
(log/debug :msg "Sync shape direct recursive"
|
||||||
:shape (str (:name shape-inst))
|
:shape (str (:name shape-inst))
|
||||||
:component (:name component))
|
:component (:name component))
|
||||||
|
@ -522,20 +546,22 @@
|
||||||
set-remote-synced?
|
set-remote-synced?
|
||||||
(change-remote-synced shape-inst container true))
|
(change-remote-synced shape-inst container true))
|
||||||
|
|
||||||
children-inst (mapv #(ctn/get-shape container %)
|
component-container (ctf/get-component-container library component)
|
||||||
(:shapes shape-inst))
|
|
||||||
children-main (mapv #(ctn/get-shape component %)
|
children-inst (mapv #(ctn/get-shape container %)
|
||||||
(:shapes shape-main))
|
(:shapes shape-inst))
|
||||||
|
children-main (mapv #(ctn/get-shape component-container %)
|
||||||
|
(:shapes shape-main))
|
||||||
|
|
||||||
only-inst (fn [changes child-inst]
|
only-inst (fn [changes child-inst]
|
||||||
(if-not (and omit-touched?
|
(if-not (and omit-touched?
|
||||||
(contains? (:touched shape-inst)
|
(contains? (:touched shape-inst)
|
||||||
:shapes-group))
|
:shapes-group))
|
||||||
(remove-shape changes
|
(remove-shape changes
|
||||||
child-inst
|
child-inst
|
||||||
container
|
container
|
||||||
omit-touched?)
|
omit-touched?)
|
||||||
changes))
|
changes))
|
||||||
|
|
||||||
only-main (fn [changes child-main]
|
only-main (fn [changes child-main]
|
||||||
(if-not (and omit-touched?
|
(if-not (and omit-touched?
|
||||||
|
@ -545,7 +571,7 @@
|
||||||
child-main
|
child-main
|
||||||
(d/index-of children-main
|
(d/index-of children-main
|
||||||
child-main)
|
child-main)
|
||||||
component
|
component-container
|
||||||
container
|
container
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
|
@ -558,6 +584,7 @@
|
||||||
container
|
container
|
||||||
child-inst
|
child-inst
|
||||||
component
|
component
|
||||||
|
library
|
||||||
child-main
|
child-main
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
|
@ -567,12 +594,12 @@
|
||||||
|
|
||||||
moved (fn [changes child-inst child-main]
|
moved (fn [changes child-inst child-main]
|
||||||
(move-shape
|
(move-shape
|
||||||
changes
|
changes
|
||||||
child-inst
|
child-inst
|
||||||
(d/index-of children-inst child-inst)
|
(d/index-of children-inst child-inst)
|
||||||
(d/index-of children-main child-main)
|
(d/index-of children-main child-main)
|
||||||
container
|
container
|
||||||
omit-touched?))]
|
omit-touched?))]
|
||||||
|
|
||||||
(compare-children changes
|
(compare-children changes
|
||||||
children-inst
|
children-inst
|
||||||
|
@ -588,22 +615,22 @@
|
||||||
the values in the shape and all its children."
|
the values in the shape and all its children."
|
||||||
[changes libraries container shape-id]
|
[changes libraries container shape-id]
|
||||||
(log/debug :msg "Sync shape inverse" :shape (str shape-id))
|
(log/debug :msg "Sync shape inverse" :shape (str shape-id))
|
||||||
(let [shape-inst (ctn/get-shape container shape-id)
|
(let [shape-inst (ctn/get-shape container shape-id)
|
||||||
component (cph/get-component libraries
|
library (dm/get-in libraries [(:component-file shape-inst) :data])
|
||||||
(:component-file shape-inst)
|
component (ctkl/get-component library (:component-id shape-inst))
|
||||||
(:component-id shape-inst))
|
shape-main (ctf/get-ref-shape library component shape-inst)
|
||||||
shape-main (ctn/get-shape component (:shape-ref shape-inst))
|
|
||||||
|
|
||||||
initial-root? (:component-root? shape-inst)
|
initial-root? (:component-root? shape-inst)
|
||||||
|
|
||||||
root-inst shape-inst
|
root-inst shape-inst
|
||||||
root-main (ctk/get-component-root component)]
|
root-main (ctf/get-component-root library component)]
|
||||||
|
|
||||||
(if component
|
(if component
|
||||||
(generate-sync-shape-inverse-recursive changes
|
(generate-sync-shape-inverse-recursive changes
|
||||||
container
|
container
|
||||||
shape-inst
|
shape-inst
|
||||||
component
|
component
|
||||||
|
library
|
||||||
shape-main
|
shape-main
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
|
@ -611,7 +638,7 @@
|
||||||
changes)))
|
changes)))
|
||||||
|
|
||||||
(defn- generate-sync-shape-inverse-recursive
|
(defn- generate-sync-shape-inverse-recursive
|
||||||
[changes container shape-inst component shape-main root-inst root-main initial-root?]
|
[changes container shape-inst component library shape-main root-inst root-main initial-root?]
|
||||||
(log/trace :msg "Sync shape inverse recursive"
|
(log/trace :msg "Sync shape inverse recursive"
|
||||||
:shape (str (:name shape-inst))
|
:shape (str (:name shape-inst))
|
||||||
:component (:name component))
|
:component (:name component))
|
||||||
|
@ -619,7 +646,7 @@
|
||||||
(if (nil? shape-main)
|
(if (nil? shape-main)
|
||||||
;; This should not occur, but protect against it in any case
|
;; This should not occur, but protect against it in any case
|
||||||
changes
|
changes
|
||||||
(let [component-container (cph/make-container component :component)
|
(let [component-container (ctf/get-component-container library component)
|
||||||
|
|
||||||
omit-touched? false
|
omit-touched? false
|
||||||
set-remote-synced? (not initial-root?)
|
set-remote-synced? (not initial-root?)
|
||||||
|
@ -650,7 +677,7 @@
|
||||||
|
|
||||||
children-inst (mapv #(ctn/get-shape container %)
|
children-inst (mapv #(ctn/get-shape container %)
|
||||||
(:shapes shape-inst))
|
(:shapes shape-inst))
|
||||||
children-main (mapv #(ctn/get-shape component %)
|
children-main (mapv #(ctn/get-shape component-container %)
|
||||||
(:shapes shape-main))
|
(:shapes shape-main))
|
||||||
|
|
||||||
only-inst (fn [changes child-inst]
|
only-inst (fn [changes child-inst]
|
||||||
|
@ -659,6 +686,7 @@
|
||||||
(d/index-of children-inst
|
(d/index-of children-inst
|
||||||
child-inst)
|
child-inst)
|
||||||
component
|
component
|
||||||
|
component-container
|
||||||
container
|
container
|
||||||
root-inst
|
root-inst
|
||||||
root-main))
|
root-main))
|
||||||
|
@ -674,6 +702,7 @@
|
||||||
container
|
container
|
||||||
child-inst
|
child-inst
|
||||||
component
|
component
|
||||||
|
library
|
||||||
child-main
|
child-main
|
||||||
root-inst
|
root-inst
|
||||||
root-main
|
root-main
|
||||||
|
@ -681,12 +710,12 @@
|
||||||
|
|
||||||
moved (fn [changes child-inst child-main]
|
moved (fn [changes child-inst child-main]
|
||||||
(move-shape
|
(move-shape
|
||||||
changes
|
changes
|
||||||
child-main
|
child-main
|
||||||
(d/index-of children-main child-main)
|
(d/index-of children-main child-main)
|
||||||
(d/index-of children-inst child-inst)
|
(d/index-of children-inst child-inst)
|
||||||
component-container
|
component-container
|
||||||
false))
|
false))
|
||||||
|
|
||||||
changes
|
changes
|
||||||
(compare-children changes
|
(compare-children changes
|
||||||
|
@ -763,9 +792,9 @@
|
||||||
(moved-cb child-inst' child-main)))))))))))
|
(moved-cb child-inst' child-main)))))))))))
|
||||||
|
|
||||||
(defn- add-shape-to-instance
|
(defn- add-shape-to-instance
|
||||||
[changes component-shape index component container root-instance root-main omit-touched? set-remote-synced?]
|
[changes component-shape index component-page container root-instance root-main omit-touched? set-remote-synced?]
|
||||||
(log/info :msg (str "ADD [P] " (:name component-shape)))
|
(log/info :msg (str "ADD [P] " (:name component-shape)))
|
||||||
(let [component-parent-shape (ctn/get-shape component (:parent-id component-shape))
|
(let [component-parent-shape (ctn/get-shape component-page (:parent-id component-shape))
|
||||||
parent-shape (d/seek #(ctk/is-main-of? component-parent-shape %)
|
parent-shape (d/seek #(ctk/is-main-of? component-parent-shape %)
|
||||||
(cph/get-children-with-self (:objects container)
|
(cph/get-children-with-self (:objects container)
|
||||||
(:id root-instance)))
|
(:id root-instance)))
|
||||||
|
@ -793,7 +822,7 @@
|
||||||
[_ new-shapes _]
|
[_ new-shapes _]
|
||||||
(ctst/clone-object component-shape
|
(ctst/clone-object component-shape
|
||||||
(:id parent-shape)
|
(:id parent-shape)
|
||||||
(get component :objects)
|
(get component-page :objects)
|
||||||
update-new-shape
|
update-new-shape
|
||||||
update-original-shape)
|
update-original-shape)
|
||||||
|
|
||||||
|
@ -831,14 +860,14 @@
|
||||||
changes')))
|
changes')))
|
||||||
|
|
||||||
(defn- add-shape-to-main
|
(defn- add-shape-to-main
|
||||||
[changes shape index component page root-instance root-main]
|
[changes shape index component component-container page root-instance root-main]
|
||||||
(log/info :msg (str "ADD [C] " (:name shape)))
|
(log/info :msg (str "ADD [C] " (:name shape)))
|
||||||
(let [parent-shape (ctn/get-shape page (:parent-id shape))
|
(let [parent-shape (ctn/get-shape page (:parent-id shape))
|
||||||
component-parent-shape (d/seek #(ctk/is-main-of? % parent-shape)
|
component-parent-shape (d/seek #(ctk/is-main-of? % parent-shape)
|
||||||
(cph/get-children-with-self (:objects component)
|
(cph/get-children-with-self (:objects component-container)
|
||||||
(:id root-main)))
|
(:id root-main)))
|
||||||
all-parents (into [(:id component-parent-shape)]
|
all-parents (into [(:id component-parent-shape)]
|
||||||
(cph/get-parent-ids (:objects component)
|
(cph/get-parent-ids (:objects component-container)
|
||||||
(:id component-parent-shape)))
|
(:id component-parent-shape)))
|
||||||
|
|
||||||
update-new-shape (fn [new-shape _original-shape]
|
update-new-shape (fn [new-shape _original-shape]
|
||||||
|
@ -854,20 +883,24 @@
|
||||||
|
|
||||||
[_new-shape new-shapes updated-shapes]
|
[_new-shape new-shapes updated-shapes]
|
||||||
(ctst/clone-object shape
|
(ctst/clone-object shape
|
||||||
(:id component-parent-shape)
|
(:id component-parent-shape)
|
||||||
(get page :objects)
|
(get page :objects)
|
||||||
update-new-shape
|
update-new-shape
|
||||||
update-original-shape)
|
update-original-shape)
|
||||||
|
|
||||||
add-obj-change (fn [changes shape']
|
add-obj-change (fn [changes shape']
|
||||||
(update changes :redo-changes conj
|
(update changes :redo-changes conj
|
||||||
{:type :add-obj
|
(cond-> (make-change
|
||||||
:id (:id shape')
|
component-container
|
||||||
:component-id (:id component)
|
{:type :add-obj
|
||||||
:parent-id (:parent-id shape')
|
:id (:id shape')
|
||||||
:index index
|
:parent-id (:parent-id shape')
|
||||||
:ignore-touched true
|
:index index
|
||||||
:obj shape'}))
|
:ignore-touched true
|
||||||
|
:obj shape'})
|
||||||
|
|
||||||
|
(ctn/page? component-container)
|
||||||
|
(assoc :frame-id (:frame-id shape')))))
|
||||||
|
|
||||||
mod-obj-change (fn [changes shape']
|
mod-obj-change (fn [changes shape']
|
||||||
(update changes :redo-changes conj
|
(update changes :redo-changes conj
|
||||||
|
@ -899,8 +932,8 @@
|
||||||
|
|
||||||
changes' (reduce add-obj-change changes new-shapes)
|
changes' (reduce add-obj-change changes new-shapes)
|
||||||
changes' (update changes' :redo-changes conj {:type :reg-objects
|
changes' (update changes' :redo-changes conj {:type :reg-objects
|
||||||
:component-id (:id component)
|
:component-id (:id component)
|
||||||
:shapes all-parents})
|
:shapes all-parents})
|
||||||
changes' (reduce mod-obj-change changes' updated-shapes)
|
changes' (reduce mod-obj-change changes' updated-shapes)
|
||||||
changes' (reduce del-obj-change changes' new-shapes)]
|
changes' (reduce del-obj-change changes' new-shapes)]
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
[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.component :as ctk]
|
||||||
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
[app.common.types.shape :as cts]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
|
@ -171,7 +172,7 @@
|
||||||
;; not the root. In this case, they must not be deleted,
|
;; not the root. In this case, they must not be deleted,
|
||||||
;; but hidden (to be able to recover them more easily).
|
;; but hidden (to be able to recover them more easily).
|
||||||
(let [shape (get objects shape-id)
|
(let [shape (get objects shape-id)
|
||||||
component-shape (cph/get-component-shape objects shape)]
|
component-shape (ctn/get-component-shape objects shape)]
|
||||||
(and (ctk/in-component-instance? shape)
|
(and (ctk/in-component-instance? shape)
|
||||||
(not= shape component-shape)
|
(not= shape component-shape)
|
||||||
(not (ctk/main-instance? component-shape)))))
|
(not (ctk/main-instance? component-shape)))))
|
||||||
|
|
|
@ -208,7 +208,10 @@
|
||||||
data (:workspace-data state)]
|
data (:workspace-data state)]
|
||||||
(-> file
|
(-> file
|
||||||
(dissoc :data)
|
(dissoc :data)
|
||||||
(assoc :pages (:pages data)))))
|
(assoc :options (:options data)
|
||||||
|
:components (:components data)
|
||||||
|
:pages (:pages data)
|
||||||
|
:pages-index (:pages-index data)))))
|
||||||
st/state =))
|
st/state =))
|
||||||
|
|
||||||
(def workspace-data
|
(def workspace-data
|
||||||
|
|
|
@ -310,16 +310,16 @@
|
||||||
update-fn #(update %1 %2 gsh/transform-shape (ctm/move-modifiers vector))]
|
update-fn #(update %1 %2 gsh/transform-shape (ctm/move-modifiers vector))]
|
||||||
(reduce update-fn objects children-ids))))
|
(reduce update-fn objects children-ids))))
|
||||||
|
|
||||||
root-shape (get objects root-shape-id)
|
root-shape' (get objects root-shape-id)
|
||||||
width (* (:width root-shape) zoom)
|
width (* (:width root-shape') zoom)
|
||||||
height (* (:height root-shape) zoom)
|
height (* (:height root-shape') zoom)
|
||||||
vbox (format-viewbox {:width (:width root-shape 0)
|
vbox (format-viewbox {:width (:width root-shape' 0)
|
||||||
:height (:height root-shape 0)})
|
:height (:height root-shape' 0)})
|
||||||
root-shape-wrapper
|
root-shape-wrapper
|
||||||
(mf/use-memo
|
(mf/use-memo
|
||||||
(mf/deps objects root-shape)
|
(mf/deps objects root-shape')
|
||||||
(fn []
|
(fn []
|
||||||
(case (:type root-shape)
|
(case (:type root-shape')
|
||||||
:group (group-wrapper-factory objects)
|
:group (group-wrapper-factory objects)
|
||||||
:frame (frame-wrapper-factory objects))))]
|
:frame (frame-wrapper-factory objects))))]
|
||||||
|
|
||||||
|
@ -332,9 +332,9 @@
|
||||||
:xmlns:penpot (when include-metadata? "https://penpot.app/xmlns")
|
:xmlns:penpot (when include-metadata? "https://penpot.app/xmlns")
|
||||||
:fill "none"}
|
:fill "none"}
|
||||||
|
|
||||||
[:> shape-container {:shape root-shape}
|
[:> shape-container {:shape root-shape'}
|
||||||
[:& (mf/provider muc/is-component?) {:value true}
|
[:& (mf/provider muc/is-component?) {:value true}
|
||||||
[:& root-shape-wrapper {:shape root-shape :view-box vbox}]]]]))
|
[:& root-shape-wrapper {:shape root-shape' :view-box vbox}]]]]))
|
||||||
|
|
||||||
(mf/defc object-svg
|
(mf/defc object-svg
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
|
|
|
@ -243,7 +243,9 @@
|
||||||
(events/unlistenByKey key1))))
|
(events/unlistenByKey key1))))
|
||||||
|
|
||||||
(mf/use-effect on-resize)
|
(mf/use-effect on-resize)
|
||||||
[:div.dashboard-content {:on-click #(st/emit! (dd/clear-selected-files)) :ref container}
|
|
||||||
|
[:div.dashboard-content {:on-click #(st/emit! (dd/clear-selected-files))
|
||||||
|
:ref container}
|
||||||
(case section
|
(case section
|
||||||
:dashboard-projects
|
:dashboard-projects
|
||||||
[:*
|
[:*
|
||||||
|
|
|
@ -105,12 +105,13 @@
|
||||||
[:span.num-assets (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
|
[:span.num-assets (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
|
||||||
[:div.asset-list
|
[:div.asset-list
|
||||||
(for [component (:sample components)]
|
(for [component (:sample components)]
|
||||||
[:div.asset-list-item {:key (str "assets-component-" (:id component))}
|
(let [root-id (or (:main-instance-id component) (:id component))] ;; Check for components-v2 in library
|
||||||
[:& component-svg {:group (get-in component [:objects (:id component)])
|
[:div.asset-list-item {:key (str "assets-component-" (:id component))}
|
||||||
:objects (:objects component)}]
|
[:& component-svg {:root-shape (get-in component [:objects root-id])
|
||||||
[:div.name-block
|
:objects (:objects component)}] ;; Components in the summary come loaded with objects, even in v2
|
||||||
[:span.item-name {:title (:name component)}
|
[:div.name-block
|
||||||
(:name component)]]])
|
[:span.item-name {:title (:name component)}
|
||||||
|
(:name component)]]]))
|
||||||
(when (> (:count components) (count (:sample components)))
|
(when (> (:count components) (count (:sample components)))
|
||||||
[:div.asset-list-item
|
[:div.asset-list-item
|
||||||
[:div.name-block
|
[:div.name-block
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.text :as txt]
|
[app.common.text :as txt]
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.file :as ctf]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
[app.main.data.events :as ev]
|
[app.main.data.events :as ev]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
|
@ -365,13 +365,17 @@
|
||||||
;;---- Components box ----
|
;;---- Components box ----
|
||||||
|
|
||||||
(mf/defc components-item
|
(mf/defc components-item
|
||||||
[{:keys [component renaming listing-thumbs? selected-components
|
[{:keys [component renaming listing-thumbs? selected-components file
|
||||||
on-asset-click on-context-menu on-drag-start do-rename cancel-rename
|
on-asset-click on-context-menu on-drag-start do-rename cancel-rename
|
||||||
selected-components-full selected-components-paths]}]
|
selected-components-full selected-components-paths]}]
|
||||||
(let [item-ref (mf/use-ref)
|
(let [item-ref (mf/use-ref)
|
||||||
dragging? (mf/use-state false)
|
dragging? (mf/use-state false)
|
||||||
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
|
workspace-read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
|
|
||||||
|
components-v2 (mf/use-ctx ctx/components-v2)
|
||||||
|
|
||||||
|
file (or (:data file) file)
|
||||||
|
|
||||||
unselect-all
|
unselect-all
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -440,15 +444,17 @@
|
||||||
:on-drag-over on-drag-over
|
:on-drag-over on-drag-over
|
||||||
:on-drop on-drop}
|
:on-drop on-drop}
|
||||||
|
|
||||||
[:& component-svg {:root-shape (ctk/get-component-root component)
|
[:& component-svg {:root-shape (ctf/get-component-root file component)
|
||||||
:objects (:objects component)}]
|
:objects (:objects (if components-v2
|
||||||
|
(ctf/get-component-page file component)
|
||||||
|
component))}]
|
||||||
(let [renaming? (= renaming (:id component))]
|
(let [renaming? (= renaming (:id component))]
|
||||||
[:*
|
[:*
|
||||||
[:& editable-label
|
[:& editable-label
|
||||||
{:class-name (dom/classnames
|
{:class-name (dom/classnames
|
||||||
:cell-name listing-thumbs?
|
:cell-name listing-thumbs?
|
||||||
:item-name (not listing-thumbs?)
|
:item-name (not listing-thumbs?)
|
||||||
:editing renaming?)
|
:editing renaming?)
|
||||||
:value (cph/merge-path-item (:path component) (:name component))
|
:value (cph/merge-path-item (:path component) (:name component))
|
||||||
:tooltip (cph/merge-path-item (:path component) (:name component))
|
:tooltip (cph/merge-path-item (:path component) (:name component))
|
||||||
:display-value (:name component)
|
:display-value (:name component)
|
||||||
|
@ -460,7 +466,7 @@
|
||||||
[:div.dragging])])]))
|
[:div.dragging])])]))
|
||||||
|
|
||||||
(mf/defc components-group
|
(mf/defc components-group
|
||||||
[{:keys [file-id prefix groups open-groups renaming listing-thumbs? selected-components on-asset-click
|
[{:keys [file prefix groups open-groups renaming listing-thumbs? selected-components on-asset-click
|
||||||
on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu
|
on-drag-start do-rename cancel-rename on-rename-group on-group on-ungroup on-context-menu
|
||||||
selected-components-full]}]
|
selected-components-full]}]
|
||||||
(let [group-open? (get open-groups prefix true)
|
(let [group-open? (get open-groups prefix true)
|
||||||
|
@ -495,7 +501,7 @@
|
||||||
:on-drag-leave on-drag-leave
|
:on-drag-leave on-drag-leave
|
||||||
:on-drag-over on-drag-over
|
:on-drag-over on-drag-over
|
||||||
:on-drop on-drop}
|
:on-drop on-drop}
|
||||||
[:& asset-group-title {:file-id file-id
|
[:& asset-group-title {:file-id (:id file)
|
||||||
:box :components
|
:box :components
|
||||||
:path prefix
|
:path prefix
|
||||||
:group-open? group-open?
|
:group-open? group-open?
|
||||||
|
@ -528,6 +534,7 @@
|
||||||
:key (:id component)
|
:key (:id component)
|
||||||
:renaming renaming
|
:renaming renaming
|
||||||
:listing-thumbs? listing-thumbs?
|
:listing-thumbs? listing-thumbs?
|
||||||
|
:file file
|
||||||
:selected-components selected-components
|
:selected-components selected-components
|
||||||
:on-asset-click on-asset-click
|
:on-asset-click on-asset-click
|
||||||
:on-context-menu on-context-menu
|
:on-context-menu on-context-menu
|
||||||
|
@ -539,7 +546,7 @@
|
||||||
:selected-components-paths selected-components-paths}])])
|
:selected-components-paths selected-components-paths}])])
|
||||||
(for [[path-item content] groups]
|
(for [[path-item content] groups]
|
||||||
(when-not (empty? path-item)
|
(when-not (empty? path-item)
|
||||||
[:& components-group {:file-id file-id
|
[:& components-group {:file file
|
||||||
:prefix (cph/merge-path-item prefix path-item)
|
:prefix (cph/merge-path-item prefix path-item)
|
||||||
:groups content
|
:groups content
|
||||||
:open-groups open-groups
|
:open-groups open-groups
|
||||||
|
@ -556,7 +563,7 @@
|
||||||
:selected-components-full selected-components-full}]))])]))
|
:selected-components-full selected-components-full}]))])]))
|
||||||
|
|
||||||
(mf/defc components-box
|
(mf/defc components-box
|
||||||
[{:keys [file-id local? components listing-thumbs? open? reverse-sort? open-groups selected-assets
|
[{:keys [file local? components listing-thumbs? open? reverse-sort? open-groups selected-assets
|
||||||
on-asset-click on-assets-delete on-clear-selection] :as props}]
|
on-asset-click on-assets-delete on-clear-selection] :as props}]
|
||||||
(let [input-ref (mf/use-ref nil)
|
(let [input-ref (mf/use-ref nil)
|
||||||
state (mf/use-state {:renaming nil
|
state (mf/use-state {:renaming nil
|
||||||
|
@ -579,14 +586,14 @@
|
||||||
add-component
|
add-component
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
#(st/emit! (dwl/set-assets-box-open file-id :components true))
|
#(st/emit! (dwl/set-assets-box-open (:id file) :components true))
|
||||||
(dom/click (mf/ref-val input-ref))))
|
(dom/click (mf/ref-val input-ref))))
|
||||||
|
|
||||||
on-file-selected
|
on-file-selected
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file-id)
|
(mf/deps file)
|
||||||
(fn [blobs]
|
(fn [blobs]
|
||||||
(let [params {:file-id file-id
|
(let [params {:file-id (:id file)
|
||||||
:blobs (seq blobs)}]
|
:blobs (seq blobs)}]
|
||||||
(st/emit! (dwm/upload-media-components params)
|
(st/emit! (dwm/upload-media-components params)
|
||||||
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
||||||
|
@ -598,22 +605,22 @@
|
||||||
(fn []
|
(fn []
|
||||||
(let [undo-id (js/Symbol)]
|
(let [undo-id (js/Symbol)]
|
||||||
(if (empty? selected-components)
|
(if (empty? selected-components)
|
||||||
(st/emit! (dwl/duplicate-component {:id (:component-id @state)}))
|
(st/emit! (dwl/duplicate-component (:id file) (:component-id @state)))
|
||||||
(do
|
(do
|
||||||
(st/emit! (dwu/start-undo-transaction undo-id))
|
(st/emit! (dwu/start-undo-transaction undo-id))
|
||||||
(apply st/emit! (map #(dwl/duplicate-component {:id %}) selected-components))
|
(apply st/emit! (map (partial dwl/duplicate-component (:id file)) selected-components))
|
||||||
(st/emit! (dwu/commit-undo-transaction undo-id)))))))
|
(st/emit! (dwu/commit-undo-transaction undo-id)))))))
|
||||||
|
|
||||||
on-delete
|
on-delete
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps @state file-id multi-components? multi-assets?)
|
(mf/deps @state file multi-components? multi-assets?)
|
||||||
(fn []
|
(fn []
|
||||||
(let [undo-id (js/Symbol)]
|
(let [undo-id (js/Symbol)]
|
||||||
(if (or multi-components? multi-assets?)
|
(if (or multi-components? multi-assets?)
|
||||||
(on-assets-delete)
|
(on-assets-delete)
|
||||||
(st/emit! (dwu/start-undo-transaction undo-id)
|
(st/emit! (dwu/start-undo-transaction undo-id)
|
||||||
(dwl/delete-component {:id (:component-id @state)})
|
(dwl/delete-component {:id (:component-id @state)})
|
||||||
(dwl/sync-file file-id file-id :components (:component-id @state))
|
(dwl/sync-file (:id file) (:id file) :components (:component-id @state))
|
||||||
(dwu/commit-undo-transaction undo-id))))))
|
(dwu/commit-undo-transaction undo-id))))))
|
||||||
|
|
||||||
on-rename
|
on-rename
|
||||||
|
@ -716,7 +723,7 @@
|
||||||
on-drag-start
|
on-drag-start
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [component event]
|
(fn [component event]
|
||||||
(dnd/set-data! event "penpot/component" {:file-id file-id
|
(dnd/set-data! event "penpot/component" {:file-id (:id file)
|
||||||
:component component})
|
:component component})
|
||||||
(dnd/set-allowed-effect! event "move")))
|
(dnd/set-allowed-effect! event "move")))
|
||||||
|
|
||||||
|
@ -734,7 +741,7 @@
|
||||||
(when (and main-instance-id main-instance-page) ;; Only when :components-v2 is enabled
|
(when (and main-instance-id main-instance-page) ;; Only when :components-v2 is enabled
|
||||||
(st/emit! (dw/go-to-main-instance main-instance-page main-instance-id))))))]
|
(st/emit! (dw/go-to-main-instance main-instance-page main-instance-id))))))]
|
||||||
|
|
||||||
[:& asset-section {:file-id file-id
|
[:& asset-section {:file-id (:id file)
|
||||||
:title (tr "workspace.assets.components")
|
:title (tr "workspace.assets.components")
|
||||||
:box :components
|
:box :components
|
||||||
:assets-count (count components)
|
:assets-count (count components)
|
||||||
|
@ -750,7 +757,7 @@
|
||||||
:on-selected on-file-selected}]])])
|
:on-selected on-file-selected}]])])
|
||||||
|
|
||||||
[:& asset-section-block {:role :content}
|
[:& asset-section-block {:role :content}
|
||||||
[:& components-group {:file-id file-id
|
[:& components-group {:file file
|
||||||
:prefix ""
|
:prefix ""
|
||||||
:groups groups
|
:groups groups
|
||||||
:open-groups open-groups
|
:open-groups open-groups
|
||||||
|
@ -2158,7 +2165,7 @@
|
||||||
i/listing-thumbs)]]
|
i/listing-thumbs)]]
|
||||||
|
|
||||||
(when show-components?
|
(when show-components?
|
||||||
[:& components-box {:file-id (:id file)
|
[:& components-box {:file file
|
||||||
:local? local?
|
:local? local?
|
||||||
:components components
|
:components components
|
||||||
:listing-thumbs? listing-thumbs?
|
:listing-thumbs? listing-thumbs?
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue