Merge pull request #6214 from penpot/palba-cleanup-components-v2

♻️ Cleanup of componentsv2
 Add check to avoid open files with components v1
This commit is contained in:
Pablo Alba 2025-04-07 10:18:53 +02:00 committed by GitHub
commit af1d5b86e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
44 changed files with 346 additions and 1208 deletions

View file

@ -1462,8 +1462,6 @@
(:objects page) (:objects page)
(:id page) (:id page)
file-id file-id
true
nil
cfsh/prepare-create-artboard-from-selection)] cfsh/prepare-create-artboard-from-selection)]
(shape-cb shape) (shape-cb shape)

View file

@ -179,7 +179,7 @@
component-child (first component-children)] component-child (first component-children)]
(if (or (nil? child) (nil? component-child)) (if (or (nil? child) (nil? component-child))
container container
(let [container (if (and (not (ctk/is-main-of? component-child child true)) (let [container (if (and (not (ctk/is-main-of? component-child child))
(nil? (ctk/get-swap-slot child)) (nil? (ctk/get-swap-slot child))
(ctk/instance-head? child)) (ctk/instance-head? child))
(let [slot (guess-swap-slot component-child component-container)] (let [slot (guess-swap-slot component-child component-container)]

View file

@ -104,7 +104,6 @@
"Translate a flag to a feature name" "Translate a flag to a feature name"
[flag] [flag]
(case flag (case flag
:feature-components-v2 "components/v2"
:feature-styles-v2 "styles/v2" :feature-styles-v2 "styles/v2"
:feature-fdata-objects-map "fdata/objects-map" :feature-fdata-objects-map "fdata/objects-map"
:feature-fdata-pointer-map "fdata/pointer-map" :feature-fdata-pointer-map "fdata/pointer-map"
@ -241,7 +240,13 @@
:code :file-feature-mismatch :code :file-feature-mismatch
:feature (first not-supported) :feature (first not-supported)
:hint (str/ffmt "file features '%' not enabled" :hint (str/ffmt "file features '%' not enabled"
(str/join "," not-supported)))))) (str/join "," not-supported)))))
;; Components v1 is deprecated
(when-not (contains? file-features "components/v2")
(ex/raise :type :restriction
:code :file-in-components-v1
:hint "components v1 is deprecated")))
enabled-features)) enabled-features))

View file

