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)
(:id page)
file-id
true
nil
cfsh/prepare-create-artboard-from-selection)]
(shape-cb shape)

View file

@ -179,7 +179,7 @@
component-child (first component-children)]
(if (or (nil? child) (nil? component-child))
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))
(ctk/instance-head? child))
(let [slot (guess-swap-slot component-child component-container)]

View file

@ -104,7 +104,6 @@
"Translate a flag to a feature name"
[flag]
(case flag
:feature-components-v2 "components/v2"
:feature-styles-v2 "styles/v2"
:feature-fdata-objects-map "fdata/objects-map"
:feature-fdata-pointer-map "fdata/pointer-map"
@ -241,7 +240,13 @@
:code :file-feature-mismatch
:feature (first not-supported)
: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))

View file

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

View file

@ -921,11 +921,11 @@
(apply-changes-local))))
(defn add-component
([changes id path name new-shapes 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))
([changes id path name new-shapes 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))
([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]
(add-component changes id path name updated-shapes main-instance-id main-instance-page nil nil nil))
([changes id path name updated-shapes main-instance-id main-instance-page annotation]
(add-component changes id path name updated-shapes main-instance-id main-instance-page annotation nil nil))
([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-objects! changes)
(let [page-id (::page-id (meta changes))
@ -965,8 +965,6 @@
:main-instance-id main-instance-id
:main-instance-page main-instance-page
:annotation annotation}
(some? new-shapes) ;; this will be null in components-v2
(assoc :shapes (vec new-shapes))
(some? variant-id)
(assoc :variant-id variant-id)
(seq variant-properties)
@ -1000,7 +998,7 @@
:main-instance-id (:main-instance-id new-component)
:main-instance-page (:main-instance-page 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)}
(some? (:variant-id new-component))
(assoc :variant-id (:variant-id new-component))

View file

@ -79,7 +79,7 @@
:file-schema-validation
;; Reports the schema validation errors internally.
: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
;; Reports the referential integrity validation errors internally.
:soft-file-validation

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -182,10 +182,8 @@
(= (:component-file shape) file-id)))
(defn is-main-of?
[shape-main shape-inst components-v2]
(or (= (:shape-ref shape-inst) (:id shape-main))
(and (= (:shape-ref shape-inst) (:shape-ref shape-main))
(not components-v2))))
[shape-main shape-inst]
(= (:shape-ref shape-inst) (:id shape-main)))
(defn main-instance?
"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)))
(defn add-component
[fdata {:keys [id name path main-instance-id main-instance-page shapes annotation variant-id variant-properties]}]
(let [components-v2 (dm/get-in fdata [:options :components-v2])
fdata (update fdata :components assoc id (touch {:id id :name name :path path}))]
(if components-v2
[fdata {:keys [id name path main-instance-id main-instance-page annotation variant-id variant-properties]}]
(let [fdata (update fdata :components assoc id (touch {:id id :name name :path path}))]
(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)
variant-id (update-in [:components id] assoc :variant-id variant-id)
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)))))))
variant-properties (update-in [:components id] assoc :variant-properties variant-properties))))
(defn mod-component
[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))
(map #(dissoc % :component-root)))]
[(assoc new-root :id new-id)
nil
(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
"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"
@ -352,20 +293,18 @@
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
automatically creates correct references."
([page component library-data position components-v2]
(make-component-instance page component library-data position components-v2 {}))
([page component library-data position components-v2
([page component library-data position]
(make-component-instance page component library-data position {}))
([page component library-data position
{:keys [main-instance? force-id force-frame-id keep-ids?]
:or {main-instance? false force-id nil force-frame-id nil keep-ids? false}}]
(let [component-page (when components-v2
(ctpl/get-page library-data (:main-instance-page component)))
(let [component-page (ctpl/get-page library-data (:main-instance-page component))
component-shape (if components-v2
(-> (get-shape component-page (:main-instance-id component))
component-shape (-> (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 :frame-id uuid/zero)
(remove-swap-keep-attrs))
(get-shape component (:id component)))
orig-pos (gpt/point (:x component-shape) (:y component-shape))
delta (gpt/subtract position orig-pos)
@ -395,8 +334,7 @@
update-new-shape
(fn [new-shape original-shape]
(let [new-name (:name new-shape)
root? (or (ctk/instance-root? original-shape) ; If shape is inside a component (not components-v2)
(nil? (:parent-id original-shape)))] ; we detect it by having no parent)
root? (ctk/instance-root? original-shape)]
(when root?
(vswap! unames conj new-name))
@ -417,10 +355,8 @@
main-instance?
(dissoc :shape-ref)
(and (not main-instance?)
(or components-v2 ; In v1, shape-ref points to the remote instance
(nil? (:shape-ref original-shape)))) ; in v2, shape-ref points to the near instance
(assoc :shape-ref (:id original-shape))
(not main-instance?)
(assoc :shape-ref (:id original-shape)) ; shape-ref points to the near instance
(nil? (:parent-id original-shape))
(assoc :component-id (:id component)
@ -428,14 +364,14 @@
:component-root true
: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))
(dissoc :component-root))))
[new-shape new-shapes _]
(ctst/clone-shape component-shape
frame-id
(if components-v2 (:objects component-page) (:objects component))
(:objects component-page)
:update-new-shape update-new-shape
:force-id force-id
:keep-ids? keep-ids?
@ -593,8 +529,7 @@
;; TODO: the check of :width and :height probably may be
;; removed after the check added in
;; data/workspace/modifiers/check-delta function. Better check
;; it and test toroughly when activating components-v2 mode.
;; data/workspace/modifiers/check-delta function.
in-copy?
(ctk/in-component-copy? shape)

View file

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

View file

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

View file

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

View file

@ -227,7 +227,7 @@
(t/is (= (:touched copy-root') nil))
(t/is (= (:touched copy-new-child') nil))
(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
(let [;; ==== Setup

View file

@ -54,7 +54,7 @@
(t/is (= (count components') 1))
(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/deftest absorb-colors

View file

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

View file

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

View file

@ -24,7 +24,6 @@
[app.main.data.helpers :as dsh]
[app.main.data.media :as dmm]
[app.main.data.notifications :as ntf]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.shapes :as dwsh]
[app.main.data.workspace.svg-upload :as svg]
[app.main.repo :as rp]
@ -235,16 +234,6 @@
(rx/catch #(handle-media-error % on-error))
(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
[{:keys [position file-id] :as params}]
(let [params (assoc params
@ -378,7 +367,7 @@
(defn- add-shapes-and-component
[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))
changes (-> (pcb/empty-changes it)
@ -389,7 +378,6 @@
(pcb/add-component (:id component-shape)
""
name
component-shapes
updated-shapes
(:id shape)
(:id page)))]

View file

@ -24,7 +24,6 @@
[app.main.data.workspace.edition :as dwe]
[app.main.data.workspace.selection :as dws]
[app.main.data.workspace.undo :as dwu]
[app.main.features :as features]
[beicon.v2.core :as rx]
[potok.v2.core :as ptk]))
@ -171,12 +170,10 @@
page (dsh/get-page fdata page-id)
objects (:objects page)
components-v2 (features/active-feature? state "components/v2")
undo-id (or (:undo-id options) (js/Symbol))
[all-parents changes] (-> (pcb/empty-changes it (:id page))
(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-id undo-id}))]

View file

@ -260,6 +260,14 @@
(let [message (tr "errors.feature-not-supported" (:feature error))]
(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
(print-cause! "Restriction Error" error)))

View file

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

View file

@ -8,10 +8,12 @@
.modal-overlay {
@extend .modal-overlay-base;
&.transparent {
background-color: transparent;
}
}
.modal-container {
@extend .modal-container-base;
}
@ -48,6 +50,7 @@
.accept-btn {
@extend .modal-accept-btn;
&.danger {
@extend .modal-danger-btn;
}
@ -60,3 +63,15 @@
color: var(--modal-text-foreground-color);
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 libraries (mf/create-context nil))
(def components-v2 (mf/create-context nil))
(def design-tokens (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
[:div {:class (stl/css :asset-list)}
(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)
:key (str "assets-component-" (:id component))}
[:& 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-file-id) {:value file-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/workspace-read-only?) {:value read-only?}
[:> modal-container*]
@ -216,4 +215,4 @@
:file file
:wglobal wglobal
:layout layout}]
[:> workspace-loader*])]]]]]]]))
[:> workspace-loader*])]]]]]]))

View file

@ -555,7 +555,7 @@
objects (deref refs/workspace-page-objects)
can-make-component (every? true? (map #(ctn/valid-shape-for-component? objects %) 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)))
do-add-component #(st/emit! (dwl/add-component))
do-add-multiple-components #(st/emit! (dwl/add-multiple-components))

View file

@ -75,8 +75,7 @@
{::mf/wrap [mf/memo]
::mf/wrap-props false}
[{:keys [size file-id]}]
(let [components-v2 (mf/use-ctx ctx/components-v2)
read-only? (mf/use-ctx ctx/workspace-read-only?)
(let [read-only? (mf/use-ctx ctx/workspace-read-only?)
filters* (mf/use-state
{:term ""
:section "all"
@ -148,11 +147,6 @@
:id "components"
: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")
:id "colors"
:handler on-section-filter-change}

View file

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

View file

@ -308,7 +308,6 @@
menu-state (mf/use-state cmm/initial-context-menu-state)
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)
selected (:components selected)
@ -521,7 +520,7 @@
:title (tr "workspace.assets.grid-view")
:id "opt-grid"}]]])
(when (and components-v2 (not read-only?) is-local)
(when (and (not read-only?) is-local)
[:> icon-button* {:variant "ghost"
:aria-label (tr "workspace.assets.components.add-component")
:on-click add-component
@ -561,9 +560,7 @@
:id "assets-rename-component"
:handler on-rename})
(when (and is-local (not (or multi-assets? read-only? any-variant?)))
{:name (if components-v2
(tr "workspace.assets.duplicate-main")
(tr "workspace.assets.duplicate"))
{:name (tr "workspace.assets.duplicate-main")
:id "assets-duplicate-component"
:handler on-duplicate})
@ -576,7 +573,7 @@
:id "assets-group-component"
:handler on-group})
(when (and components-v2 (not multi-assets?))
(when (not multi-assets?)
{:name (tr "workspace.shape.menu.show-main")
:id "assets-show-main-component"
: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.common :as cmm]
[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.util.dom :as dom]
[app.util.i18n :as i18n :refer [tr]]
@ -145,11 +144,10 @@
(mf/defc file-library-content*
{::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)
file-id (:id file)
project-id (:project-id file)
filters-section (:section filters)
has-filters-term? (not ^boolean (str/empty? (:term filters)))
@ -165,11 +163,6 @@
(or (pos? (count components))
(not has-filters-term?)))
show-graphics?
(and (or (= filters-section "all")
(= filters-section "graphics"))
(pos? (count media)))
show-colors?
(and (or (= filters-section "all")
(= filters-section "colors"))
@ -188,9 +181,6 @@
force-open-colors?
(when ^boolean has-filters-term? (> 60 (count colors)))
force-open-graphics?
(when ^boolean has-filters-term? (> 60 (count media)))
force-open-typographies?
(when ^boolean has-filters-term? (> 60 (count typographies)))
@ -214,9 +204,6 @@
on-component-click
(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
(mf/use-fn (mf/deps on-asset-click) (partial on-asset-click :colors))
@ -266,23 +253,6 @@
:on-clear-selection on-clear-selection
: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?
[:& colors-section
{:file-id file-id
@ -315,7 +285,6 @@
:on-clear-selection on-clear-selection}])
(when (and (not ^boolean show-components?)
(not ^boolean show-graphics?)
(not ^boolean show-colors?)
(not ^boolean show-typography?))
[:div {:class (stl/css :asset-title)}
@ -333,7 +302,6 @@
library (use-library-ref file-id)
colors (:colors library)
media (:media library)
typographies (:typographies library)
filters-term (:term filters)
@ -350,11 +318,6 @@
(cmm/apply-filters $ filters)
(remove #(cfv/is-secondary-variant? % library) $)))
filtered-media
(mf/with-memo [filters media]
(-> (vals media)
(cmm/apply-filters filters)))
filtered-typographies
(mf/with-memo [filters typographies]
(-> (vals typographies)
@ -372,7 +335,6 @@
(and (not (str/blank? filters-term))
(or (> 60 (count filtered-colors))
(> 60 (count filtered-components))
(> 60 (count filtered-media))
(> 60 (count filtered-typographies))))
open?
@ -415,7 +377,6 @@
:filters filters
:colors filtered-colors
:components filtered-components
:media filtered-media
:typographies filtered-typographies
:on-clear-selection unselect-all
: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)
(= uuid/zero (:parent-id item)))
absolute? (ctl/item-absolute? item)
components-v2 (mf/use-ctx ctx/components-v2)
main-instance? (or (not components-v2) (:main-instance item))
main-instance? (:main-instance item)
variants? (features/use-feature "variants/v1")
is-variant? (when variants? (ctk/is-variant? item))
variant-name (when is-variant? (:variant-name item))

View file

@ -679,7 +679,7 @@
(fn []
(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)
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.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.component :refer [component-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.grid-cell :as grid-cell]
@ -70,7 +69,6 @@
[:div {:class (stl/css :options)}
[:& layer-menu {:type type :ids layer-ids :values layer-values}]
[:> measures-menu* {:type type :ids measure-ids :values measure-values :shape shape}]
[:& component-menu {:shapes [shape]}] ;;remove this in components-v2
[:& layout-container-menu
{:type type

View file

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

View file

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

View file

@ -146,8 +146,6 @@
(:objects page)
(:id page)
current-file-id
true
dwg/prepare-create-group
cfsh/prepare-create-artboard-from-selection)]
(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 "
"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
msgid "errors.generic"
msgstr "Something wrong has happened."

View file

@ -1245,6 +1245,18 @@ msgstr ""
"del fichero que se esta intentando abrir. Falta aplicar migraciones para "
"'%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
msgid "errors.generic"
msgstr "Ha ocurrido algún error."