🎉 Make components-v2 an optional feature

This commit is contained in:
Andrés Moya 2022-07-12 13:52:48 +02:00
parent 1ef37281e6
commit a5bf1c03e7
40 changed files with 495 additions and 296 deletions

View file

@ -465,15 +465,20 @@
(defmulti components-changed (fn [_ change] (:type change)))
(defmethod components-changed :mod-obj
[file-data {:keys [id page-id component-id operations]}]
[file-data {:keys [id page-id _component-id operations]}]
(when page-id
(let [page (ctpl/get-page file-data page-id)
shape-and-parents (map #(ctn/get-shape page %)
(into [id] (cph/get-parent-ids (:objects page) id)))
any-set? (some #(= (:type %) :set) operations)]
(when any-set?
need-sync? (fn [operation]
; We need to trigger a sync if the shape has changed any
; attribute that participates in components syncronization.
(and (= (:type operation) :set)
(component-sync-attrs (:attr operation))))
any-sync? (some need-sync? operations)]
(when any-sync?
(into #{} (->> shape-and-parents
(filter #(:main-instance? %))
(filter #(:main-instance? %)) ; Select shapes that are main component instances
(map :id)))))))
(defmethod components-changed :default

View file

@ -50,7 +50,7 @@
(defn with-objects
[changes objects]
(let [file-data (-> (ctf/make-file-data (uuid/next) uuid/zero)
(let [file-data (-> (ctf/make-file-data (uuid/next) uuid/zero true)
(assoc-in [:pages-index uuid/zero :objects] objects))]
(vary-meta changes assoc ::file-data file-data
::applied-changes-count 0)))

View file

@ -9,7 +9,7 @@
[app.common.colors :as clr]
[app.common.uuid :as uuid]))
(def file-version 20)
(def file-version 19)
(def default-color clr/gray-20)
(def root uuid/zero)

View file

@ -440,68 +440,5 @@
(update :pages-index d/update-vals update-container)
(update :components d/update-vals update-container))))
(defmethod migrate 20
[data]
(let [components (ctkl/components-seq data)]
(if (empty? components)
data
(let [grid-gap 50
[data page-id start-pos]
(ctf/get-or-add-library-page data grid-gap)
add-main-instance
(fn [data component position]
(let [page (ctpl/get-page data page-id)
[new-shape new-shapes]
(ctn/make-component-instance page
component
(:id data)
position
true)
add-shapes
(fn [page]
(reduce (fn [page shape]
(ctst/add-shape (:id shape)
shape
page
(:frame-id shape)
(:parent-id shape)
nil ; <- As shapes are ordered, we can safely add each
true)) ; one at the end of the parent's children list.
page
new-shapes))
update-component
(fn [component]
(assoc component
:main-instance-id (:id new-shape)
:main-instance-page page-id))]
(-> data
(ctpl/update-page page-id add-shapes)
(ctkl/update-component (:id component) update-component))))
add-instance-grid
(fn [data components]
(let [position-seq (ctst/generate-shape-grid
(map ctk/get-component-root components)
start-pos
grid-gap)]
(loop [data data
components-seq (seq components)
position-seq position-seq]
(let [component (first components-seq)
position (first position-seq)]
(if (nil? component)
data
(recur (add-main-instance data component position)
(rest components-seq)
(rest position-seq)))))))]
(add-instance-grid data (sort-by :name components))))))
;; TODO: pending to do a migration for delete already not used fill
;; and stroke props. This should be done for >1.14.x version.

View file

@ -14,13 +14,19 @@
(defn add-component
[file-data id name path main-instance-id main-instance-page shapes]
(assoc-in file-data [:components id]
{:id id
:name name
:path path
:main-instance-id main-instance-id
:main-instance-page main-instance-page
:objects (d/index-by :id shapes)}))
(let [components-v2 (get-in file-data [:options :components-v2])]
(cond-> file-data
:always
(assoc-in [:components id]
{:id id
:name name
:path path
:objects (d/index-by :id shapes)})
components-v2
(update-in [:components id] #(assoc %
:main-instance-id main-instance-id
:main-instance-page main-instance-page)))))
(defn get-component
[file-data component-id]

View file

@ -65,7 +65,7 @@
"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]
[shape objects file-id components-v2]
(assert (nil? (:component-id shape)))
(assert (nil? (:component-file shape)))
(assert (nil? (:shape-ref shape)))
@ -94,8 +94,10 @@
(nil? (:parent-id new-shape))
(assoc :component-id (:id new-shape)
:component-file file-id
:component-root? true
:main-instance? true)
:component-root? true)
components-v2
(assoc :main-instance? true)
(some? (:parent-id new-shape))
(dissoc :component-root?)))]
@ -103,6 +105,9 @@
(ctst/clone-object shape nil objects update-new-shape update-original-shape)))
(defn make-component-instance
"Clone the shapes of the component, generating new names and ids, and linking
each new shape to the corresponding one of the component. Place the new instance
coordinates in the given position."
[container component component-file-id position main-instance?]
(let [component-shape (get-shape component (:id component))

View file

@ -83,14 +83,17 @@
:pages-index {}})
(defn make-file-data
([file-id]
(make-file-data file-id (uuid/next)))
([file-id components-v2]
(make-file-data file-id (uuid/next) components-v2))
([file-id page-id]
([file-id page-id components-v2]
(let [page (ctp/make-empty-page page-id "Page-1")]
(-> empty-file-data
(assoc :id file-id)
(ctpl/add-page page)))))
(cond-> (-> empty-file-data
(assoc :id file-id)
(ctpl/add-page page))
components-v2
(assoc-in [:options :components-v2] true)))))
;; Helpers
@ -162,9 +165,9 @@
assets-seq)))
(defn get-or-add-library-page
[file-data grid-gap]
"If exists a page named 'Library page', get the id and calculate the position to start
adding new components. If not, create it and start at (0, 0)."
[file-data grid-gap]
(let [library-page (d/seek #(= (:name %) "Library page") (ctpl/pages-seq file-data))]
(if (some? library-page)
(let [compare-pos (fn [pos shape]
@ -180,6 +183,74 @@
(let [library-page (ctp/make-empty-page (uuid/next) "Library page")]
[(ctpl/add-page file-data library-page) (:id library-page) (gpt/point 0 0)]))))
(defn migrate-to-components-v2
"If there is any component in the file library, add a new 'Library Page' and generate
main instances for all components there. Mark the file with the :comonents-v2 option."
[file-data]
(let [components (ctkl/components-seq file-data)]
(if (or (empty? components)
(get-in file-data [:options :components-v2]))
(assoc-in file-data [:options :components-v2] true)
(let [grid-gap 50
[file-data page-id start-pos]
(get-or-add-library-page file-data grid-gap)
add-main-instance
(fn [file-data component position]
(let [page (ctpl/get-page file-data page-id)
[new-shape new-shapes]
(ctn/make-component-instance page
component
(:id file-data)
position
true)
add-shapes
(fn [page]
(reduce (fn [page shape]
(ctst/add-shape (:id shape)
shape
page
(:frame-id shape)
(:parent-id shape)
nil ; <- As shapes are ordered, we can safely add each
true)) ; one at the end of the parent's children list.
page
new-shapes))
update-component
(fn [component]
(assoc component
:main-instance-id (:id new-shape)
:main-instance-page page-id))]
(-> file-data
(ctpl/update-page page-id add-shapes)
(ctkl/update-component (:id component) update-component))))
add-instance-grid
(fn [file-data components]
(let [position-seq (ctst/generate-shape-grid
(map ctk/get-component-root components)
start-pos
grid-gap)]
(loop [file-data file-data
components-seq (seq components)
position-seq position-seq]
(let [component (first components-seq)
position (first position-seq)]
(if (nil? component)
file-data
(recur (add-main-instance file-data component position)
(rest components-seq)
(rest position-seq)))))))]
(-> file-data
(add-instance-grid (sort-by :name components))
(assoc-in [:options :components-v2] true))))))
(defn- absorb-components
[file-data library-data used-components]
(let [grid-gap 50

View file

@ -15,7 +15,7 @@
(t/deftest process-change-set-option
(let [file-id (uuid/custom 2 2)
page-id (uuid/custom 1 1)
data (ctf/make-file-data file-id page-id)]
data (ctf/make-file-data file-id page-id true)]
(t/testing "Sets option single"
(let [chg {:type :set-option
:page-id page-id
@ -81,7 +81,7 @@
(t/deftest process-change-add-obj
(let [file-id (uuid/custom 2 2)
page-id (uuid/custom 1 1)
data (ctf/make-file-data file-id page-id)
data (ctf/make-file-data file-id page-id true)
id-a (uuid/custom 2 1)
id-b (uuid/custom 2 2)
id-c (uuid/custom 2 3)]
@ -135,7 +135,7 @@
(t/deftest process-change-mod-obj
(let [file-id (uuid/custom 2 2)
page-id (uuid/custom 1 1)
data (ctf/make-file-data file-id page-id)]
data (ctf/make-file-data file-id page-id true)]
(t/testing "simple mod-obj"
(let [chg {:type :mod-obj
:page-id page-id
@ -162,7 +162,7 @@
(let [file-id (uuid/custom 2 2)
page-id (uuid/custom 1 1)
id (uuid/custom 2 1)
data (ctf/make-file-data file-id page-id)
data (ctf/make-file-data file-id page-id true)
data (-> data
(assoc-in [:pages-index page-id :objects uuid/zero :shapes] [id])
(assoc-in [:pages-index page-id :objects id]
@ -206,7 +206,7 @@
file-id (uuid/custom 2 2)
page-id (uuid/custom 1 1)
data (ctf/make-file-data file-id page-id)
data (ctf/make-file-data file-id page-id true)
data (update-in data [:pages-index page-id :objects]
#(-> %
@ -450,7 +450,7 @@
:obj {:type :rect
:name "Shape 3"}}
]
data (ctf/make-file-data file-id page-id)
data (ctf/make-file-data file-id page-id true)
data (cp/process-changes data changes)]
(t/testing "preserve order on multiple shape mov 1"
@ -557,7 +557,7 @@
:parent-id group-1-id
:shapes [shape-1-id shape-2-id]}]
data (ctf/make-file-data file-id page-id)
data (ctf/make-file-data file-id page-id true)
data (cp/process-changes data changes)]
(t/testing "case 1"

View file

@ -1,7 +1,6 @@
(ns app.common.test-helpers.components
(:require
[cljs.test :as t :include-macros true]
[cljs.pprint :refer [pprint]]
[clojure.test :as t]
[app.common.pages.helpers :as cph]
[app.common.types.component :as ctk]
[app.common.types.container :as ctn]))

View file

@ -31,7 +31,7 @@
([file-id page-id props]
(merge {:id file-id
:name (get props :name "File1")
:data (ctf/make-file-data file-id page-id)}
:data (ctf/make-file-data file-id page-id true)}
props)))
(defn sample-shape
@ -68,9 +68,10 @@
(let [page (ctpl/get-page file-data page-id)
[component-shape component-shapes updated-shapes]
(ctn/make-component-shape (ctn/get-shape page shape-id)
(ctn/make-component-shape (ctn/get-shape page shape-id true)
(:objects page)
(:id file))]
(:id file)
true)]
(swap! idmap assoc label (:id component-shape))
(-> file-data

View file

@ -110,6 +110,7 @@
(t/is (= (:name p-group) "Group1"))
(t/is (ctk/instance-of? p-group file-id (:id component1)))
(t/is (not (:main-instance? p-group)))
(t/is (not (ctk/is-main-instance? (:id p-group) file-page-id component1)))
(t/is (ctk/is-main-of? c-group1 p-group))