@ -11,7 +11,6 @@
[app.common.exceptions :as ex] [app.common.exceptions :as ex]
[app.common.files.changes :as ch] [app.common.files.changes :as ch]
[app.common.geom.point :as gpt] [app.common.geom.point :as gpt]
[app.common.geom.rect :as grc]
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.common.pprint :as pp] [app.common.pprint :as pp]
[app.common.schema :as sm] [app.common.schema :as sm]
@ -38,20 +37,12 @@
fail-on-spec?] fail-on-spec?]
:or {add-container? false :or {add-container? false
fail-on-spec? false}}] fail-on-spec? false}}]
(let [components-v2 (dm/get-in file [:data :options :components-v2]) (let [change (cond-> change
component-id (:current-component-id file) add-container?
change (cond-> change
(and add-container? (some? component-id) (not components-v2))
(-> (assoc :component-id component-id)
(cond-> (some? (:current-frame-id file))
(assoc :frame-id (:current-frame-id file))))
(and add-container? (or (nil? component-id) components-v2))
(assoc :page-id (:current-page-id file) (assoc :page-id (:current-page-id file)
:frame-id (:current-frame-id file))) :frame-id (:current-frame-id file)))
valid? (or (and components-v2 valid? (or (and (nil? (:component-id change))
(nil? (:component-id change))
(nil? (:page-id change))) (nil? (:page-id change)))
(ch/valid-change? change))] (ch/valid-change? change))]
@ -66,11 +57,11 @@
(cond-> file (cond-> file
(and valid? (or (not add-container?) (some? (:component-id change)) (some? (:page-id change)))) (and valid? (or (not add-container?) (some? (:component-id change)) (some? (:page-id change))))
(-> (update :changes conjv change) ;; In components-v2 we do not add shapes (-> (update :changes conjv change)
(update :data ch/process-changes [change] false)) ;; inside a component (update :data ch/process-changes [change] false))
(not valid?) (not valid?)
(update :errors conjv change)))));) (update :errors conjv change)))))
(defn- lookup-objects (defn- lookup-objects
([file] ([file]
@ -185,12 +176,10 @@
(update :parent-stack conjv (:id obj))))) (update :parent-stack conjv (:id obj)))))
(defn close-artboard [file] (defn close-artboard [file]
(let [components-v2 (dm/get-in file [:data :options :components-v2]) (let [parent-id (-> file :parent-stack peek)
parent-id (-> file :parent-stack peek)
parent (lookup-shape file parent-id) parent (lookup-shape file parent-id)
current-frame-id (or (:frame-id parent) current-frame-id (or (:frame-id parent)
(when (or (nil? (:current-component-id file)) components-v2) root-id)]
root-id))]
(-> file (-> file
(assoc :current-frame-id current-frame-id) (assoc :current-frame-id current-frame-id)
(update :parent-stack pop)))) (update :parent-stack pop))))
@ -514,58 +503,29 @@
(defn start-component (defn start-component
([file data] ([file data]
(let [components-v2 (dm/get-in file [:data :options :components-v2]) (start-component file data :frame))
root-type (if components-v2 :frame :group)]
(start-component file data root-type)))
([file data root-type] ([file data root-type]
;; FIXME: data probably can be a shape instance, then we can use gsh/shape->rect (let [name (:name data)
(let [components-v2 (dm/get-in file [:data :options :components-v2])
selrect (or (grc/make-rect (:x data) (:y data) (:width data) (:height data))
grc/empty-rect)
name (:name data)
path (:path data) path (:path data)
main-instance-id (:main-instance-id data) main-instance-id (:main-instance-id data)
main-instance-page (:main-instance-page data) main-instance-page (:main-instance-page data)
;; In components v1 we must create the root shape and set it inside obj-id (or (:id data) (uuid/next))]
;; the :objects attribute of the component. When in components-v2,
;; this will be ignored as the root shape has already been created
;; in its page, by the normal page import.
attrs (-> data
(assoc :type root-type)
(assoc :x (:x selrect))
(assoc :y (:y selrect))
(assoc :width (:width selrect))
(assoc :height (:height selrect))
(assoc :selrect selrect)
(dissoc :path)
(dissoc :main-instance-id)
(dissoc :main-instance-page)
(dissoc :main-instance-x)
(dissoc :main-instance-y))
obj (-> (cts/setup-shape attrs)
(check-name file root-type)
;; Components need to have nil values for frame and parent
(assoc :frame-id nil)
(assoc :parent-id nil))]
(-> file (-> file
(commit-change (commit-change
(cond-> {:type :add-component {:type :add-component
:id (:id obj) :id obj-id
:name name :name name
:path path :path path
:main-instance-id main-instance-id :main-instance-id main-instance-id
:main-instance-page main-instance-page} :main-instance-page main-instance-page})
(not components-v2)
(assoc :shapes [obj])))
(assoc :last-id (:id obj)) (assoc :last-id obj-id)
(assoc :parent-stack [(:id obj)]) (assoc :parent-stack [obj-id])
(assoc :current-component-id (:id obj)) (assoc :current-component-id obj-id)
(assoc :current-frame-id (if (= (:type obj) :frame) (:id obj) uuid/zero)))))) (assoc :current-frame-id (if (= root-type :frame) obj-id uuid/zero))))))
(defn start-deleted-component (defn start-deleted-component
[file data] [file data]
@ -600,8 +560,7 @@
file file
(cond (cond
;; In components-v2 components haven't any shape inside them. component-data
(and component-data (:main-instance-id component-data))
(update file :data (update file :data
(fn [data] (fn [data]
(ctkl/update-component data component-id dissoc :objects))) (ctkl/update-component data component-id dissoc :objects)))
@ -677,17 +636,12 @@
page (ctpl/get-page (:data file) page-id) page (ctpl/get-page (:data file) page-id)
component (ctkl/get-component (:data file) component-id) component (ctkl/get-component (:data file) component-id)
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
:force-id main-instance-id})]
(as-> file $ (as-> file $
(reduce #(commit-change %1 (reduce #(commit-change %1

View file

@ -921,11 +921,11 @@
(apply-changes-local)))) (apply-changes-local))))
(defn add-component (defn add-component
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page] ([changes id path name updated-shapes main-instance-id main-instance-page]
(add-component changes id path name new-shapes updated-shapes main-instance-id main-instance-page nil nil nil)) (add-component changes id path name updated-shapes main-instance-id main-instance-page nil nil nil))
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page annotation] ([changes id path name updated-shapes main-instance-id main-instance-page annotation]
(add-component changes id path name new-shapes updated-shapes main-instance-id main-instance-page annotation nil nil)) (add-component changes id path name updated-shapes main-instance-id main-instance-page annotation nil nil))
([changes id path name new-shapes updated-shapes main-instance-id main-instance-page annotation variant-id variant-properties & {:keys [apply-changes-local-library?]}] ([changes id path name updated-shapes main-instance-id main-instance-page annotation variant-id variant-properties & {:keys [apply-changes-local-library?]}]
(assert-page-id! changes) (assert-page-id! changes)
(assert-objects! changes) (assert-objects! changes)
(let [page-id (::page-id (meta changes)) (let [page-id (::page-id (meta changes))
@ -965,8 +965,6 @@
:main-instance-id main-instance-id :main-instance-id main-instance-id
:main-instance-page main-instance-page :main-instance-page main-instance-page
:annotation annotation} :annotation annotation}
(some? new-shapes) ;; this will be null in components-v2
(assoc :shapes (vec new-shapes))
(some? variant-id) (some? variant-id)
(assoc :variant-id variant-id) (assoc :variant-id variant-id)
(seq variant-properties) (seq variant-properties)
@ -1000,7 +998,7 @@
:main-instance-id (:main-instance-id new-component) :main-instance-id (:main-instance-id new-component)
:main-instance-page (:main-instance-page new-component) :main-instance-page (:main-instance-page new-component)
:annotation (:annotation new-component) :annotation (:annotation new-component)
:objects (:objects new-component) ;; this won't exist in components-v2 (except for deleted components) :objects (:objects new-component) ;; for deleted components
:modified-at (:modified-at new-component)} :modified-at (:modified-at new-component)}
(some? (:variant-id new-component)) (some? (:variant-id new-component))
(assoc :variant-id (:variant-id new-component)) (assoc :variant-id (:variant-id new-component))

View file

@ -79,7 +79,7 @@
:file-schema-validation :file-schema-validation
;; Reports the schema validation errors internally. ;; Reports the schema validation errors internally.
:soft-file-schema-validation :soft-file-schema-validation
;; Activates the referential integrity validation during update file; related to components-v2. ;; Activates the referential integrity validation during update file.
:file-validation :file-validation
;; Reports the referential integrity validation errors internally. ;; Reports the referential integrity validation errors internally.
:soft-file-validation :soft-file-validation

View file

@ -168,22 +168,17 @@
new-instance-shapes (into [] xf-shape new-instance-shapes)] new-instance-shapes (into [] xf-shape new-instance-shapes)]
[nil nil new-instance-shape new-instance-shapes])) [new-instance-shape new-instance-shapes]))
(defn generate-duplicate-component (defn generate-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."
[changes library component-id new-component-id components-v2 & {:keys [new-shape-id apply-changes-local-library? delta new-variant-id]}] [changes library component-id new-component-id & {:keys [new-shape-id apply-changes-local-library? delta new-variant-id]}]
(let [component (ctkl/get-component (:data library) component-id) (let [component (ctkl/get-component (:data library) component-id)
new-name (:name component) new-name (:name component)
main-instance-page (when components-v2 main-instance-page (ctf/get-component-page (:data library) component)
(ctf/get-component-page (:data library) component))
new-component-id (when components-v2 [new-main-instance-shape new-main-instance-shapes]
new-component-id)
[new-component-shape new-component-shapes ; <- null in components-v2
new-main-instance-shape new-main-instance-shapes]
(duplicate-component component new-component-id (:data library) new-shape-id delta new-variant-id)] (duplicate-component component new-component-id (:data library) new-shape-id delta new-variant-id)]
[new-main-instance-shape [new-main-instance-shape
@ -191,12 +186,9 @@
(pcb/with-page main-instance-page) (pcb/with-page main-instance-page)
(pcb/with-objects (:objects main-instance-page)) (pcb/with-objects (:objects main-instance-page))
(pcb/add-objects new-main-instance-shapes {:ignore-touched true}) (pcb/add-objects new-main-instance-shapes {:ignore-touched true})
(pcb/add-component (if components-v2 (pcb/add-component new-component-id
new-component-id
(:id new-component-shape))
(:path component) (:path component)
new-name new-name
new-component-shapes
[] []
(:id new-main-instance-shape) (:id new-main-instance-shape)
(:id main-instance-page) (:id main-instance-page)
@ -226,14 +218,11 @@
parent (when parent-id (get objects parent-id)) parent (when parent-id (get objects parent-id))
library (get libraries file-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 (ctn/make-component-instance page
component component
(:data library) (:data library)
position position
components-v2
(cond-> {} (cond-> {}
force-frame? force-frame?
(assoc :force-frame-id frame-id))) (assoc :force-frame-id frame-id)))
@ -427,8 +416,7 @@
:file (pretty-file file-id libraries current-file-id) :file (pretty-file file-id libraries current-file-id)
:library (pretty-file library-id libraries current-file-id)) :library (pretty-file library-id libraries current-file-id))
(let [file (get-in libraries [file-id :data]) (let [file (get-in libraries [file-id :data])]
components-v2 (get-in file [:options :components-v2])]
(loop [containers (ctf/object-containers-seq file) (loop [containers (ctf/object-containers-seq file)
changes changes] changes changes]
(if-let [container (first containers)] (if-let [container (first containers)]
@ -441,7 +429,6 @@
asset-id asset-id
library-id library-id
container container
components-v2
libraries libraries
current-file-id)))) current-file-id))))
changes)))) changes))))
@ -466,8 +453,7 @@
:file (pretty-file file-id libraries current-file-id) :file (pretty-file file-id libraries current-file-id)
:library (pretty-file library-id libraries current-file-id)) :library (pretty-file library-id libraries current-file-id))
(let [file (get-in libraries [file-id :data]) (let [file (get-in libraries [file-id :data])]
components-v2 (get-in file [:options :components-v2])]
(loop [local-components (ctkl/components-seq file) (loop [local-components (ctkl/components-seq file)
changes changes] changes changes]
(if-let [local-component (first local-components)] (if-let [local-component (first local-components)]
@ -479,7 +465,6 @@
asset-id asset-id
library-id library-id
(cfh/make-container local-component :component) (cfh/make-container local-component :component)
components-v2
libraries libraries
current-file-id))) current-file-id)))
changes)))) changes))))
@ -487,7 +472,7 @@
(defn- generate-sync-container (defn- generate-sync-container
"Generate changes to synchronize all shapes in a particular container (a page "Generate changes to synchronize all shapes in a particular container (a page
or a component) that use assets of the given type in the given library." or a component) that use assets of the given type in the given library."
[changes asset-type asset-id library-id container components-v2 libraries current-file-id] [changes asset-type asset-id library-id container libraries current-file-id]
(if (cfh/page? container) (if (cfh/page? container)
(container-log :debug (:id container) :msg "Sync page in local file" :page-id (:id container)) (container-log :debug (:id container) :msg "Sync page in local file" :page-id (:id container))
@ -506,7 +491,6 @@
library-id library-id
container container
shape shape
components-v2
libraries libraries
current-file-id)) current-file-id))
changes)))) changes))))
@ -536,13 +520,13 @@
(defmulti generate-sync-shape (defmulti generate-sync-shape
"Generate changes to synchronize one shape from all assets of the given type "Generate changes to synchronize one shape from all assets of the given type
that is using, in the given library." that is using, in the given library."
(fn [asset-type _changes _library-id _container _shape _components-v2 _libraries _current-file-id] asset-type)) (fn [asset-type _changes _library-id _container _shape _libraries _current-file-id] asset-type))
(defmethod generate-sync-shape :components (defmethod generate-sync-shape :components
[_ changes _library-id container shape components-v2 libraries current-file-id] [_ changes _library-id container shape libraries current-file-id]
(let [shape-id (:id shape) (let [shape-id (:id shape)
file (get current-file-id libraries)] file (get current-file-id libraries)]
(generate-sync-shape-direct changes file libraries container shape-id false components-v2))) (generate-sync-shape-direct changes file libraries container shape-id false)))
(defmethod generate-sync-shape :colors (defmethod generate-sync-shape :colors
[_ changes library-id _ shape _ libraries _] [_ changes library-id _ shape _ libraries _]
@ -718,7 +702,7 @@
(defn generate-sync-shape-direct (defn generate-sync-shape-direct
"Generate changes to synchronize one shape that is 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 file libraries container shape-id reset? components-v2] [changes file libraries container shape-id reset?]
(shape-log :debug shape-id container (shape-log :debug shape-id container
:msg "Sync shape direct" :shape-inst (str shape-id) :reset? reset?) :msg "Sync shape direct" :shape-inst (str shape-id) :reset? reset?)
(let [shape-inst (ctn/get-shape container shape-id) (let [shape-inst (ctn/get-shape container shape-id)
@ -729,12 +713,12 @@
(let [redirect-shaperef (partial redirect-shaperef container libraries) (let [redirect-shaperef (partial redirect-shaperef container libraries)
shape-main (when component shape-main (when component
(if (and reset? components-v2) (if reset?
;; the reset is against the ref-shape, not against the original shape of the component ;; the reset is against the ref-shape, not against the original shape of the component
(ctf/find-ref-shape file container libraries shape-inst) (ctf/find-ref-shape file container libraries shape-inst)
(ctf/get-ref-shape library component shape-inst))) (ctf/get-ref-shape library component shape-inst)))
shape-inst (if (and reset? components-v2) shape-inst (if reset?
(redirect-shaperef shape-inst shape-main) (redirect-shaperef shape-inst shape-main)
shape-inst) shape-inst)
@ -756,13 +740,10 @@
root-main root-main
reset? reset?
initial-root? initial-root?
redirect-shaperef redirect-shaperef)
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.
(if components-v2 changes))
changes
(generate-detach-instance changes libraries container shape-id))))
changes))) changes)))
(defn- find-main-container (defn- find-main-container
@ -783,7 +764,7 @@
nil)))))) nil))))))
(defn- generate-sync-shape-direct-recursive (defn- generate-sync-shape-direct-recursive
[changes container shape-inst component library file libraries shape-main root-inst root-main reset? initial-root? redirect-shaperef components-v2] [changes container shape-inst component library file libraries shape-main root-inst root-main reset? initial-root? redirect-shaperef]
(shape-log :debug (:id shape-inst) container (shape-log :debug (:id shape-inst) container
:msg "Sync shape direct recursive" :msg "Sync shape direct recursive"
:shape-inst (str (:name shape-inst) " " (pretty-uuid (:id shape-inst))) :shape-inst (str (:name shape-inst) " " (pretty-uuid (:id shape-inst)))
@ -791,9 +772,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
(if components-v2
changes changes
(generate-detach-instance changes container {(:id library) library} (:id shape-inst)))
(let [omit-touched? (not reset?) (let [omit-touched? (not reset?)
clear-remote-synced? (and initial-root? reset?) clear-remote-synced? (and initial-root? reset?)
set-remote-synced? (and (not initial-root?) reset?) set-remote-synced? (and (not initial-root?) reset?)
@ -832,7 +811,7 @@
children-inst (vec (ctn/get-direct-children container shape-inst)) children-inst (vec (ctn/get-direct-children container shape-inst))
children-main (vec (ctn/get-direct-children component-container shape-main)) children-main (vec (ctn/get-direct-children component-container shape-main))
children-inst (if (and reset? components-v2) children-inst (if reset?
(map #(redirect-shaperef %) children-inst) children-inst) (map #(redirect-shaperef %) children-inst) children-inst)
only-inst (fn [changes child-inst] only-inst (fn [changes child-inst]
@ -864,8 +843,7 @@
root-inst root-inst
root-main root-main
omit-touched? omit-touched?
set-remote-synced? set-remote-synced?)
components-v2)
changes)) changes))
both (fn [changes child-inst child-main] both (fn [changes child-inst child-main]
@ -885,8 +863,7 @@
root-main root-main
reset? reset?
initial-root? initial-root?
redirect-shaperef redirect-shaperef))
components-v2))
swapped (fn [changes child-inst child-main] swapped (fn [changes child-inst child-main]
(shape-log :trace (:id child-inst) container (shape-log :trace (:id child-inst) container
@ -924,8 +901,7 @@
swapped swapped
moved moved
false false
reset? reset?)
components-v2)
changes changes
(cond-> changes (cond-> changes
@ -941,27 +917,16 @@
(defn generate-rename-component (defn generate-rename-component
"Generate the changes for rename the component with the given id, in the current file library." "Generate the changes for rename the component with the given id, in the current file library."
[changes id new-name library-data components-v2] [changes id new-name library-data]
(let [[path name] (cfh/parse-path-name new-name) (let [[path name] (cfh/parse-path-name new-name)]
update-fn
(fn [component]
(cond-> component
:always
(assoc :path path
:name name)
(not components-v2)
(update :objects
;; Give the same name to the root shape
#(assoc-in % [id :name] name))))]
(-> changes (-> changes
(pcb/with-library-data library-data) (pcb/with-library-data library-data)
(pcb/update-component id update-fn)))) (pcb/update-component id #(assoc % :path path :name name)))))
(defn generate-sync-shape-inverse (defn generate-sync-shape-inverse
"Generate changes to update the component a shape is linked to, from "Generate changes to update the component a shape is linked to, from
the values in the shape and all its children." the values in the shape and all its children."
[changes file libraries container shape-id components-v2] [changes file libraries container shape-id]
(shape-log :debug shape-id container :msg "Sync shape inverse" :shape (str shape-id)) (shape-log :debug shape-id container :msg "Sync shape inverse" :shape (str shape-id))
(let [redirect-shaperef (partial redirect-shaperef container libraries) (let [redirect-shaperef (partial redirect-shaperef container libraries)
shape-inst (ctn/get-shape container shape-id) shape-inst (ctn/get-shape container shape-id)
@ -969,13 +934,9 @@
component (ctkl/get-component library (:component-id shape-inst)) component (ctkl/get-component library (:component-id shape-inst))
shape-main (when component shape-main (when component
(if components-v2 (ctf/find-remote-shape container libraries shape-inst))
(ctf/find-remote-shape container libraries shape-inst)
(ctf/get-ref-shape library component shape-inst)))
shape-inst (if components-v2 shape-inst (redirect-shaperef shape-inst shape-main)
(redirect-shaperef shape-inst shape-main)
shape-inst)
initial-root? (:component-root shape-inst) initial-root? (:component-root shape-inst)
@ -984,7 +945,7 @@
changes (cond-> changes changes (cond-> changes
(and component (contains? (:touched shape-inst) :name-group)) (and component (contains? (:touched shape-inst) :name-group))
(generate-rename-component (:component-id shape-inst) (:name shape-inst) library components-v2))] (generate-rename-component (:component-id shape-inst) (:name shape-inst) library))]
(if component (if component
(generate-sync-shape-inverse-recursive changes (generate-sync-shape-inverse-recursive changes
@ -998,12 +959,11 @@
root-inst root-inst
root-main root-main
initial-root? initial-root?
redirect-shaperef redirect-shaperef)
components-v2)
changes))) changes)))
(defn- generate-sync-shape-inverse-recursive (defn- generate-sync-shape-inverse-recursive
[changes container shape-inst component library file libraries shape-main root-inst root-main initial-root? redirect-shaperef components-v2] [changes container shape-inst component library file libraries shape-main root-inst root-main initial-root? redirect-shaperef]
(shape-log :trace (:id shape-inst) container (shape-log :trace (:id shape-inst) container
:msg "Sync shape inverse recursive" :msg "Sync shape inverse recursive"
:shape (str (:name shape-inst)) :shape (str (:name shape-inst))
@ -1060,9 +1020,7 @@
children-main (mapv #(ctn/get-shape component-container %) children-main (mapv #(ctn/get-shape component-container %)
(:shapes shape-main)) (:shapes shape-main))
children-inst (if components-v2 children-inst (map #(redirect-shaperef %) children-inst)
(map #(redirect-shaperef %) children-inst)
children-inst)
only-inst (fn [changes child-inst] only-inst (fn [changes child-inst]
(add-shape-to-main changes (add-shape-to-main changes
@ -1073,8 +1031,7 @@
component-container component-container
container container
root-inst root-inst
root-main root-main))
components-v2))
only-main (fn [changes child-main] only-main (fn [changes child-main]
(remove-shape changes (remove-shape changes
@ -1094,8 +1051,7 @@
root-inst root-inst
root-main root-main
initial-root? initial-root?
redirect-shaperef redirect-shaperef))
components-v2))
swapped (fn [changes child-inst child-main] swapped (fn [changes child-inst child-main]
(shape-log :trace (:id child-inst) container (shape-log :trace (:id child-inst) container
@ -1129,8 +1085,7 @@
swapped swapped
moved moved
true true
true true)
components-v2)
;; The inverse sync may be made on a component that is inside a ;; The inverse sync may be made on a component that is inside a
;; remote library. We need to separate changes that are from ;; remote library. We need to separate changes that are from
@ -1148,7 +1103,7 @@
;; ---- Operation generation helpers ---- ;; ---- Operation generation helpers ----
(defn- compare-children (defn- compare-children
[changes shape-inst children-inst children-main container-inst container-main file libraries only-inst-cb only-main-cb both-cb swapped-cb moved-cb inverse? reset? components-v2] [changes shape-inst children-inst children-main container-inst container-main file libraries only-inst-cb only-main-cb both-cb swapped-cb moved-cb inverse? reset?]
(shape-log :trace (:id shape-inst) container-inst :msg "Compare children") (shape-log :trace (:id shape-inst) container-inst :msg "Compare children")
(loop [children-inst (seq (or children-inst [])) (loop [children-inst (seq (or children-inst []))
children-main (seq (or children-main [])) children-main (seq (or children-main []))
@ -1169,18 +1124,18 @@
(reduce only-inst-cb changes children-inst) (reduce only-inst-cb changes children-inst)
:else :else
(if (or (ctk/is-main-of? child-main child-inst components-v2) (if (or (ctk/is-main-of? child-main child-inst)
(and (ctf/match-swap-slot? child-main child-inst container-inst container-main file libraries) (not reset?))) (and (ctf/match-swap-slot? child-main child-inst container-inst container-main file libraries) (not reset?)))
(recur (next children-inst) (recur (next children-inst)
(next children-main) (next children-main)
(if (ctk/is-main-of? child-main child-inst components-v2) (if (ctk/is-main-of? child-main child-inst)
(both-cb changes child-inst child-main) (both-cb changes child-inst child-main)
(swapped-cb changes child-inst child-main))) (swapped-cb changes child-inst child-main)))
(let [child-inst' (d/seek #(or (ctk/is-main-of? child-main % components-v2) (let [child-inst' (d/seek #(or (ctk/is-main-of? child-main %)
(and (ctf/match-swap-slot? child-main % container-inst container-main file libraries) (not reset?))) (and (ctf/match-swap-slot? child-main % container-inst container-main file libraries) (not reset?)))
children-inst) children-inst)
child-main' (d/seek #(or (ctk/is-main-of? % child-inst components-v2) child-main' (d/seek #(or (ctk/is-main-of? % child-inst)
(and (ctf/match-swap-slot? % child-inst container-inst container-main file libraries) (not reset?))) (and (ctf/match-swap-slot? % child-inst container-inst container-main file libraries) (not reset?)))
children-main)] children-main)]
(cond (cond
@ -1196,7 +1151,7 @@
:else :else
(if inverse? (if inverse?
(let [is-main? (ctk/is-main-of? child-inst child-main' components-v2)] (let [is-main? (ctk/is-main-of? child-inst child-main')]
(recur (next children-inst) (recur (next children-inst)
(remove #(= (:id %) (:id child-main')) children-main) (remove #(= (:id %) (:id child-main')) children-main)
(cond-> changes (cond-> changes
@ -1206,7 +1161,7 @@
(swapped-cb child-inst child-main') (swapped-cb child-inst child-main')
:always :always
(moved-cb child-inst child-main')))) (moved-cb child-inst child-main'))))
(let [is-main? (ctk/is-main-of? child-inst' child-main components-v2)] (let [is-main? (ctk/is-main-of? child-inst' child-main)]
(recur (remove #(= (:id %) (:id child-inst')) children-inst) (recur (remove #(= (:id %) (:id child-inst')) children-inst)
(next children-main) (next children-main)
(cond-> changes (cond-> changes
@ -1218,14 +1173,14 @@
(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-page container root-instance root-main omit-touched? set-remote-synced? components-v2] [changes component-shape index component-page container root-instance root-main omit-touched? set-remote-synced?]
(shape-log :info (:id component-shape) component-page (shape-log :info (:id component-shape) component-page
:msg (str "ADD [P " (pretty-uuid (:id container)) "] " :msg (str "ADD [P " (pretty-uuid (:id container)) "] "
(:name component-shape) (:name component-shape)
" " " "
(pretty-uuid (:id component-shape)))) (pretty-uuid (:id component-shape))))
(let [component-parent-shape (ctn/get-shape component-page (: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 % components-v2) parent-shape (d/seek #(ctk/is-main-of? component-parent-shape %)
(cfh/get-children-with-self (:objects container) (cfh/get-children-with-self (:objects container)
(:id root-instance))) (:id root-instance)))
all-parents (into [(:id parent-shape)] all-parents (into [(:id parent-shape)]
@ -1294,14 +1249,14 @@
changes'))) changes')))
(defn- add-shape-to-main (defn- add-shape-to-main
[changes shape index component component-container page root-instance root-main components-v2] [changes shape index component component-container page root-instance root-main]
(shape-log :info (:id shape) page (shape-log :info (:id shape) page
:msg (str "ADD [C " (pretty-uuid (:id component-container)) "] " :msg (str "ADD [C " (pretty-uuid (:id component-container)) "] "
(:name shape) (:name shape)
" " " "
(pretty-uuid (:id shape)))) (pretty-uuid (:id 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 components-v2) component-parent-shape (d/seek #(ctk/is-main-of? % parent-shape)
(cfh/get-children-with-self (:objects component-container) (cfh/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)]
@ -1886,30 +1841,27 @@
(assoc change :component-id (:id container)))) (assoc change :component-id (:id container))))
(defn generate-add-component-changes (defn generate-add-component-changes
[changes root objects file-id page-id components-v2] [changes root objects file-id page-id]
(let [name (:name root) (let [name (:name root)
[path name] (cfh/parse-path-name name) [path name] (cfh/parse-path-name name)
[root-shape new-shapes updated-shapes] [root-shape updated-shapes]
(if-not components-v2 (ctn/convert-shape-in-component root objects file-id)
(ctn/make-component-shape root objects file-id components-v2)
(ctn/convert-shape-in-component root objects file-id))
changes (-> changes changes (-> changes
(pcb/add-component (:id root-shape) (pcb/add-component (:id root-shape)
path path
name name
new-shapes
updated-shapes updated-shapes
(:id root) (:id root)
page-id))] page-id))]
[root-shape changes])) [root-shape changes]))
(defn generate-add-component (defn generate-add-component
"If there is exactly one id, and it's a frame (or a group in v1), and not already a component, "If there is exactly one id, and it's a frame, and not already a component,
use it as root. Otherwise, create a frame (v2) or group (v1) that contains all ids. Then, make a use it as root. Otherwise, create a frame that contains all ids. Then, make a
component with it, and link all shapes to their corresponding one in the component." component with it, and link all shapes to their corresponding one in the component."
[changes shapes objects page-id file-id components-v2 prepare-create-group prepare-create-board] [changes shapes objects page-id file-id prepare-create-board]
(let [changes (pcb/with-page-id changes page-id) (let [changes (pcb/with-page-id changes page-id)
shapes-count (count shapes) shapes-count (count shapes)
@ -1921,9 +1873,7 @@
[root changes old-root-ids] [root changes old-root-ids]
(if (and (= shapes-count 1) (if (and (= shapes-count 1)
(or (and (cfh/group-shape? first-shape) (cfh/frame-shape? first-shape)
(not components-v2))
(cfh/frame-shape? first-shape))
(not (ctk/instance-head? first-shape))) (not (ctk/instance-head? first-shape)))
[first-shape [first-shape
(-> changes (-> changes
@ -1938,13 +1888,6 @@
shape-ids (into (d/ordered-set) (map :id) shapes) shape-ids (into (d/ordered-set) (map :id) shapes)
[root changes] [root changes]
(if-not components-v2
(prepare-create-group changes ; These functions needs to be passed as argument
objects ; to avoid a circular dependence
page-id
shapes
root-name
(not (ctk/instance-head? first-shape)))
(prepare-create-board changes (prepare-create-board changes
(uuid/next) (uuid/next)
(:parent-id first-shape) (:parent-id first-shape)
@ -1952,7 +1895,7 @@
shape-ids shape-ids
nil nil
root-name root-name
true))] true)]
[root changes shape-ids])) [root changes shape-ids]))
@ -1966,7 +1909,7 @@
objects' (assoc objects (:id root) root) objects' (assoc objects (:id root) root)
[root-shape changes] (generate-add-component-changes changes root objects' file-id page-id components-v2) [root-shape changes] (generate-add-component-changes changes root objects' file-id page-id)
changes (pcb/update-shapes changes changes (pcb/update-shapes changes
old-root-ids old-root-ids
@ -2052,8 +1995,7 @@
[changes objects shape file page libraries id-new-component index target-cell keep-props-values] [changes objects shape file page libraries id-new-component index target-cell keep-props-values]
(let [[all-parents changes] (let [[all-parents changes]
(-> changes (-> changes
(cls/generate-delete-shapes file page objects (d/ordered-set (:id shape)) {:components-v2 true (cls/generate-delete-shapes file page objects (d/ordered-set (:id shape)) {:component-swap true}))
:component-swap true}))
[new-shape changes] [new-shape changes]
(-> changes (-> changes
(generate-new-shape-for-swap shape file page libraries id-new-component index target-cell keep-props-values))] (generate-new-shape-for-swap shape file page libraries id-new-component index target-cell keep-props-values))]
@ -2084,7 +2026,7 @@
(generate-sync-file file-id :typographies asset-id library-id libraries current-file-id)))) (generate-sync-file file-id :typographies asset-id library-id libraries current-file-id))))
(defn generate-sync-head (defn generate-sync-head
[changes file-full libraries container id components-v2 reset?] [changes file-full libraries container id reset?]
(let [shape-inst (ctn/get-shape container id) (let [shape-inst (ctn/get-shape container id)
objects (:objects container) objects (:objects container)
parent (get objects (:parent-id shape-inst)) parent (get objects (:parent-id shape-inst))
@ -2093,11 +2035,11 @@
(-> changes (-> changes
(pcb/with-container container) (pcb/with-container container)
(pcb/with-objects (:objects container)) (pcb/with-objects (:objects container))
(generate-sync-shape-direct file-full libraries container (:id head) reset? components-v2))] (generate-sync-shape-direct file-full libraries container (:id head) reset?))]
changes)) changes))
(defn generate-reset-component (defn generate-reset-component
[changes file-full libraries container id components-v2] [changes file-full libraries container id]
(let [objects (:objects container) (let [objects (:objects container)
swap-slot (-> (ctn/get-shape container id) swap-slot (-> (ctn/get-shape container id)
(ctk/get-swap-slot)) (ctk/get-swap-slot))
@ -2105,11 +2047,11 @@
(-> changes (-> changes
(pcb/with-container container) (pcb/with-container container)
(pcb/with-objects objects) (pcb/with-objects objects)
(generate-sync-shape-direct file-full libraries container id true components-v2))] (generate-sync-shape-direct file-full libraries container id true))]
(cond-> changes (cond-> changes
(some? swap-slot) (some? swap-slot)
(generate-sync-head file-full libraries container id components-v2 true)))) (generate-sync-head file-full libraries container id true))))
(defn generate-duplicate-flows (defn generate-duplicate-flows
[changes shapes page ids-map] [changes shapes page ids-map]
@ -2174,7 +2116,6 @@
library library
(:component-id component-shape) (:component-id component-shape)
new-component-id new-component-id
true
{:apply-changes-local-library? true {:apply-changes-local-library? true
:delta delta :delta delta
:new-variant-id parent-id})] :new-variant-id parent-id})]
@ -2271,8 +2212,7 @@
regenerate-component regenerate-component
(fn [changes shape] (fn [changes shape]
(let [components-v2 (dm/get-in library-data [:options :components-v2]) (let [[_ changes] (generate-add-component-changes changes shape objects file-id (:id page))]
[_ changes] (generate-add-component-changes changes shape objects file-id (:id page) components-v2)]
changes)) changes))
new-obj new-obj

View file

@ -82,7 +82,7 @@
(pcb/update-shapes ids update-fn {:attrs #{:blocked :hidden}})))) (pcb/update-shapes ids update-fn {:attrs #{:blocked :hidden}}))))
(defn generate-delete-shapes (defn generate-delete-shapes
[changes file page objects ids {:keys [components-v2 ignore-touched component-swap]}] [changes file page objects ids {:keys [ignore-touched component-swap]}]
(let [ids (cfh/clean-loops objects ids) (let [ids (cfh/clean-loops objects ids)
in-component-copy? in-component-copy?
@ -97,7 +97,6 @@
(not component-swap)))) (not component-swap))))
[ids-to-delete ids-to-hide] [ids-to-delete ids-to-hide]
(if components-v2
(loop [ids-seq (seq ids) (loop [ids-seq (seq ids)
ids-to-delete [] ids-to-delete []
ids-to-hide []] ids-to-hide []]
@ -111,7 +110,7 @@
(recur (rest ids-seq) (recur (rest ids-seq)
(conj ids-to-delete id) (conj ids-to-delete id)
ids-to-hide))))) ids-to-hide)))))
[ids []])
changes (-> changes changes (-> changes
(pcb/with-page page) (pcb/with-page page)
@ -190,7 +189,6 @@
#{}) #{})
components-to-delete components-to-delete
(if components-v2
(reduce (fn [components id] (reduce (fn [components id]
(let [shape (get objects id)] (let [shape (get objects id)]
(if (and (= (:component-file shape) (:id file)) ;; Main instances should exist only in local file (if (and (= (:component-file shape) (:id file)) ;; Main instances should exist only in local file
@ -199,7 +197,7 @@
components))) components)))
[] []
(into ids-to-delete all-children)) (into ids-to-delete all-children))
[])
ids-set (set ids-to-delete) ids-set (set ids-to-delete)

View file

@ -24,7 +24,6 @@
{:data data} {:data data}
component-id component-id
new-component-id new-component-id
true
{:new-shape-id new-shape-id :apply-changes-local-library? true}))] {:new-shape-id new-shape-id :apply-changes-local-library? true}))]
(-> changes (-> changes
(clvp/generate-update-property-value new-component-id prop-num value) (clvp/generate-update-property-value new-component-id prop-num value)

View file

@ -31,7 +31,7 @@
"Need that root is already a frame" "Need that root is already a frame"
(cfh/frame-shape? root)) (cfh/frame-shape? root))
(let [[_new-root _new-shapes updated-shapes] (let [[_new-root updated-shapes]
(ctn/convert-shape-in-component root (:objects page) (:id file)) (ctn/convert-shape-in-component root (:objects page) (:id file))
updated-root (first updated-shapes) ; Can't use new-root because it has a new id updated-root (first updated-shapes) ; Can't use new-root because it has a new id
@ -54,8 +54,7 @@
:name name :name name
:path path :path path
:main-instance-id (:id updated-root) :main-instance-id (:id updated-root)
:main-instance-page (:id page) :main-instance-page (:id page)))))))))
:shapes updated-shapes))))))))
(defn update-component (defn update-component
[file component-label & {:keys [] :as params}] [file component-label & {:keys [] :as params}]
@ -98,7 +97,6 @@
component component
(:data library) (:data library)
(gpt/point 100 100) (gpt/point 100 100)
true
{:force-id (thi/new-id! copy-root-label) {:force-id (thi/new-id! copy-root-label)
:force-frame-id frame-id}) :force-frame-id frame-id})

View file

@ -336,8 +336,7 @@
file file
{file-id file} {file-id file}
(ctn/make-container container :page) (ctn/make-container container :page)
(:id shape) (:id shape)))
true))
file' (thf/apply-changes file changes)] file' (thf/apply-changes file changes)]
(if propagate-fn (if propagate-fn
(propagate-fn file') (propagate-fn file')
@ -361,7 +360,7 @@
(:objects page) (:objects page)
#{(-> (ths/get-shape file shape-tag :page-label page-label) #{(-> (ths/get-shape file shape-tag :page-label page-label)
:id)} :id)}
{:components-v2 true}) {})
file' (thf/apply-changes file changes)] file' (thf/apply-changes file changes)]
(if propagate-fn (if propagate-fn
(propagate-fn file') (propagate-fn file')

View file

@ -182,10 +182,8 @@
(= (:component-file shape) file-id))) (= (:component-file shape) file-id)))
(defn is-main-of? (defn is-main-of?
[shape-main shape-inst components-v2] [shape-main shape-inst]
(or (= (:shape-ref shape-inst) (:id shape-main)) (= (:shape-ref shape-inst) (:id shape-main)))
(and (= (:shape-ref shape-inst) (:shape-ref shape-main))
(not components-v2))))
(defn main-instance? (defn main-instance?
"Check if this shape is the root of the main instance of some "Check if this shape is the root of the main instance of some

View file

@ -34,20 +34,12 @@
(assoc component :modified-at (dt/now))) (assoc component :modified-at (dt/now)))
(defn add-component (defn add-component
[fdata {:keys [id name path main-instance-id main-instance-page shapes annotation variant-id variant-properties]}] [fdata {:keys [id name path main-instance-id main-instance-page annotation variant-id variant-properties]}]
(let [components-v2 (dm/get-in fdata [:options :components-v2]) (let [fdata (update fdata :components assoc id (touch {:id id :name name :path path}))]
fdata (update fdata :components assoc id (touch {:id id :name name :path path}))]
(if components-v2
(cond-> (update-in fdata [:components id] assoc :main-instance-id main-instance-id :main-instance-page main-instance-page) (cond-> (update-in fdata [:components id] assoc :main-instance-id main-instance-id :main-instance-page main-instance-page)
annotation (update-in [:components id] assoc :annotation annotation) annotation (update-in [:components id] assoc :annotation annotation)
variant-id (update-in [:components id] assoc :variant-id variant-id) variant-id (update-in [:components id] assoc :variant-id variant-id)
variant-properties (update-in [:components id] assoc :variant-properties variant-properties)) variant-properties (update-in [:components id] assoc :variant-properties variant-properties))))
(let [wrap-object-fn cfeat/*wrap-with-objects-map-fn*]
(assoc-in fdata [:components id :objects]
(->> shapes
(d/index-by :id)
(wrap-object-fn)))))))
(defn mod-component (defn mod-component
[file-data {:keys [id name path main-instance-id main-instance-page objects annotation variant-id variant-properties modified-at]}] [file-data {:keys [id name path main-instance-id main-instance-page objects annotation variant-id variant-properties modified-at]}]

View file

@ -267,67 +267,8 @@
new-children (->> (cfh/get-children objects (:id root)) new-children (->> (cfh/get-children objects (:id root))
(map #(dissoc % :component-root)))] (map #(dissoc % :component-root)))]
[(assoc new-root :id new-id) [(assoc new-root :id new-id)
nil
(into [new-root] new-children)])) (into [new-root] new-children)]))
(defn make-component-shape ;; Only used for components v1
"Clone the shape and all children. Generate new ids and detach
from parent and frame. Update the original shapes to have links
to the new ones."
[shape objects file-id components-v2]
(assert (nil? (:component-id shape)))
(assert (nil? (:component-file shape)))
(assert (nil? (:shape-ref shape)))
(let [frame-ids-map (volatile! {})
;; Ensure that the component root is not an instance
update-new-shape (fn [new-shape original-shape]
(when (= (:type original-shape) :frame)
(vswap! frame-ids-map assoc (:id original-shape) (:id new-shape)))
(cond-> new-shape
true
(dissoc :component-root)
(nil? (:parent-id new-shape))
(dissoc :component-id
:component-file
:shape-ref)))
;; Make the original shape an instance of the new component.
;; If one of the original shape children already was a component
;; instance, maintain this instanceness untouched.
update-original-shape (fn [original-shape new-shape]
(cond-> original-shape
(nil? (:shape-ref original-shape))
(-> (assoc :shape-ref (:id new-shape))
(dissoc :touched))
(nil? (:parent-id new-shape))
(assoc :component-id (:id new-shape)
:component-file file-id
:component-root true)
(and (nil? (:parent-id new-shape)) components-v2)
(assoc :main-instance true)
(some? (:parent-id new-shape))
(dissoc :component-root)))
[new-root-shape new-shapes updated-shapes]
(ctst/clone-shape shape
nil
objects
:update-new-shape update-new-shape
:update-original-shape update-original-shape)
;; If frame-id points to a shape inside the component, remap it to the
;; corresponding new frame shape. If not, set it to nil.
remap-frame-id (fn [shape]
(update shape :frame-id #(get @frame-ids-map % nil)))]
[new-root-shape (map remap-frame-id new-shapes) updated-shapes]))
(defn remove-swap-keep-attrs (defn remove-swap-keep-attrs
"Remove flex children properties except the fit-content for flex layouts. These are properties "Remove flex children properties except the fit-content for flex layouts. These are properties
that we don't have to propagate to copies but will be respected when swapping components" that we don't have to propagate to copies but will be respected when swapping components"
@ -352,20 +293,18 @@
WARNING: This process does not remap media references (on fills, strokes, ...); that is WARNING: This process does not remap media references (on fills, strokes, ...); that is
delegated to an async process on the backend side that checks unreferenced shapes and delegated to an async process on the backend side that checks unreferenced shapes and
automatically creates correct references." automatically creates correct references."
([page component library-data position components-v2] ([page component library-data position]
(make-component-instance page component library-data position components-v2 {})) (make-component-instance page component library-data position {}))
([page component library-data position components-v2 ([page component library-data position
{:keys [main-instance? force-id force-frame-id keep-ids?] {:keys [main-instance? force-id force-frame-id keep-ids?]
:or {main-instance? false force-id nil force-frame-id nil keep-ids? false}}] :or {main-instance? false force-id nil force-frame-id nil keep-ids? false}}]
(let [component-page (when components-v2 (let [component-page (ctpl/get-page library-data (:main-instance-page component))
(ctpl/get-page library-data (:main-instance-page component)))
component-shape (if components-v2 component-shape (-> (get-shape component-page (:main-instance-id component))
(-> (get-shape component-page (:main-instance-id component))
(assoc :parent-id nil) ;; On v2 we force parent-id to nil in order to behave like v1 (assoc :parent-id nil) ;; On v2 we force parent-id to nil in order to behave like v1
(assoc :frame-id uuid/zero) (assoc :frame-id uuid/zero)
(remove-swap-keep-attrs)) (remove-swap-keep-attrs))
(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)
@ -395,8 +334,7 @@
update-new-shape update-new-shape
(fn [new-shape original-shape] (fn [new-shape original-shape]
(let [new-name (:name new-shape) (let [new-name (:name new-shape)
root? (or (ctk/instance-root? original-shape) ; If shape is inside a component (not components-v2) root? (ctk/instance-root? original-shape)]
(nil? (:parent-id original-shape)))] ; we detect it by having no parent)
(when root? (when root?
(vswap! unames conj new-name)) (vswap! unames conj new-name))
@ -417,10 +355,8 @@
main-instance? main-instance?
(dissoc :shape-ref) (dissoc :shape-ref)
(and (not main-instance?) (not main-instance?)
(or components-v2 ; In v1, shape-ref points to the remote instance (assoc :shape-ref (:id original-shape)) ; shape-ref points to the near instance
(nil? (:shape-ref original-shape)))) ; in v2, shape-ref points to the near instance
(assoc :shape-ref (:id original-shape))
(nil? (:parent-id original-shape)) (nil? (:parent-id original-shape))
(assoc :component-id (:id component) (assoc :component-id (:id component)
@ -428,14 +364,14 @@
:component-root true :component-root true
:name new-name) :name new-name)
(or (some? (:parent-id original-shape)) ; On v2 we have removed the parent-id for component roots (see above) (or (some? (:parent-id original-shape)) ; On v2 we have removed the parent-id for component roots
(some? component-frame)) (some? component-frame))
(dissoc :component-root)))) (dissoc :component-root))))
[new-shape new-shapes _] [new-shape new-shapes _]
(ctst/clone-shape component-shape (ctst/clone-shape component-shape
frame-id frame-id
(if components-v2 (:objects component-page) (:objects component)) (:objects component-page)
:update-new-shape update-new-shape :update-new-shape update-new-shape
:force-id force-id :force-id force-id
:keep-ids? keep-ids? :keep-ids? keep-ids?
@ -593,8 +529,7 @@
;; TODO: the check of :width and :height probably may be ;; TODO: the check of :width and :height probably may be
;; removed after the check added in ;; removed after the check added in
;; data/workspace/modifiers/check-delta function. Better check ;; data/workspace/modifiers/check-delta function.
;; it and test toroughly when activating components-v2 mode.
in-copy? in-copy?
(ctk/in-component-copy? shape) (ctk/in-component-copy? shape)

View file

@ -130,7 +130,7 @@
(some? page-id) (some? page-id)
(ctpl/add-page page) (ctpl/add-page page)
(contains? cfeat/*current* "components/v2") :always
(assoc-in [:options :components-v2] true))))) (assoc-in [:options :components-v2] true)))))
(defn make-file (defn make-file
@ -221,31 +221,28 @@
(ctpl/get-page file-data (:main-instance-page component))) (ctpl/get-page file-data (:main-instance-page component)))
(defn get-component-container (defn get-component-container
"Retrieve the container that holds the component shapes (the page in components-v2 "Retrieve the container that holds the component shapes (the page
or the component itself in v1 or deleted component)." or the component itself on deleted component)."
[file-data component] [file-data component]
(let [components-v2 (dm/get-in file-data [:options :components-v2])] (if (not (:deleted component))
(if (and components-v2 (not (:deleted component)))
(let [component-page (get-component-page file-data component)] (let [component-page (get-component-page file-data component)]
(cfh/make-container component-page :page)) (cfh/make-container component-page :page))
(cfh/make-container component :component)))) (cfh/make-container component :component)))
(defn get-component-root (defn get-component-root
"Retrieve the root shape of the component." "Retrieve the root shape of the component."
[file-data component] [file-data component]
(let [components-v2 (dm/get-in file-data [:options :components-v2])] (if (not (:deleted component))
(if (and components-v2 (not (:deleted component)))
(-> file-data (-> file-data
(get-component-page component) (get-component-page component)
(ctn/get-shape (:main-instance-id component))) (ctn/get-shape (:main-instance-id component)))
(ctk/get-component-root component)))) (ctk/get-component-root component)))
(defn get-component-shape (defn get-component-shape
"Retrieve one shape in the component by id. If with-context? is true, add the "Retrieve one shape in the component by id. If with-context? is true, add the
file and container where the shape resides in its metadata." file and container where the shape resides in its metadata."
[file-data component shape-id & {:keys [with-context?] :or {with-context? false}}] [file-data component shape-id & {:keys [with-context?] :or {with-context? false}}]
(let [components-v2 (dm/get-in file-data [:options :components-v2])] (if (not (:deleted component))
(if (and components-v2 (not (:deleted component)))
(let [component-page (get-component-page file-data component)] (let [component-page (get-component-page file-data component)]
(when component-page (when component-page
(let [child (cfh/get-child (:objects component-page) (let [child (cfh/get-child (:objects component-page)
@ -262,7 +259,7 @@
(and shape with-context?) (and shape with-context?)
(with-meta {:file {:id (:id file-data) (with-meta {:file {:id (:id file-data)
:data file-data} :data file-data}
:container (ctn/make-container component :component)})))))) :container (ctn/make-container component :component)})))))
(defn get-ref-shape (defn get-ref-shape
"Retrieve the shape in the component that is referenced by the instance shape." "Retrieve the shape in the component that is referenced by the instance shape."
@ -384,12 +381,11 @@
(defn get-component-shapes (defn get-component-shapes
"Retrieve all shapes of the component" "Retrieve all shapes of the component"
[file-data component] [file-data component]
(let [components-v2 (dm/get-in file-data [:options :components-v2])]
(if (and components-v2 (if (not (:deleted component)) ;; the deleted components have its children in the :objects property
(not (:deleted component))) ;; the deleted components have its children in the :objects property
(let [instance-page (get-component-page file-data component)] (let [instance-page (get-component-page file-data component)]
(cfh/get-children-with-self (:objects instance-page) (:main-instance-id component))) (cfh/get-children-with-self (:objects instance-page) (:main-instance-id component)))
(vals (:objects component))))) (vals (:objects component))))
;; Return true if the object is a component that exists on the file or its libraries (even a deleted one) ;; Return true if the object is a component that exists on the file or its libraries (even a deleted one)
(defn is-main-of-known-component? (defn is-main-of-known-component?
@ -406,8 +402,7 @@
([file-data component] ([file-data component]
(load-component-objects file-data component (gpt/point 0 0))) (load-component-objects file-data component (gpt/point 0 0)))
([file-data component delta] ([file-data component delta]
(let [components-v2 (dm/get-in file-data [:options :components-v2])] (if (and component (empty? (:objects component))) ;; This operation may be called twice, e.g. in an idempotent change
(if (and components-v2 component (empty? (:objects component))) ;; This operation may be called twice, e.g. in an idempotent change
(let [component-page (get-component-page file-data component) (let [component-page (get-component-page file-data component)
page-objects (:objects component-page) page-objects (:objects component-page)
objects (->> (cons (:main-instance-id component) objects (->> (cons (:main-instance-id component)
@ -418,15 +413,14 @@
(map #(gsh/move % delta)) (map #(gsh/move % delta))
(d/index-by :id))] (d/index-by :id))]
(assoc component :objects objects)) (assoc component :objects objects))
component)))) component)))
(defn delete-component (defn delete-component
"Mark a component as deleted and store the main instance shapes iside it, to "Mark a component as deleted and store the main instance shapes iside it, to
be able to be recovered later." be able to be recovered later."
[file-data component-id skip-undelete? delta] [file-data component-id skip-undelete? delta]
(let [components-v2 (dm/get-in file-data [:options :components-v2]) (let [delta (or delta (gpt/point 0 0))]
delta (or delta (gpt/point 0 0))] (if skip-undelete?
(if (or (not components-v2) skip-undelete?)
(ctkl/delete-component file-data component-id) (ctkl/delete-component file-data component-id)
(-> file-data (-> file-data
(ctkl/update-component component-id #(load-component-objects file-data % delta)) (ctkl/update-component component-id #(load-component-objects file-data % delta))
@ -435,8 +429,7 @@
(defn restore-component (defn restore-component
"Recover a deleted component and all its shapes and put all this again in place." "Recover a deleted component and all its shapes and put all this again in place."
[file-data component-id page-id parent-id] [file-data component-id page-id parent-id]
(let [components-v2 (dm/get-in file-data [:options :components-v2]) (let [update-page? (not (nil? page-id))
update-page? (and components-v2 (not (nil? page-id)))
component (ctkl/get-component file-data component-id true) component (ctkl/get-component file-data component-id true)
update-variant? (and (some? parent-id) update-variant? (and (some? parent-id)
(ctk/is-variant? component))] (ctk/is-variant? component))]
@ -563,7 +556,6 @@
component component
library-data library-data
position position
(dm/get-in file-data [:options :components-v2])
{:main-instance? true {:main-instance? true
:keep-ids? true}) :keep-ids? true})
@ -595,8 +587,7 @@
:name (:name component) :name (:name component)
: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 (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

View file

@ -40,8 +40,6 @@
(:objects page) (:objects page)
(:id page) (:id page)
(:id file) (:id file)
true
nil
nil) nil)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -74,8 +72,6 @@
(:objects page) (:objects page)
(:id page) (:id page)
(:id file) (:id file)
true
nil
cfsh/prepare-create-artboard-from-selection) cfsh/prepare-create-artboard-from-selection)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -111,8 +107,6 @@
(:objects page) (:objects page)
(:id page) (:id page)
(:id file) (:id file)
true
nil
cfsh/prepare-create-artboard-from-selection) cfsh/prepare-create-artboard-from-selection)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -151,8 +145,6 @@
(:objects page) (:objects page)
(:id page) (:id page)
(:id file) (:id file)
true
nil
cfsh/prepare-create-artboard-from-selection) cfsh/prepare-create-artboard-from-selection)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -191,8 +183,6 @@
(:objects page) (:objects page)
(:id page) (:id page)
(:id file) (:id file)
true
nil
nil) nil)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -232,8 +222,6 @@
(:objects page) (:objects page)
(:id page) (:id page)
(:id file) (:id file)
true
nil
cfsh/prepare-create-artboard-from-selection) cfsh/prepare-create-artboard-from-selection)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -265,8 +253,7 @@
changes (cll/generate-rename-component (pcb/empty-changes) changes (cll/generate-rename-component (pcb/empty-changes)
(:id component) (:id component)
"Test component after" "Test component after"
(:data file) (:data file))
true)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -445,8 +432,8 @@
(t/is (some? copy1-child')) (t/is (some? copy1-child'))
(t/is (ctk/instance-root? copy1-root')) (t/is (ctk/instance-root? copy1-root'))
(t/is (ctk/instance-of? copy1-root' (:id file') (:id component'))) (t/is (ctk/instance-of? copy1-root' (:id file') (:id component')))
(t/is (ctk/is-main-of? main1-root' copy1-root' true)) (t/is (ctk/is-main-of? main1-root' copy1-root'))
(t/is (ctk/is-main-of? main1-child' copy1-child' true)) (t/is (ctk/is-main-of? main1-child' copy1-child'))
(t/is (ctst/parent-of? copy1-root' copy1-child')))) (t/is (ctst/parent-of? copy1-root' copy1-child'))))
(t/deftest test-instantiate-component-from-lib (t/deftest test-instantiate-component-from-lib
@ -489,8 +476,8 @@
(t/is (some? copy1-child')) (t/is (some? copy1-child'))
(t/is (ctk/instance-root? copy1-root')) (t/is (ctk/instance-root? copy1-root'))
(t/is (ctk/instance-of? copy1-root' (:id library) (:id component'))) (t/is (ctk/instance-of? copy1-root' (:id library) (:id component')))
(t/is (ctk/is-main-of? main1-root' copy1-root' true)) (t/is (ctk/is-main-of? main1-root' copy1-root'))
(t/is (ctk/is-main-of? main1-child' copy1-child' true)) (t/is (ctk/is-main-of? main1-child' copy1-child'))
(t/is (ctst/parent-of? copy1-root' copy1-child')))) (t/is (ctst/parent-of? copy1-root' copy1-child'))))
(t/deftest test-instantiate-nested-component (t/deftest test-instantiate-nested-component
@ -533,8 +520,8 @@
(t/is (some? copy1-child')) (t/is (some? copy1-child'))
(t/is (ctk/instance-root? copy1-root')) (t/is (ctk/instance-root? copy1-root'))
(t/is (ctk/instance-of? copy1-root' (:id file') (:id component'))) (t/is (ctk/instance-of? copy1-root' (:id file') (:id component')))
(t/is (ctk/is-main-of? main1-root' copy1-root' true)) (t/is (ctk/is-main-of? main1-root' copy1-root'))
(t/is (ctk/is-main-of? main1-child' copy1-child' true)) (t/is (ctk/is-main-of? main1-child' copy1-child'))
(t/is (ctst/parent-of? copy1-root' copy1-child')))) (t/is (ctst/parent-of? copy1-root' copy1-child'))))
(t/deftest test-instantiate-nested-component-from-lib (t/deftest test-instantiate-nested-component-from-lib
@ -580,8 +567,8 @@
(t/is (some? copy1-child')) (t/is (some? copy1-child'))
(t/is (ctk/instance-root? copy1-root')) (t/is (ctk/instance-root? copy1-root'))
(t/is (ctk/instance-of? copy1-root' (:id library) (:id component'))) (t/is (ctk/instance-of? copy1-root' (:id library) (:id component')))
(t/is (ctk/is-main-of? main1-root' copy1-root' true)) (t/is (ctk/is-main-of? main1-root' copy1-root'))
(t/is (ctk/is-main-of? main1-child' copy1-child' true)) (t/is (ctk/is-main-of? main1-child' copy1-child'))
(t/is (ctst/parent-of? copy1-root' copy1-child')))) (t/is (ctst/parent-of? copy1-root' copy1-child'))))
(t/deftest test-detach-copy (t/deftest test-detach-copy

View file

@ -47,8 +47,7 @@
file-mdf file-mdf
{(:id file-mdf) file-mdf} {(:id file-mdf) file-mdf}
page-mdf page-mdf
(:id copy-root) (:id copy-root))
true)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -99,8 +98,7 @@
{(:id file-mdf) file-mdf {(:id file-mdf) file-mdf
(:id library) library} (:id library) library}
page-mdf page-mdf
(:id copy-root) (:id copy-root))
true)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -151,8 +149,7 @@
file-mdf file-mdf
{(:id file-mdf) file-mdf} {(:id file-mdf) file-mdf}
page-mdf page-mdf
(:id copy-root) (:id copy-root))
true)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -198,8 +195,7 @@
file-mdf file-mdf
{(:id file-mdf) file-mdf} {(:id file-mdf) file-mdf}
page-mdf page-mdf
(:id copy-root) (:id copy-root))
true)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -246,8 +242,7 @@
file-mdf file-mdf
{(:id file-mdf) file-mdf} {(:id file-mdf) file-mdf}
page-mdf page-mdf
(:id copy-root) (:id copy-root))
true)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -291,8 +286,7 @@
file-mdf file-mdf
{(:id file-mdf) file-mdf} {(:id file-mdf) file-mdf}
page-mdf page-mdf
(:id copy2-root) (:id copy2-root))
true)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)
@ -338,8 +332,7 @@
file-mdf file-mdf
{(:id file-mdf) file-mdf} {(:id file-mdf) file-mdf}
page-mdf page-mdf
(:id copy2-root) (:id copy2-root))
true)
file' (thf/apply-changes file changes) file' (thf/apply-changes file changes)

View file

@ -227,7 +227,7 @@
(t/is (= (:touched copy-root') nil)) (t/is (= (:touched copy-root') nil))
(t/is (= (:touched copy-new-child') nil)) (t/is (= (:touched copy-new-child') nil))
(t/is (ctst/parent-of? copy-root' copy-new-child')) (t/is (ctst/parent-of? copy-root' copy-new-child'))
(t/is (ctk/is-main-of? main-free-shape' copy-new-child' true)))) (t/is (ctk/is-main-of? main-free-shape' copy-new-child'))))
(t/deftest test-sync-when-deleting-shape (t/deftest test-sync-when-deleting-shape
(let [;; ==== Setup (let [;; ==== Setup

View file

@ -54,7 +54,7 @@
(t/is (= (count components') 1)) (t/is (= (count components') 1))
(t/is (ctk/instance-of? copy-root' (:id file') (:id component'))) (t/is (ctk/instance-of? copy-root' (:id file') (:id component')))
(t/is (ctk/is-main-of? main-root' copy-root' true)) (t/is (ctk/is-main-of? main-root' copy-root'))
(t/is (ctk/main-instance-of? (:id main-root') (:id (second pages')) component')))) (t/is (ctk/main-instance-of? (:id main-root') (:id (second pages')) component'))))
(t/deftest absorb-colors (t/deftest absorb-colors

View file

@ -582,7 +582,6 @@
component component
fdata fdata
(gpt/point (:x shape) (:y shape)) (gpt/point (:x shape) (:y shape))
true
{:keep-ids? true :force-frame-id (:frame-id shape)}) {:keep-ids? true :force-frame-id (:frame-id shape)})
children (into {} (map (fn [shape] [(:id shape) shape]) new-shapes)) children (into {} (map (fn [shape] [(:id shape) shape]) new-shapes))
objs (assoc objs id new-shape)] objs (assoc objs id new-shape)]

View file

@ -395,9 +395,9 @@
(defn- add-component2 (defn- add-component2
"This is the second step of the component creation." "This is the second step of the component creation."
([selected components-v2] ([selected]
(add-component2 nil selected components-v2)) (add-component2 nil selected))
([id-ref selected components-v2] ([id-ref selected]
(ptk/reify ::add-component2 (ptk/reify ::add-component2
ev/Event ev/Event
(-data [_] (-data [_]
@ -413,8 +413,7 @@
parents (into #{} (map :parent-id) shapes)] parents (into #{} (map :parent-id) shapes)]
(when-not (empty? shapes) (when-not (empty? shapes)
(let [[root component-id changes] (let [[root component-id changes]
(cll/generate-add-component (pcb/empty-changes it) shapes objects page-id file-id components-v2 (cll/generate-add-component (pcb/empty-changes it) shapes objects page-id file-id
dwg/prepare-create-group
cfsh/prepare-create-artboard-from-selection)] cfsh/prepare-create-artboard-from-selection)]
(when id-ref (when id-ref
(reset! id-ref component-id)) (reset! id-ref component-id))
@ -439,12 +438,11 @@
selected (->> (d/nilv ids (dsh/lookup-selected state)) selected (->> (d/nilv ids (dsh/lookup-selected state))
(cfh/clean-loops objects)) (cfh/clean-loops objects))
selected-objects (map #(get objects %) selected) selected-objects (map #(get objects %) selected)
components-v2 (features/active-feature? state "components/v2")
;; We don't want to change the structure of component copies ;; We don't want to change the structure of component copies
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects))] can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects))]
(when can-make-component (when can-make-component
(rx/of (add-component2 id-ref selected components-v2)))))))) (rx/of (add-component2 id-ref selected))))))))
(defn add-multiple-components (defn add-multiple-components
"Add several new components to current file library, from the currently selected shapes." "Add several new components to current file library, from the currently selected shapes."
@ -452,15 +450,14 @@
(ptk/reify ::add-multiple-components (ptk/reify ::add-multiple-components
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [components-v2 (features/active-feature? state "components/v2") (let [objects (dsh/lookup-page-objects state)
objects (dsh/lookup-page-objects state)
selected (->> (dsh/lookup-selected state) selected (->> (dsh/lookup-selected state)
(cfh/clean-loops objects)) (cfh/clean-loops objects))
selected-objects (map #(get objects %) selected) selected-objects (map #(get objects %) selected)
;; We don't want to change the structure of component copies ;; We don't want to change the structure of component copies
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects)) can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) selected-objects))
added-components (map (fn [id] added-components (map (fn [id]
(with-meta (add-component2 [id] components-v2) (with-meta (add-component2 [id])
{:multiple true})) {:multiple true}))
selected) selected)
undo-id (js/Symbol)] undo-id (js/Symbol)]
@ -489,7 +486,7 @@
(rx/empty) (rx/empty)
(let [data (dsh/lookup-file-data state) (let [data (dsh/lookup-file-data state)
changes (-> (pcb/empty-changes it) changes (-> (pcb/empty-changes it)
(cll/generate-rename-component id new-name data true))] (cll/generate-rename-component id new-name data))]
(rx/of (dch/commit-changes changes)))))))) (rx/of (dch/commit-changes changes))))))))
(defn rename-component-and-main-instance (defn rename-component-and-main-instance
@ -512,7 +509,6 @@
(rx/concat (rx/concat
(rx/of (rename-component component-id clean-name)) (rx/of (rename-component component-id clean-name))
;; NOTE: only when components-v2 is enabled
(when (and shape-id page-id) (when (and shape-id page-id)
(rx/of (dwsh/update-shapes [shape-id] #(assoc % :name clean-name) {:page-id page-id :stack-undo? true})))))))))) (rx/of (dwsh/update-shapes [shape-id] #(assoc % :name clean-name) {:page-id page-id :stack-undo? true}))))))))))
@ -526,11 +522,10 @@
(watch [it state _] (watch [it state _]
(let [libraries (dsh/lookup-libraries state) (let [libraries (dsh/lookup-libraries state)
library (get libraries library-id) library (get libraries library-id)
components-v2 (features/active-feature? state "components/v2")
[main-instance changes] [main-instance changes]
(-> (pcb/empty-changes it nil) (-> (pcb/empty-changes it nil)
(cll/generate-duplicate-component library component-id new-component-id components-v2))] (cll/generate-duplicate-component library component-id new-component-id))]
(rx/of (rx/of
(ptk/data-event :layout/update {:ids [(:id main-instance)]}) (ptk/data-event :layout/update {:ids [(:id main-instance)]})
(dch/commit-changes changes))))))) (dch/commit-changes changes)))))))
@ -560,8 +555,7 @@
[all-parents changes] [all-parents changes]
(-> (pcb/empty-changes it page-id) (-> (pcb/empty-changes it page-id)
;; Deleting main root triggers component delete ;; Deleting main root triggers component delete
(cls/generate-delete-shapes fdata page objects #{root-id} {:components-v2 true (cls/generate-delete-shapes fdata page objects #{root-id} {:undo-group undo-group
:undo-group undo-group
:undo-id undo-id}))] :undo-id undo-id}))]
(rx/of (rx/of
(dwu/start-undo-transaction undo-id) (dwu/start-undo-transaction undo-id)
@ -827,7 +821,7 @@
changes changes
(-> (pcb/empty-changes it) (-> (pcb/empty-changes it)
(cll/generate-reset-component file libraries container id true))] (cll/generate-reset-component file libraries container id))]
(log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes (log/debug :msg "RESET-COMPONENT finished" :js/rchanges (log-changes
(:redo-changes changes) (:redo-changes changes)
@ -879,7 +873,7 @@
(-> (pcb/empty-changes it) (-> (pcb/empty-changes it)
(pcb/set-undo-group undo-group) (pcb/set-undo-group undo-group)
(pcb/with-container container) (pcb/with-container container)
(cll/generate-sync-shape-inverse fdata libraries container id true)) (cll/generate-sync-shape-inverse fdata libraries container id))
ldata (->> (:component-file shape) ldata (->> (:component-file shape)
(dsh/lookup-file-data state)) (dsh/lookup-file-data state))
@ -1269,10 +1263,8 @@
[] []
(ptk/reify ::watch-component-changes (ptk/reify ::watch-component-changes
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ _ stream]
(let [components-v2? (features/active-feature? state "components/v2") (let [stopper-s
stopper-s
(->> stream (->> stream
(rx/filter #(or (= ::dw/finalize-page (ptk/type %)) (rx/filter #(or (= ::dw/finalize-page (ptk/type %))
(= ::watch-component-changes (ptk/type %))))) (= ::watch-component-changes (ptk/type %)))))
@ -1335,7 +1327,7 @@
(rx/debounce 5000) (rx/debounce 5000)
(rx/tap #(log/trc :hint "buffer initialized")))] (rx/tap #(log/trc :hint "buffer initialized")))]
(when (and components-v2? (contains? cf/flags :component-thumbnails)) (when (contains? cf/flags :component-thumbnails)
(->> (rx/merge (->> (rx/merge
changes-s changes-s

View file

@ -24,7 +24,6 @@
[app.main.data.helpers :as dsh] [app.main.data.helpers :as dsh]
[app.main.data.media :as dmm] [app.main.data.media :as dmm]
[app.main.data.notifications :as ntf] [app.main.data.notifications :as ntf]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.shapes :as dwsh] [app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.svg-upload :as svg] [app.main.data.workspace.svg-upload :as svg]
[app.main.repo :as rp] [app.main.repo :as rp]
@ -235,16 +234,6 @@
(rx/catch #(handle-media-error % on-error)) (rx/catch #(handle-media-error % on-error))
(rx/finalize #(st/emit! (ntf/hide :tag :media-loading)))))))) (rx/finalize #(st/emit! (ntf/hide :tag :media-loading))))))))
;; Deprecated in components-v2
(defn upload-media-asset
[params]
(let [params (assoc params
:force-media true
:local? false
:on-image #(st/emit! (dwl/add-media %))
:on-svg #(st/emit! (dwl/add-media %)))]
(process-media-objects params)))
(defn upload-media-workspace (defn upload-media-workspace
[{:keys [position file-id] :as params}] [{:keys [position file-id] :as params}]
(let [params (assoc params (let [params (assoc params
@ -378,7 +367,7 @@
(defn- add-shapes-and-component (defn- add-shapes-and-component
[it file-data page name [shape children]] [it file-data page name [shape children]]
(let [[component-shape component-shapes updated-shapes] (let [[component-shape updated-shapes]
(ctn/convert-shape-in-component shape children (:id file-data)) (ctn/convert-shape-in-component shape children (:id file-data))
changes (-> (pcb/empty-changes it) changes (-> (pcb/empty-changes it)
@ -389,7 +378,6 @@
(pcb/add-component (:id component-shape) (pcb/add-component (:id component-shape)
"" ""
name name
component-shapes
updated-shapes updated-shapes
(:id shape) (:id shape)
(:id page)))] (:id page)))]

View file

@ -24,7 +24,6 @@
[app.main.data.workspace.edition :as dwe] [app.main.data.workspace.edition :as dwe]
[app.main.data.workspace.selection :as dws] [app.main.data.workspace.selection :as dws]
[app.main.data.workspace.undo :as dwu] [app.main.data.workspace.undo :as dwu]
[app.main.features :as features]
[beicon.v2.core :as rx] [beicon.v2.core :as rx]
[potok.v2.core :as ptk])) [potok.v2.core :as ptk]))
@ -171,12 +170,10 @@
page (dsh/get-page fdata page-id) page (dsh/get-page fdata page-id)
objects (:objects page) objects (:objects page)
components-v2 (features/active-feature? state "components/v2")
undo-id (or (:undo-id options) (js/Symbol)) undo-id (or (:undo-id options) (js/Symbol))
[all-parents changes] (-> (pcb/empty-changes it (:id page)) [all-parents changes] (-> (pcb/empty-changes it (:id page))
(cls/generate-delete-shapes fdata page objects ids (cls/generate-delete-shapes fdata page objects ids
{:components-v2 components-v2 {:ignore-touched (:component-swap options)
:ignore-touched (:component-swap options)
:undo-group (:undo-group options) :undo-group (:undo-group options)
:undo-id undo-id}))] :undo-id undo-id}))]

View file

@ -260,6 +260,14 @@
(let [message (tr "errors.feature-not-supported" (:feature error))] (let [message (tr "errors.feature-not-supported" (:feature error))]
(st/emit! (modal/show {:type :alert :message message}))) (st/emit! (modal/show {:type :alert :message message})))
(= :file-in-components-v1 code)
(st/emit! (modal/show {:type :alert
:message (tr "errors.deprecated")
:link-message {:before (tr "errors.deprecated.contact.before")
:text (tr "errors.deprecated.contact.text")
:after (tr "errors.deprecated.contact.after")
:on-click #(st/emit! (rt/nav :settings-feedback))}}))
:else :else
(print-cause! "Restriction Error" error))) (print-cause! "Restriction Error" error)))

View file

@ -9,6 +9,7 @@
(:require (:require
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.link :as lk]
[app.main.ui.icons :as i] [app.main.ui.icons :as i]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -21,6 +22,7 @@
::mf/register-as :alert} ::mf/register-as :alert}
[{:keys [message [{:keys [message
scd-message scd-message
link-message
title title
on-accept on-accept
hint hint
@ -59,8 +61,16 @@
[:div {:class (stl/css :modal-content)} [:div {:class (stl/css :modal-content)}
(when (and (string? message) (not= message "")) (when (and (string? message) (not= message ""))
[:h3 {:class (stl/css :modal-msg)} message]) [:h3 {:class (stl/css :modal-msg)} message])
(when (seq link-message)
[:h3 {:class (stl/css :modal-msg)}
[:span (:before link-message)]
[:& lk/link {:action (:on-click link-message)
:class (stl/css :link)}
(:text link-message)]
[:span (:after link-message)]])
(when (and (string? scd-message) (not= scd-message "")) (when (and (string? scd-message) (not= scd-message ""))
[:h3 {:class (stl/css :modal-scd-msg)} scd-message]) [:h3 {:class (stl/css :modal-scd-msg)} scd-message])
(when (string? hint) (when (string? hint)
[:p {:class (stl/css :modal-hint)} hint])] [:p {:class (stl/css :modal-hint)} hint])]

View file

@ -8,10 +8,12 @@
.modal-overlay { .modal-overlay {
@extend .modal-overlay-base; @extend .modal-overlay-base;
&.transparent { &.transparent {
background-color: transparent; background-color: transparent;
} }
} }
.modal-container { .modal-container {
@extend .modal-container-base; @extend .modal-container-base;
} }
@ -48,6 +50,7 @@
.accept-btn { .accept-btn {
@extend .modal-accept-btn; @extend .modal-accept-btn;
&.danger { &.danger {
@extend .modal-danger-btn; @extend .modal-danger-btn;
} }
@ -60,3 +63,15 @@
color: var(--modal-text-foreground-color); color: var(--modal-text-foreground-color);
line-height: 1.5; line-height: 1.5;
} }
.link {
color: var(--color-accent-primary);
}
.link::before {
content: " ";
}
.link::after {
content: " ";
}

View file

@ -23,7 +23,6 @@
(def render-thumbnails (mf/create-context nil)) (def render-thumbnails (mf/create-context nil))
(def libraries (mf/create-context nil)) (def libraries (mf/create-context nil))
(def components-v2 (mf/create-context nil))
(def design-tokens (mf/create-context nil)) (def design-tokens (mf/create-context nil))
(def current-scroll (mf/create-context nil)) (def current-scroll (mf/create-context nil))

View file

@ -159,7 +159,7 @@
[:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space [:span {:class (stl/css :num-assets)} (str "\u00A0(") (:count components) ")"]] ;; Unicode 00A0 is non-breaking space
[:div {:class (stl/css :asset-list)} [:div {:class (stl/css :asset-list)}
(for [component (:sample components)] (for [component (:sample components)]
(let [root-id (or (:main-instance-id component) (:id component))] ;; Check for components-v2 in library (let [root-id (:main-instance-id component)]
[:div {:class (stl/css :asset-list-item) [:div {:class (stl/css :asset-list-item)
:key (str "assets-component-" (:id component))} :key (str "assets-component-" (:id component))}
[:& render/component-svg {:root-shape (get-in component [:objects root-id]) [:& render/component-svg {:root-shape (get-in component [:objects root-id])

View file

@ -200,7 +200,6 @@
[:> (mf/provider ctx/current-project-id) {:value project-id} [:> (mf/provider ctx/current-project-id) {:value project-id}
[:> (mf/provider ctx/current-file-id) {:value file-id} [:> (mf/provider ctx/current-file-id) {:value file-id}
[:> (mf/provider ctx/current-page-id) {:value page-id} [:> (mf/provider ctx/current-page-id) {:value page-id}
[:> (mf/provider ctx/components-v2) {:value true}
[:> (mf/provider ctx/design-tokens) {:value design-tokens?} [:> (mf/provider ctx/design-tokens) {:value design-tokens?}
[:> (mf/provider ctx/workspace-read-only?) {:value read-only?} [:> (mf/provider ctx/workspace-read-only?) {:value read-only?}
[:> modal-container*] [:> modal-container*]
@ -216,4 +215,4 @@
:file file :file file
:wglobal wglobal :wglobal wglobal
:layout layout}] :layout layout}]
[:> workspace-loader*])]]]]]]])) [:> workspace-loader*])]]]]]]))

View file

@ -555,7 +555,7 @@
objects (deref refs/workspace-page-objects) objects (deref refs/workspace-page-objects)
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) shapes)) can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) shapes))
heads (filter ctk/instance-head? shapes) heads (filter ctk/instance-head? shapes)
components-menu-entries (cmm/generate-components-menu-entries heads true) components-menu-entries (cmm/generate-components-menu-entries heads)
variant-container? (and single? (ctk/is-variant-container? (first shapes))) variant-container? (and single? (ctk/is-variant-container? (first shapes)))
do-add-component #(st/emit! (dwl/add-component)) do-add-component #(st/emit! (dwl/add-component))
do-add-multiple-components #(st/emit! (dwl/add-multiple-components)) do-add-multiple-components #(st/emit! (dwl/add-multiple-components))

View file

@ -75,8 +75,7 @@
{::mf/wrap [mf/memo] {::mf/wrap [mf/memo]
::mf/wrap-props false} ::mf/wrap-props false}
[{:keys [size file-id]}] [{:keys [size file-id]}]
(let [components-v2 (mf/use-ctx ctx/components-v2) (let [read-only? (mf/use-ctx ctx/workspace-read-only?)
read-only? (mf/use-ctx ctx/workspace-read-only?)
filters* (mf/use-state filters* (mf/use-state
{:term "" {:term ""
:section "all" :section "all"
@ -148,11 +147,6 @@
:id "components" :id "components"
:handler on-section-filter-change} :handler on-section-filter-change}
(when (not components-v2)
{:name (tr "workspace.assets.graphics")
:id "graphics"
:handler on-section-filter-change})
{:name (tr "workspace.assets.colors") {:name (tr "workspace.assets.colors")
:id "colors" :id "colors"
:handler on-section-filter-change} :handler on-section-filter-change}

View file

@ -322,7 +322,7 @@
:is-hidden is-hidden}]))) :is-hidden is-hidden}])))
(defn generate-components-menu-entries (defn generate-components-menu-entries
[shapes components-v2] [shapes]
(let [multi (> (count shapes) 1) (let [multi (> (count shapes) 1)
copies (filter ctk/in-component-copy? shapes) copies (filter ctk/in-component-copy? shapes)
@ -350,13 +350,13 @@
touched-not-dangling (filter #(and (cfh/component-touched? objects (:id %)) touched-not-dangling (filter #(and (cfh/component-touched? objects (:id %))
(find-component % false)) copies) (find-component % false)) copies)
can-reset-overrides? (or (not components-v2) (seq touched-not-dangling)) can-reset-overrides? (seq touched-not-dangling)
;; For when it's only one shape ;; For when it's only one shape
shape (first shapes) shape (first shapes)
id (:id shape) id (:id shape)
main-instance? (if components-v2 (ctk/main-instance? shape) true) main-instance? (ctk/main-instance? shape)
component-id (:component-id shape) component-id (:component-id shape)
library-id (:component-file shape) library-id (:component-file shape)
@ -372,10 +372,9 @@
can-update-main? (and (not multi) can-update-main? (and (not multi)
(not is-dangling?) (not is-dangling?)
(or (not components-v2)
(and (not main-instance?) (and (not main-instance?)
(not (ctn/has-any-copy-parent? objects shape)) (not (ctn/has-any-copy-parent? objects shape))
(cfh/component-touched? objects (:id shape))))) (cfh/component-touched? objects (:id shape))))
can-detach? (and (seq copies) can-detach? (and (seq copies)
(every? #(not (ctn/has-any-copy-parent? objects %)) copies)) (every? #(not (ctn/has-any-copy-parent? objects %)) copies))
@ -450,7 +449,7 @@
menu-entries [(when (and (not multi) main-instance?) menu-entries [(when (and (not multi) main-instance?)
{:title (tr "workspace.shape.menu.show-in-assets") {:title (tr "workspace.shape.menu.show-in-assets")
:action do-show-in-assets}) :action do-show-in-assets})
(when (and (not multi) main-instance? local-component? lacks-annotation? components-v2) (when (and (not multi) main-instance? local-component? lacks-annotation?)
{:title (tr "workspace.shape.menu.create-annotation") {:title (tr "workspace.shape.menu.create-annotation")
:action do-create-annotation}) :action do-create-annotation})
(when can-detach? (when can-detach?
@ -462,7 +461,7 @@
(when can-reset-overrides? (when can-reset-overrides?
{:title (tr "workspace.shape.menu.reset-overrides") {:title (tr "workspace.shape.menu.reset-overrides")
:action do-reset-component}) :action do-reset-component})
(when (and (seq restorable-copies) components-v2) (when (seq restorable-copies)
{:title (tr "workspace.shape.menu.restore-main") {:title (tr "workspace.shape.menu.restore-main")
:action do-restore-component}) :action do-restore-component})
(when can-show-component? (when can-show-component?

View file

@ -308,7 +308,6 @@
menu-state (mf/use-state cmm/initial-context-menu-state) menu-state (mf/use-state cmm/initial-context-menu-state)
read-only? (mf/use-ctx ctx/workspace-read-only?) read-only? (mf/use-ctx ctx/workspace-read-only?)
components-v2 (mf/use-ctx ctx/components-v2)
toggle-list-style (mf/use-ctx cmm/assets-toggle-list-style) toggle-list-style (mf/use-ctx cmm/assets-toggle-list-style)
selected (:components selected) selected (:components selected)
@ -521,7 +520,7 @@
:title (tr "workspace.assets.grid-view") :title (tr "workspace.assets.grid-view")
:id "opt-grid"}]]]) :id "opt-grid"}]]])
(when (and components-v2 (not read-only?) is-local) (when (and (not read-only?) is-local)
[:> icon-button* {:variant "ghost" [:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.assets.components.add-component") :aria-label (tr "workspace.assets.components.add-component")
:on-click add-component :on-click add-component
@ -561,9 +560,7 @@
:id "assets-rename-component" :id "assets-rename-component"
:handler on-rename}) :handler on-rename})
(when (and is-local (not (or multi-assets? read-only? any-variant?))) (when (and is-local (not (or multi-assets? read-only? any-variant?)))
{:name (if components-v2 {:name (tr "workspace.assets.duplicate-main")
(tr "workspace.assets.duplicate-main")
(tr "workspace.assets.duplicate"))
:id "assets-duplicate-component" :id "assets-duplicate-component"
:handler on-duplicate}) :handler on-duplicate})
@ -576,7 +573,7 @@
:id "assets-group-component" :id "assets-group-component"
:handler on-group}) :handler on-group})
(when (and components-v2 (not multi-assets?)) (when (not multi-assets?)
{:name (tr "workspace.shape.menu.show-main") {:name (tr "workspace.shape.menu.show-main")
:id "assets-show-main-component" :id "assets-show-main-component"
:handler on-show-main})]}]]])) :handler on-show-main})]}]]]))

View file

@ -24,7 +24,6 @@
[app.main.ui.workspace.sidebar.assets.colors :refer [colors-section]] [app.main.ui.workspace.sidebar.assets.colors :refer [colors-section]]
[app.main.ui.workspace.sidebar.assets.common :as cmm] [app.main.ui.workspace.sidebar.assets.common :as cmm]
[app.main.ui.workspace.sidebar.assets.components :refer [components-section]] [app.main.ui.workspace.sidebar.assets.components :refer [components-section]]
[app.main.ui.workspace.sidebar.assets.graphics :refer [graphics-section]]
[app.main.ui.workspace.sidebar.assets.typographies :refer [typographies-section]] [app.main.ui.workspace.sidebar.assets.typographies :refer [typographies-section]]
[app.util.dom :as dom] [app.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]] [app.util.i18n :as i18n :refer [tr]]
@ -145,11 +144,10 @@
(mf/defc file-library-content* (mf/defc file-library-content*
{::mf/private true} {::mf/private true}
[{:keys [file is-local is-loaded open-status-ref on-clear-selection filters colors media typographies components count-variants]}] [{:keys [file is-local is-loaded open-status-ref on-clear-selection filters colors typographies components count-variants]}]
(let [open-status (mf/deref open-status-ref) (let [open-status (mf/deref open-status-ref)
file-id (:id file) file-id (:id file)
project-id (:project-id file)
filters-section (:section filters) filters-section (:section filters)
has-filters-term? (not ^boolean (str/empty? (:term filters))) has-filters-term? (not ^boolean (str/empty? (:term filters)))
@ -165,11 +163,6 @@
(or (pos? (count components)) (or (pos? (count components))
(not has-filters-term?))) (not has-filters-term?)))
show-graphics?
(and (or (= filters-section "all")
(= filters-section "graphics"))
(pos? (count media)))
show-colors? show-colors?
(and (or (= filters-section "all") (and (or (= filters-section "all")
(= filters-section "colors")) (= filters-section "colors"))
@ -188,9 +181,6 @@
force-open-colors? force-open-colors?
(when ^boolean has-filters-term? (> 60 (count colors))) (when ^boolean has-filters-term? (> 60 (count colors)))
force-open-graphics?
(when ^boolean has-filters-term? (> 60 (count media)))
force-open-typographies? force-open-typographies?
(when ^boolean has-filters-term? (> 60 (count typographies))) (when ^boolean has-filters-term? (> 60 (count typographies)))
@ -214,9 +204,6 @@
on-component-click on-component-click
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :components)) (mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :components))
on-graphics-click
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :graphics))
on-colors-click on-colors-click
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :colors)) (mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :colors))
@ -266,23 +253,6 @@
:on-clear-selection on-clear-selection :on-clear-selection on-clear-selection
:count-variants count-variants}]) :count-variants count-variants}])
(when ^boolean show-graphics?
[:& graphics-section
{:file-id file-id
:project-id project-id
:local? is-local
:objects media
:listing-thumbs? listing-thumbs?
:open? (or ^boolean force-open-graphics?
^boolean (get open-status :graphics false))
:force-open? force-open-graphics?
:open-status-ref open-status-ref
:reverse-sort? reverse-sort?
:selected selected
:on-asset-click on-graphics-click
:on-assets-delete on-assets-delete
:on-clear-selection on-clear-selection}])
(when ^boolean show-colors? (when ^boolean show-colors?
[:& colors-section [:& colors-section
{:file-id file-id {:file-id file-id
@ -315,7 +285,6 @@
:on-clear-selection on-clear-selection}]) :on-clear-selection on-clear-selection}])
(when (and (not ^boolean show-components?) (when (and (not ^boolean show-components?)
(not ^boolean show-graphics?)
(not ^boolean show-colors?) (not ^boolean show-colors?)
(not ^boolean show-typography?)) (not ^boolean show-typography?))
[:div {:class (stl/css :asset-title)} [:div {:class (stl/css :asset-title)}
@ -333,7 +302,6 @@
library (use-library-ref file-id) library (use-library-ref file-id)
colors (:colors library) colors (:colors library)
media (:media library)
typographies (:typographies library) typographies (:typographies library)
filters-term (:term filters) filters-term (:term filters)
@ -350,11 +318,6 @@
(cmm/apply-filters $ filters) (cmm/apply-filters $ filters)
(remove #(cfv/is-secondary-variant? % library) $))) (remove #(cfv/is-secondary-variant? % library) $)))
filtered-media
(mf/with-memo [filters media]
(-> (vals media)
(cmm/apply-filters filters)))
filtered-typographies filtered-typographies
(mf/with-memo [filters typographies] (mf/with-memo [filters typographies]
(-> (vals typographies) (-> (vals typographies)
@ -372,7 +335,6 @@
(and (not (str/blank? filters-term)) (and (not (str/blank? filters-term))
(or (> 60 (count filtered-colors)) (or (> 60 (count filtered-colors))
(> 60 (count filtered-components)) (> 60 (count filtered-components))
(> 60 (count filtered-media))
(> 60 (count filtered-typographies)))) (> 60 (count filtered-typographies))))
open? open?
@ -415,7 +377,6 @@
:filters filters :filters filters
:colors filtered-colors :colors filtered-colors
:components filtered-components :components filtered-components
:media filtered-media
:typographies filtered-typographies :typographies filtered-typographies
:on-clear-selection unselect-all :on-clear-selection unselect-all
:open-status-ref open-status-ref :open-status-ref open-status-ref

View file

@ -1,432 +0,0 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) KALEIDOS INC
(ns app.main.ui.workspace.sidebar.assets.graphics
(:require-macros [app.main.style :as stl])
(:require
[app.common.data :as d]
[app.common.data.macros :as dm]
[app.common.files.helpers :as cfh]
[app.common.media :as cm]
[app.config :as cf]
[app.main.data.event :as ev]
[app.main.data.modal :as modal]
[app.main.data.workspace :as dw]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.media :as dwm]
[app.main.data.workspace.undo :as dwu]
[app.main.store :as st]
[app.main.ui.components.editable-label :refer [editable-label]]
[app.main.ui.components.file-uploader :refer [file-uploader]]
[app.main.ui.context :as ctx]
[app.main.ui.hooks :as h]
[app.main.ui.icons :as i]
[app.main.ui.workspace.sidebar.assets.common :as cmm]
[app.main.ui.workspace.sidebar.assets.groups :as grp]
[app.util.dom :as dom]
[app.util.dom.dnd :as dnd]
[app.util.i18n :as i18n :refer [tr]]
[cuerdas.core :as str]
[okulary.core :as l]
[potok.v2.core :as ptk]
[rumext.v2 :as mf]))
(mf/defc graphics-item
[{:keys [object renaming listing-thumbs? selected-objects file-id
on-asset-click on-context-menu on-drag-start do-rename cancel-rename
selected-full selected-graphics-paths]}]
(let [item-ref (mf/use-ref)
visible? (h/use-visible item-ref :once? true)
object-id (:id object)
dragging* (mf/use-state false)
dragging? (deref dragging*)
read-only? (mf/use-ctx ctx/workspace-read-only?)
on-drop
(mf/use-fn
(mf/deps object dragging* selected-objects selected-full selected-graphics-paths)
(fn [event]
(cmm/on-drop-asset event object dragging* selected-objects selected-full
selected-graphics-paths dwl/rename-media)))
on-drag-enter
(mf/use-fn
(mf/deps object dragging* selected-objects selected-graphics-paths)
(fn [event]
(cmm/on-drag-enter-asset event object dragging* selected-objects selected-graphics-paths)))
on-drag-leave
(mf/use-fn
(mf/deps dragging*)
(fn [event]
(cmm/on-drag-leave-asset event dragging*)))
on-grahic-drag-start
(mf/use-fn
(mf/deps object file-id selected-objects item-ref on-drag-start read-only?)
(fn [event]
(if read-only?
(dom/prevent-default event)
(cmm/on-asset-drag-start event file-id object selected-objects item-ref :graphics on-drag-start))))
on-context-menu
(mf/use-fn
(mf/deps object-id)
(partial on-context-menu object-id))
on-asset-click
(mf/use-fn
(mf/deps object-id on-asset-click)
(fn [event]
(on-asset-click event object-id)))]
[:div {:ref item-ref
:class-name (stl/css-case
:selected (contains? selected-objects object-id)
:grid-cell listing-thumbs?
:enum-item (not listing-thumbs?))
:draggable (not read-only?)
:on-click on-asset-click
:on-context-menu on-context-menu
:on-drag-start on-grahic-drag-start
:on-drag-enter on-drag-enter
:on-drag-leave on-drag-leave
:on-drag-over dom/prevent-default
:on-drop on-drop}
(when visible?
[:*
[:img {:src (when visible? (cf/resolve-file-media object true))
:class (stl/css :graphic-image)
:draggable false}] ;; Also need to add css pointer-events: none
(let [renaming? (= renaming (:id object))]
[:*
[:& editable-label
{:class (stl/css-case
:cell-name listing-thumbs?
:item-name (not listing-thumbs?)
:editing renaming?)
:value (cfh/merge-path-item (:path object) (:name object))
:tooltip (cfh/merge-path-item (:path object) (:name object))
:display-value (:name object)
:editing renaming?
:disable-dbl-click true
:on-change do-rename
:on-cancel cancel-rename}]
(when ^boolean dragging?
[:div {:class (stl/css :dragging)}])])])]))
(mf/defc graphics-group
[{:keys [file-id prefix groups open-groups force-open? renaming listing-thumbs? selected-objects on-asset-click
on-drag-start do-rename cancel-rename on-rename-group on-ungroup
on-context-menu selected-full]}]
(let [group-open? (get open-groups prefix true)
dragging* (mf/use-state false)
dragging? (deref dragging*)
selected-paths
(mf/with-memo [selected-full]
(into #{}
(comp (map :path) (d/nilv ""))
selected-full))
on-drag-enter
(mf/use-fn
(mf/deps dragging* prefix selected-paths)
(fn [event]
(cmm/on-drag-enter-asset-group event dragging* prefix selected-paths)))
on-drag-leave
(mf/use-fn
(mf/deps dragging*)
(fn [event]
(cmm/on-drag-leave-asset event dragging*)))
on-drop
(mf/use-fn
(mf/deps dragging* prefix selected-paths selected-full)
(fn [event]
(cmm/on-drop-asset-group event dragging* prefix selected-paths selected-full dwl/rename-media)))]
[:div {:class (stl/css :graphics-group)
:on-drag-enter on-drag-enter
:on-drag-leave on-drag-leave
:on-drag-over dom/prevent-default
:on-drop on-drop}
[:& grp/asset-group-title
{:file-id file-id
:section :graphics
:path prefix
:group-open? group-open?
:on-rename on-rename-group
:on-ungroup on-ungroup}]
(when group-open?
[:*
(let [objects (get groups "" [])]
[:div {:class-name (stl/css-case
:asset-grid listing-thumbs?
:asset-enum (not listing-thumbs?)
:drop-space (and
(empty? objects)
(some? groups)
(not dragging?)))
:on-drag-enter on-drag-enter
:on-drag-leave on-drag-leave
:on-drag-over dom/prevent-default
:on-drop on-drop}
(when ^boolean dragging?
[:div {:class (stl/css :grid-placeholder)} "\u00A0"])
(when (and (empty? objects)
(some? groups))
[:div {:class (stl/css :drop-space)}])
(for [object objects]
[:& graphics-item
{:key (dm/str "object-" (:id object))
:file-id file-id
:object object
:renaming renaming
:listing-thumbs? listing-thumbs?
:selected-objects selected-objects
:on-asset-click on-asset-click
:on-context-menu on-context-menu
:on-drag-start on-drag-start
:do-rename do-rename
:cancel-rename cancel-rename
:selected-full selected-full
:selected-paths selected-paths}])])
(for [[path-item content] groups]
(when-not (empty? path-item)
[:& graphics-group {:file-id file-id
:key path-item
:prefix (cfh/merge-path-item prefix path-item)
:groups content
:open-groups open-groups
:force-open? force-open?
:renaming renaming
:listing-thumbs? listing-thumbs?
:selected-objects selected-objects
:on-asset-click on-asset-click
:on-drag-start on-drag-start
:do-rename do-rename
:cancel-rename cancel-rename
:on-rename-group on-rename-group
:on-ungroup on-ungroup
:on-context-menu on-context-menu
:selected-full selected-full
:selected-paths selected-paths}]))])]))
(mf/defc graphics-section
{::mf/wrap-props false}
[{:keys [file-id project-id local? objects listing-thumbs? open? force-open? open-status-ref selected reverse-sort?
on-asset-click on-assets-delete on-clear-selection]}]
(let [input-ref (mf/use-ref nil)
state (mf/use-state {:renaming nil :object-id nil})
menu-state (mf/use-state cmm/initial-context-menu-state)
read-only? (mf/use-ctx ctx/workspace-read-only?)
open-groups-ref (mf/with-memo [open-status-ref]
(-> (l/in [:groups :graphics])
(l/derived open-status-ref)))
open-groups (mf/deref open-groups-ref)
selected (:graphics selected)
selected-full (into #{} (filter #(contains? selected (:id %))) objects)
multi-objects? (> (count selected) 1)
multi-assets? (or (seq (:components selected))
(seq (:colors selected))
(seq (:typographies selected)))
objects (mf/with-memo [objects]
(mapv dwl/extract-path-if-missing objects))
groups (mf/with-memo [objects reverse-sort?]
(grp/group-assets objects reverse-sort?))
components-v2 (mf/use-ctx ctx/components-v2)
team-id (mf/use-ctx ctx/current-team-id)
add-graphic
(mf/use-fn
(fn []
(st/emit! (dw/set-assets-section-open file-id :graphics true))
(dom/click (mf/ref-val input-ref))))
on-file-selected
(mf/use-fn
(mf/deps file-id project-id team-id)
(fn [blobs]
(let [params {:file-id file-id
:blobs (seq blobs)}]
(st/emit! (dwm/upload-media-asset params)
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
:asset-type "graphics"
:file-id file-id
:project-id project-id
:team-id team-id})))))
on-delete
(mf/use-fn
(mf/deps @state multi-objects? multi-assets?)
(fn []
(if (or multi-objects? multi-assets?)
(on-assets-delete)
(st/emit! (dwl/delete-media {:id (:object-id @state)})))))
on-rename
(mf/use-fn
(fn []
(swap! state (fn [state]
(assoc state :renaming (:object-id state))))))
cancel-rename
(mf/use-fn
(fn []
(swap! state assoc :renaming nil)))
do-rename
(mf/use-fn
(mf/deps @state)
(fn [new-name]
(st/emit! (dwl/rename-media (:renaming @state) new-name))
(swap! state assoc :renaming nil)))
on-context-menu
(mf/use-fn
(mf/deps selected on-clear-selection read-only?)
(fn [object-id event]
(dom/prevent-default event)
(let [pos (dom/get-client-position event)]
(when (and local? (not read-only?))
(when-not (contains? selected object-id)
(on-clear-selection))
(swap! state assoc :object-id object-id)
(swap! menu-state cmm/open-context-menu pos)))))
on-close-menu
(mf/use-fn
(fn []
(swap! menu-state cmm/close-context-menu)))
create-group
(mf/use-fn
(mf/deps objects selected on-clear-selection (:object-id @state))
(fn [group-name]
(on-clear-selection)
(let [undo-id (js/Symbol)]
(st/emit! (dwu/start-undo-transaction undo-id))
(run! st/emit!
(->> objects
(filter #(if multi-objects?
(contains? selected (:id %))
(= (:object-id @state) (:id %))))
(map #(dwl/rename-media (:id %) (cmm/add-group % group-name)))))
(st/emit! (dwu/commit-undo-transaction undo-id)))))
rename-group
(mf/use-fn
(mf/deps objects)
(fn [path last-path]
(on-clear-selection)
(let [undo-id (js/Symbol)]
(st/emit! (dwu/start-undo-transaction undo-id))
(run! st/emit!
(->> objects
(filter #(str/starts-with? (:path %) path))
(map #(dwl/rename-media (:id %) (cmm/rename-group % path last-path)))))
(st/emit! (dwu/commit-undo-transaction undo-id)))))
on-group
(mf/use-fn
(mf/deps objects selected create-group)
(fn [event]
(dom/stop-propagation event)
(modal/show! :name-group-dialog {:accept create-group})))
on-rename-group
(mf/use-fn
(mf/deps objects)
(fn [event path last-path]
(dom/stop-propagation event)
(modal/show! :name-group-dialog {:path path
:last-path last-path
:accept rename-group})))
on-ungroup
(mf/use-fn
(mf/deps objects)
(fn [path]
(on-clear-selection)
(let [undo-id (js/Symbol)]
(st/emit! (dwu/start-undo-transaction undo-id))
(run! st/emit!
(->> objects
(filter #(str/starts-with? (:path %) path))
(map #(dwl/rename-media (:id %) (cmm/ungroup % path)))))
(st/emit! (dwu/commit-undo-transaction undo-id)))))
on-drag-start
(mf/use-fn
(fn [{:keys [name id mtype]} event]
(dnd/set-data! event "text/asset-id" (str id))
(dnd/set-data! event "text/asset-name" name)
(dnd/set-data! event "text/asset-type" mtype)
(dnd/set-allowed-effect! event "move")))
on-asset-click
(mf/use-fn (mf/deps groups on-asset-click) (partial on-asset-click groups))]
[:& cmm/asset-section {:file-id file-id
:title (tr "workspace.assets.graphics")
:section :graphics
:assets-count (count objects)
:open? open?}
(when local?
[:& cmm/asset-section-block {:role :title-button}
(when (and (not components-v2) (not read-only?))
[:button {:class (stl/css :assets-btn)
:on-click add-graphic}
i/add
[:& file-uploader {:accept cm/str-image-types
:multi true
:ref input-ref
:on-selected on-file-selected}]])])
[:& cmm/asset-section-block {:role :content}
[:& graphics-group {:file-id file-id
:prefix ""
:groups groups
:open-groups open-groups
:force-open? force-open?
:renaming (:renaming @state)
:listing-thumbs? listing-thumbs?
:selected selected
:on-asset-click on-asset-click
:on-drag-start on-drag-start
:do-rename do-rename
:cancel-rename cancel-rename
:on-rename-group on-rename-group
:on-ungroup on-ungroup
:on-context-menu on-context-menu
:selected-full selected-full}]
(when local?
[:& cmm/assets-context-menu
{:on-close on-close-menu
:state @menu-state
:options [(when-not (or multi-objects? multi-assets?)
{:name (tr "workspace.assets.rename")
:id "assets-rename-graphics"
:handler on-rename})
{:name (tr "workspace.assets.delete")
:id "assets-delete-graphics"
:handler on-delete}
(when-not multi-assets?
{:name (tr "workspace.assets.group")
:id "assets-group-graphics"
:handler on-group})]}])]]))

View file

@ -1,188 +0,0 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
@import "refactor/common-refactor.scss";
.graphics-group {
.drop-space {
height: $s-12;
}
.asset-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: $s-4;
margin-left: $s-8;
.grid-cell {
@include flexCenter;
position: relative;
padding: $s-8;
border: $s-2 solid transparent;
border-radius: $br-8;
aspect-ratio: 1/1;
background-color: var(--color-foreground-secondary);
overflow: hidden;
cursor: pointer;
img {
height: auto;
width: auto;
max-height: 100%;
max-width: 100%;
pointer-events: none;
}
svg {
height: 10vh;
}
.cell-name {
@include bodySmallTypography;
@include textEllipsis;
display: none;
position: absolute;
left: 0;
bottom: 0;
width: 100%;
padding: $s-2;
&.editing {
display: block;
}
.editable-label-input {
height: unset;
width: 100%;
padding: $s-2;
margin: 0;
}
.editable-label-close {
display: none;
}
}
&:hover {
background-color: var(--assets-item-background-color-hover);
.cell-name {
display: block;
color: var(--assets-item-name-foreground-color-hover);
background: linear-gradient(to top, rgba(52, 57, 59, 1) 0%, rgba(52, 57, 59, 0) 100%);
}
}
&.selected {
border: $s-1 solid var(--assets-item-border-color);
}
.dragging {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: $s-8;
background-color: var(--assets-item-background-color-drag);
border: $s-2 solid var(--assets-item-border-color-drag);
}
}
}
.asset-enum {
padding-bottom: $s-4;
.enum-item {
position: relative;
display: flex;
align-items: center;
height: $s-36;
margin-bottom: $s-4;
padding: $s-2;
border-radius: $br-8;
background-color: var(--assets-item-background-color);
cursor: pointer;
svg,
img {
@include flexCenter;
padding: $s-2;
height: $s-32;
width: $s-32;
border-radius: $br-6;
background-color: var(--assets-component-background-color);
}
.item-name {
@include bodySmallTypography;
@include textEllipsis;
padding-left: $s-8;
color: var(--assets-item-name-foreground-color);
&.editing {
display: flex;
align-items: center;
.editable-label-input {
height: $s-24;
}
.editable-label-close {
display: none;
}
}
}
&:hover {
background-color: var(--assets-item-background-color-hover);
.item-name {
color: var(--assets-item-name-foreground-color-hover);
}
}
&.selected {
border: $s-1 solid var(--assets-item-border-color);
}
}
}
.grid-placeholder {
height: $s-2;
background-color: var(--color-accent-primary);
margin-bottom: $s-2;
}
}
.listing-options {
display: flex;
align-items: center;
.listing-option-btn {
@include flexCenter;
cursor: pointer;
&.first {
margin-left: auto;
}
svg {
height: $s-16;
width: $s-16;
}
}
}
.add-component {
@extend .button-tertiary;
height: $s-32;
width: $s-28;
margin-left: $s-2;
border-radius: $br-8;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
}
.assets-btn {
@extend .button-tertiary;
height: $s-32;
width: calc($s-24 + $s-4);
padding: 0;
border-radius: $br-8;
svg {
@extend .button-icon;
stroke: var(--icon-foreground);
}
}

View file

@ -53,8 +53,7 @@
parent-board? (and (cfh/frame-shape? item) parent-board? (and (cfh/frame-shape? item)
(= uuid/zero (:parent-id item))) (= uuid/zero (:parent-id item)))
absolute? (ctl/item-absolute? item) absolute? (ctl/item-absolute? item)
components-v2 (mf/use-ctx ctx/components-v2) main-instance? (:main-instance item)
main-instance? (or (not components-v2) (:main-instance item))
variants? (features/use-feature "variants/v1") variants? (features/use-feature "variants/v1")
is-variant? (when variants? (ctk/is-variant? item)) is-variant? (when variants? (ctk/is-variant? item))
variant-name (when is-variant? (:variant-name item)) variant-name (when is-variant? (:variant-name item))

View file

@ -679,7 +679,7 @@
(fn [] (fn []
(swap! state* update :render inc))) (swap! state* update :render inc)))
menu-entries (cmm/generate-components-menu-entries shapes true) menu-entries (cmm/generate-components-menu-entries shapes)
show-menu? (seq menu-entries) show-menu? (seq menu-entries)
path (->> component (:path) (cfh/split-path) (cfh/join-path-with-dot))] path (->> component (:path) (cfh/split-path) (cfh/join-path-with-dot))]

View file

@ -13,7 +13,6 @@
[app.main.ui.hooks :as hooks] [app.main.ui.hooks :as hooks]
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]] [app.main.ui.workspace.sidebar.options.menus.color-selection :refer [color-selection-menu*]]
[app.main.ui.workspace.sidebar.options.menus.component :refer [component-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu]] [app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-menu]]
[app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell] [app.main.ui.workspace.sidebar.options.menus.grid-cell :as grid-cell]
@ -70,7 +69,6 @@
[:div {:class (stl/css :options)} [:div {:class (stl/css :options)}
[:& layer-menu {:type type :ids layer-ids :values layer-values}] [:& layer-menu {:type type :ids layer-ids :values layer-values}]
[:> measures-menu* {:type type :ids measure-ids :values measure-values :shape shape}] [:> measures-menu* {:type type :ids measure-ids :values measure-values :shape shape}]
[:& component-menu {:shapes [shape]}] ;;remove this in components-v2
[:& layout-container-menu [:& layout-container-menu
{:type type {:type type

View file

@ -251,8 +251,7 @@
on-frame-enter (unchecked-get props "on-frame-enter") on-frame-enter (unchecked-get props "on-frame-enter")
on-frame-leave (unchecked-get props "on-frame-leave") on-frame-leave (unchecked-get props "on-frame-leave")
on-frame-select (unchecked-get props "on-frame-select") on-frame-select (unchecked-get props "on-frame-select")
components-v2 (mf/use-ctx ctx/components-v2) shapes (ctt/get-frames objects {:skip-copies? true})
shapes (ctt/get-frames objects {:skip-copies? components-v2})
shapes (if (dbg/enabled? :shape-titles) shapes (if (dbg/enabled? :shape-titles)
(into (set shapes) (into (set shapes)
(map (d/getf objects)) (map (d/getf objects))

View file

@ -12,9 +12,6 @@
[app.plugins :as plugins] [app.plugins :as plugins]
[app.util.timers :as tm])) [app.util.timers :as tm]))
(defn ^:export is-components-v2 []
(features/active-feature? @st/state "components/v2"))
(defn ^:export grid [] (defn ^:export grid []
(tm/schedule-on-idle #(st/emit! (features/toggle-feature "layout/grid"))) (tm/schedule-on-idle #(st/emit! (features/toggle-feature "layout/grid")))
nil) nil)

View file

@ -146,8 +146,6 @@
(:objects page) (:objects page)
(:id page) (:id page)
current-file-id current-file-id
true
dwg/prepare-create-group
cfsh/prepare-create-artboard-from-selection)] cfsh/prepare-create-artboard-from-selection)]
(swap! idmap assoc instance-label (:id group) (swap! idmap assoc instance-label (:id group)

View file

@ -1237,6 +1237,18 @@ msgstr ""
"features of the file you are trying to open. Migrations for '%s' need to be " "features of the file you are trying to open. Migrations for '%s' need to be "
"applied before the file can be opened." "applied before the file can be opened."
msgid "errors.deprecated"
msgstr "Sorry! This is an old file that uses a deprecated type of Penpot assets and you can't open it."
msgid "errors.deprecated.contact.before"
msgstr "Although Penpot no longer support this type of Assets, you can"
msgid "errors.deprecated.contact.text"
msgstr "contact us"
msgid "errors.deprecated.contact.after"
msgstr "so we can help you."
#: src/app/main/data/auth.cljs:322, src/app/main/ui/auth/login.cljs:81, src/app/main/ui/auth/login.cljs:122, src/app/main/ui/auth/register.cljs:66, src/app/main/ui/auth/register.cljs:207, src/app/main/ui/auth/verify_token.cljs:94, src/app/main/ui/dashboard/team.cljs:193, src/app/main/ui/onboarding/team_choice.cljs:112, src/app/main/ui/settings/access_tokens.cljs:80, src/app/main/ui/settings/feedback.cljs:49 #: src/app/main/data/auth.cljs:322, src/app/main/ui/auth/login.cljs:81, src/app/main/ui/auth/login.cljs:122, src/app/main/ui/auth/register.cljs:66, src/app/main/ui/auth/register.cljs:207, src/app/main/ui/auth/verify_token.cljs:94, src/app/main/ui/dashboard/team.cljs:193, src/app/main/ui/onboarding/team_choice.cljs:112, src/app/main/ui/settings/access_tokens.cljs:80, src/app/main/ui/settings/feedback.cljs:49
msgid "errors.generic" msgid "errors.generic"
msgstr "Something wrong has happened." msgstr "Something wrong has happened."

View file

@ -1245,6 +1245,18 @@ msgstr ""
"del fichero que se esta intentando abrir. Falta aplicar migraciones para " "del fichero que se esta intentando abrir. Falta aplicar migraciones para "
"'%s' antes de poder abrir el fichero." "'%s' antes de poder abrir el fichero."
msgid "errors.deprecated"
msgstr "¡Lo sentimos! Este es un fichero antiguo que utiliza un tipo de recurso de Penpot obsoleto, y no puedes abrirlo."
msgid "errors.deprecated.contact.before"
msgstr "Aunque Penpot ya no da soporte a este tipo de Recursos, puedes"
msgid "errors.deprecated.contact.text"
msgstr "contactar con nosotros"
msgid "errors.deprecated.contact.after"
msgstr "para que podamos ayudarte."
#: src/app/main/data/auth.cljs:322, src/app/main/ui/auth/login.cljs:81, src/app/main/ui/auth/login.cljs:122, src/app/main/ui/auth/register.cljs:66, src/app/main/ui/auth/register.cljs:207, src/app/main/ui/auth/verify_token.cljs:94, src/app/main/ui/dashboard/team.cljs:193, src/app/main/ui/onboarding/team_choice.cljs:112, src/app/main/ui/settings/access_tokens.cljs:80, src/app/main/ui/settings/feedback.cljs:49 #: src/app/main/data/auth.cljs:322, src/app/main/ui/auth/login.cljs:81, src/app/main/ui/auth/login.cljs:122, src/app/main/ui/auth/register.cljs:66, src/app/main/ui/auth/register.cljs:207, src/app/main/ui/auth/verify_token.cljs:94, src/app/main/ui/dashboard/team.cljs:193, src/app/main/ui/onboarding/team_choice.cljs:112, src/app/main/ui/settings/access_tokens.cljs:80, src/app/main/ui/settings/feedback.cljs:49
msgid "errors.generic" msgid "errors.generic"
msgstr "Ha ocurrido algún error." msgstr "Ha ocurrido algún error."