Synchronize add/delete/move shapes in componentes

This commit is contained in:
Andrés Moya 2020-11-11 13:03:24 +01:00
parent 912be76400
commit ebb7410e5b
5 changed files with 640 additions and 405 deletions

View file

@ -251,7 +251,8 @@
:add-media :mod-media :del-media :add-media :mod-media :del-media
:add-component :mod-component :del-component :add-component :mod-component :del-component
:add-typography :mod-typography :del-typography} (:type change)) :add-typography :mod-typography :del-typography} (:type change))
(and (= (:type change) :mod-obj) (and (#{:add-obj :mod-obj :del-obj
:reg-objects :mov-objects} (:type change))
(some? (:component-id change))))) (some? (:component-id change)))))
(declare update-file) (declare update-file)

View file

@ -435,6 +435,14 @@
:internal.file/recent-colors :internal.file/recent-colors
:internal.file/media])) :internal.file/media]))
(s/def ::container-type #{:page :component})
(s/def ::container
(s/keys :req-un [::container-type
::id
::name
:internal.page/objects]))
(defmulti operation-spec :type) (defmulti operation-spec :type)
(s/def :internal.operations.set/attr keyword?) (s/def :internal.operations.set/attr keyword?)
@ -461,9 +469,9 @@
(s/def :internal.changes.add-obj/obj ::shape) (s/def :internal.changes.add-obj/obj ::shape)
(defmethod change-spec :add-obj [_] (defmethod change-spec :add-obj [_]
(s/keys :req-un [::id ::page-id ::frame-id (s/keys :req-un [::id (or ::page-id ::component-id)
:internal.changes.add-obj/obj] :internal.changes.add-obj/obj]
:opt-un [::parent-id])) :opt-un [::parent-id ::frame-id]))
(s/def ::operation (s/multi-spec operation-spec :type)) (s/def ::operation (s/multi-spec operation-spec :type))
(s/def ::operations (s/coll-of ::operation)) (s/def ::operations (s/coll-of ::operation))
@ -472,16 +480,17 @@
(s/keys :req-un [::id (or ::page-id ::component-id) ::operations])) (s/keys :req-un [::id (or ::page-id ::component-id) ::operations]))
(defmethod change-spec :del-obj [_] (defmethod change-spec :del-obj [_]
(s/keys :req-un [::id ::page-id])) (s/keys :req-un [::id (or ::page-id ::component-id)]))
(s/def :internal.changes.reg-objects/shapes (s/def :internal.changes.reg-objects/shapes
(s/coll-of uuid? :kind vector?)) (s/coll-of uuid? :kind vector?))
(defmethod change-spec :reg-objects [_] (defmethod change-spec :reg-objects [_]
(s/keys :req-un [::page-id :internal.changes.reg-objects/shapes])) (s/keys :req-un [(or ::page-id ::component-id)
:internal.changes.reg-objects/shapes]))
(defmethod change-spec :mov-objects [_] (defmethod change-spec :mov-objects [_]
(s/keys :req-un [::page-id ::parent-id :internal.shape/shapes] (s/keys :req-un [(or ::page-id ::component-id) ::parent-id :internal.shape/shapes]
:opt-un [::index])) :opt-un [::index]))
(defmethod change-spec :add-page [_] (defmethod change-spec :add-page [_]
@ -701,26 +710,26 @@
(assoc data :options (d/dissoc-in (:options data) path))))))) (assoc data :options (d/dissoc-in (:options data) path)))))))
(defmethod process-change :add-obj (defmethod process-change :add-obj
[data {:keys [id obj page-id frame-id parent-id index] :as change}] [data {:keys [id obj page-id component-id frame-id parent-id index] :as change}]
(d/update-in-when data [:pages-index page-id] (let [update-fn (fn [data]
(fn [data] (let [parent-id (or parent-id frame-id)
(let [parent-id (or parent-id frame-id) objects (:objects data)]
objects (:objects data)] (let [obj (assoc obj
(when (and (contains? objects parent-id) :frame-id frame-id
(contains? objects frame-id)) :parent-id parent-id
(let [obj (assoc obj :id id)]
:frame-id frame-id (-> data
:parent-id parent-id (update :objects assoc id obj)
:id id)] (update-in [:objects parent-id :shapes]
(-> data (fn [shapes]
(update :objects assoc id obj) (let [shapes (or shapes [])]
(update-in [:objects parent-id :shapes] (cond
(fn [shapes] (some #{id} shapes) shapes
(let [shapes (or shapes [])] (nil? index) (conj shapes id)
(cond :else (cph/insert-at-index shapes index [id])))))))))]
(some #{id} shapes) shapes (if page-id
(nil? index) (conj shapes id) (d/update-in-when data [:pages-index page-id] update-fn)
:else (cph/insert-at-index shapes index [id])))))))))))) (d/update-in-when data [:components component-id] update-fn))))
(defmethod process-change :mod-obj (defmethod process-change :mod-obj
[data {:keys [id page-id component-id operations] :as change}] [data {:keys [id page-id component-id operations] :as change}]
@ -733,8 +742,8 @@
(d/update-in-when data [:components component-id :objects] update-fn)))) (d/update-in-when data [:components component-id :objects] update-fn))))
(defmethod process-change :del-obj (defmethod process-change :del-obj
[data {:keys [page-id id] :as change}] [data {:keys [page-id component-id id] :as change}]
(letfn [(delete-object [objects id] (letfn [(delete-object [objects]
(if-let [target (get objects id)] (if-let [target (get objects id)]
(let [parent-id (cph/get-parent id objects) (let [parent-id (cph/get-parent id objects)
frame-id (:frame-id target) frame-id (:frame-id target)
@ -752,7 +761,9 @@
; dependend objects ; dependend objects
(as-> $ (reduce delete-object $ (:shapes target))))) (as-> $ (reduce delete-object $ (:shapes target)))))
objects))] objects))]
(d/update-in-when data [:pages-index page-id :objects] delete-object id))) (if page-id
(d/update-in-when data [:pages-index page-id :objects] delete-object)
(d/update-in-when data [:components component-id :objects] delete-object))))
(defn rotation-modifiers (defn rotation-modifiers
[center shape angle] [center shape angle]
@ -765,7 +776,7 @@
;; reg-objects operation "regenerates" the values for the parent groups ;; reg-objects operation "regenerates" the values for the parent groups
(defmethod process-change :reg-objects (defmethod process-change :reg-objects
[data {:keys [page-id shapes]}] [data {:keys [page-id component-id shapes]}]
(letfn [(reg-objects [objects] (letfn [(reg-objects [objects]
(reduce #(update %1 %2 update-group %1) objects (reduce #(update %1 %2 update-group %1) objects
(sequence (comp (sequence (comp
@ -797,10 +808,12 @@
(assoc-in [:modifiers :rotation] (:rotation group 0)) (assoc-in [:modifiers :rotation] (:rotation group 0))
(geom/transform-shape))))] (geom/transform-shape))))]
(d/update-in-when data [:pages-index page-id :objects] reg-objects))) (if page-id
(d/update-in-when data [:pages-index page-id :objects] reg-objects)
(d/update-in-when data [:components component-id :objects] reg-objects))))
(defmethod process-change :mov-objects (defmethod process-change :mov-objects
[data {:keys [parent-id shapes index page-id] :as change}] [data {:keys [parent-id shapes index page-id component-id] :as change}]
(letfn [(is-valid-move? [objects shape-id] (letfn [(is-valid-move? [objects shape-id]
(let [invalid-targets (cph/calculate-invalid-targets shape-id objects)] (let [invalid-targets (cph/calculate-invalid-targets shape-id objects)]
(and (not (invalid-targets parent-id)) (and (not (invalid-targets parent-id))
@ -881,7 +894,9 @@
(reduce (partial update-frame-ids frm-id) $ (get-in $ [parent-id :shapes]))) (reduce (partial update-frame-ids frm-id) $ (get-in $ [parent-id :shapes])))
objects)))] objects)))]
(d/update-in-when data [:pages-index page-id :objects] move-objects))) (if page-id
(d/update-in-when data [:pages-index page-id :objects] move-objects)
(d/update-in-when data [:components component-id :objects] move-objects))))
(defmethod process-change :add-page (defmethod process-change :add-page
[data {:keys [id name page]}] [data {:keys [id name page]}]

View file

@ -42,11 +42,25 @@
objects) objects)
nil))) nil)))
(defn make-container
[page-or-component container-type]
(assoc page-or-component
:container-type container-type))
(defn is-page
[container]
(= (:container-type container) :page))
(defn is-component
[container]
(= (:container-type container) :component))
(defn get-container (defn get-container
[page-id component-id local-file] [container-id container-type local-file]
(if (some? page-id) (-> (if (= container-type :page)
(get-in local-file [:pages-index page-id]) (get-in local-file [:pages-index container-id])
(get-in local-file [:components component-id]))) (get-in local-file [:components container-id]))
(assoc :container-type container-type)))
(defn get-shape (defn get-shape
[container shape-id] [container shape-id]
@ -59,6 +73,12 @@
(get-in libraries [file-id :data]))] (get-in libraries [file-id :data]))]
(get-in file [:components component-id]))) (get-in file [:components component-id])))
(defn is-master-of
[shape-master shape-inst]
(and (:shape-ref shape-inst)
(or (= (:shape-ref shape-inst) (:id shape-master))
(= (:shape-ref shape-inst) (:shape-ref shape-master)))))
(defn get-component-root (defn get-component-root
[component] [component]
(get-in component [:objects (:id component)])) (get-in component [:objects (:id component)]))
@ -75,12 +95,12 @@
(defn get-children-objects (defn get-children-objects
"Retrieve all children objects recursively for a given object" "Retrieve all children objects recursively for a given object"
[id objects] [id objects]
(map #(get objects %) (get-children id objects))) (mapv #(get objects %) (get-children id objects)))
(defn get-object-with-children (defn get-object-with-children
"Retrieve a list with an object and all of its children" "Retrieve a vector with an object and all of its children"
[id objects] [id objects]
(map #(get objects %) (cons id (get-children id objects)))) (mapv #(get objects %) (cons id (get-children id objects))))
(defn is-shape-grouped (defn is-shape-grouped
"Checks if a shape is inside a group" "Checks if a shape is inside a group"
@ -210,17 +230,17 @@
:parent-id parent-id) :parent-id parent-id)
(some? (:shapes object)) (some? (:shapes object))
(assoc :shapes (map :id new-direct-children))) (assoc :shapes (mapv :id new-direct-children)))
new-object (update-new-object new-object object) new-object (update-new-object new-object object)
new-objects (concat [new-object] new-children) new-objects (d/concat [new-object] new-children)
updated-object (update-original-object object new-object) updated-object (update-original-object object new-object)
updated-objects (if (identical? object updated-object) updated-objects (if (identical? object updated-object)
updated-children updated-children
(concat [updated-object] updated-children))] (d/concat [updated-object] updated-children))]
[new-object new-objects updated-objects]) [new-object new-objects updated-objects])
@ -232,9 +252,9 @@
(recur (recur
(next child-ids) (next child-ids)
(concat new-direct-children [new-child]) (d/concat new-direct-children [new-child])
(concat new-children new-child-objects) (d/concat new-children new-child-objects)
(concat updated-children updated-child-objects)))))))) (d/concat updated-children updated-child-objects))))))))
(defn indexed-shapes (defn indexed-shapes

View file

@ -32,6 +32,7 @@
[cljs.spec.alpha :as s] [cljs.spec.alpha :as s]
[potok.core :as ptk])) [potok.core :as ptk]))
;; Change this to :info :debug or :trace to debug this module
(log/set-level! :warn) (log/set-level! :warn)
(declare sync-file) (declare sync-file)
@ -493,16 +494,18 @@
(ptk/reify ::reset-component (ptk/reify ::reset-component
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
;; ===== Uncomment this to debug =====
(log/info :msg "RESET-COMPONENT of shape" :id (str id)) (log/info :msg "RESET-COMPONENT of shape" :id (str id))
(let [[rchanges uchanges] (let [local-file (get state :workspace-data)
(dwlh/generate-sync-shape-and-children-components (get state :current-page-id) libraries (get state :workspace-libraries)
nil container (cph/get-container (get state :current-page-id)
id :page
(get state :workspace-data) local-file)
(get state :workspace-libraries) [rchanges uchanges]
true)] (dwlh/generate-sync-shape-direct container
;; ===== Uncomment this to debug ===== id
local-file
libraries
true)]
(log/debug :msg "RESET-COMPONENT finished" :js/rchanges rchanges) (log/debug :msg "RESET-COMPONENT finished" :js/rchanges rchanges)
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
@ -516,7 +519,6 @@
(ptk/reify ::update-component (ptk/reify ::update-component
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
;; ===== Uncomment this to debug =====
(log/info :msg "UPDATE-COMPONENT of shape" :id (str id)) (log/info :msg "UPDATE-COMPONENT of shape" :id (str id))
(let [page-id (:current-page-id state) (let [page-id (:current-page-id state)
objects (dwc/lookup-page-objects state page-id) objects (dwc/lookup-page-objects state page-id)
@ -529,7 +531,6 @@
(get state :workspace-data) (get state :workspace-data)
(get state :workspace-libraries))] (get state :workspace-libraries))]
;; ===== Uncomment this to debug =====
(log/debug :msg "UPDATE-COMPONENT finished" :js/rchanges rchanges) (log/debug :msg "UPDATE-COMPONENT finished" :js/rchanges rchanges)
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))
@ -552,7 +553,6 @@
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
;; ===== Uncomment this to debug =====
(log/info :msg "SYNC-FILE" :file (str (or file-id "local"))) (log/info :msg "SYNC-FILE" :file (str (or file-id "local")))
(let [library-changes [(dwlh/generate-sync-library :components file-id state) (let [library-changes [(dwlh/generate-sync-library :components file-id state)
(dwlh/generate-sync-library :colors file-id state) (dwlh/generate-sync-library :colors file-id state)
@ -566,7 +566,6 @@
uchanges (d/concat [] uchanges (d/concat []
(->> library-changes (remove nil?) (map second) (flatten)) (->> library-changes (remove nil?) (map second) (flatten))
(->> file-changes (remove nil?) (map second) (flatten)))] (->> file-changes (remove nil?) (map second) (flatten)))]
;; ===== Uncomment this to debug =====
(log/debug :msg "SYNC-FILE finished" :js/rchanges rchanges) (log/debug :msg "SYNC-FILE finished" :js/rchanges rchanges)
(rx/concat (rx/concat
(rx/of (dm/hide-tag :sync-dialog)) (rx/of (dm/hide-tag :sync-dialog))
@ -593,14 +592,12 @@
(ptk/reify ::sync-file-2nd-stage (ptk/reify ::sync-file-2nd-stage
ptk/WatchEvent ptk/WatchEvent
(watch [_ state stream] (watch [_ state stream]
;; ===== Uncomment this to debug =====
(log/info :msg "SYNC-FILE (2nd stage)" :file (str (or file-id "local"))) (log/info :msg "SYNC-FILE (2nd stage)" :file (str (or file-id "local")))
(let [[rchanges1 uchanges1] (dwlh/generate-sync-file :components nil state) (let [[rchanges1 uchanges1] (dwlh/generate-sync-file :components nil state)
[rchanges2 uchanges2] (dwlh/generate-sync-library :components file-id state) [rchanges2 uchanges2] (dwlh/generate-sync-library :components file-id state)
rchanges (d/concat rchanges1 rchanges2) rchanges (d/concat rchanges1 rchanges2)
uchanges (d/concat uchanges1 uchanges2)] uchanges (d/concat uchanges1 uchanges2)]
(when rchanges (when rchanges
;; ===== Uncomment this to debug =====
(log/debug :msg "SYNC-FILE (2nd stage) finished" :js/rchanges rchanges) (log/debug :msg "SYNC-FILE (2nd stage) finished" :js/rchanges rchanges)
(rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true}))))))) (rx/of (dwc/commit-changes rchanges uchanges {:commit-local? true})))))))

File diff suppressed because it is too large Load diff