🎉 Add many improvements on nil handling and code structure on changes impl.

This commit is contained in:
Andrey Antukh 2021-07-26 21:06:39 +02:00 committed by Andrés Moya
parent d61a86cad1
commit 394e6b08ad
2 changed files with 100 additions and 91 deletions

View file

@ -15,6 +15,20 @@
[app.common.pages.spec :as spec] [app.common.pages.spec :as spec]
[app.common.spec :as us])) [app.common.spec :as us]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Specific helpers
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defn- without-obj
"Clear collection from specified obj and without nil values."
[coll o]
(into [] (filter #(not= % o)) coll))
(defn vec-without-nils
[coll]
(into [] (remove nil?) coll))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Page Transformation Changes ;; Page Transformation Changes
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@ -54,45 +68,50 @@
(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 component-id frame-id parent-id [data {:keys [id obj page-id component-id frame-id parent-id index ignore-touched]}]
index ignore-touched]}] (letfn [(update-parent-shapes [shapes]
(letfn [(update-fn [data] ;; Ensure that shapes is always a vector.
(let [parent-id (or parent-id frame-id) (let [shapes (into [] shapes)]
objects (:objects data)
obj (assoc obj
:frame-id frame-id
:parent-id parent-id
:id id)]
(if (and (or (nil? parent-id) (contains? objects parent-id))
(or (nil? frame-id) (contains? objects frame-id)))
(-> data
(update :objects assoc id obj)
(update-in [:objects parent-id :shapes]
(fn [shapes]
(let [shapes (or shapes [])]
(cond (cond
(some #{id} shapes) (some #{id} shapes)
shapes shapes
(nil? index) (nil? index)
(if (= :frame (:type obj)) (if (= :frame (:type obj))
(d/concat [id] shapes) (into [id] shapes)
(conj shapes id)) (conj shapes id))
:else :else
(cph/insert-at-index shapes index [id]))))) (cph/insert-at-index shapes index [id]))))
(cond-> (and (:shape-ref (get-in data [:objects parent-id])) (update-parent [parent]
(not= parent-id frame-id) (-> parent
(update :shapes update-parent-shapes)
(update :shapes vec-without-nils)
(cond-> (and (:shape-ref parent)
(not= (:id parent) frame-id)
(not ignore-touched)) (not ignore-touched))
(-> (-> (update :touched cph/set-touched-group :shapes-group)
(update-in [:objects parent-id :touched] (dissoc :remote-synced?)))))
cph/set-touched-group :shapes-group)
(d/dissoc-in [:objects parent-id :remote-synced?])))) (update-objects [objects parent-id]
data)))] (if (and (or (nil? parent-id) (contains? objects parent-id))
(or (nil? frame-id) (contains? objects frame-id)))
(-> objects
(assoc id (-> obj
(assoc :frame-id frame-id)
(assoc :parent-id parent-id)
(assoc :id id)))
(update parent-id update-parent))
objects))
(update-container [data]
(let [parent-id (or parent-id frame-id)]
(update data :objects update-objects parent-id)))]
(if page-id (if page-id
(d/update-in-when data [:pages-index page-id] update-fn) (d/update-in-when data [:pages-index page-id] update-container)
(d/update-in-when data [:components component-id] update-fn)))) (d/update-in-when data [:components component-id] update-container))))
(defmethod process-change :mod-obj (defmethod process-change :mod-obj
[data {:keys [id page-id component-id operations]}] [data {:keys [id page-id component-id operations]}]
@ -107,32 +126,27 @@
(defmethod process-change :del-obj (defmethod process-change :del-obj
[data {:keys [page-id component-id id ignore-touched]}] [data {:keys [page-id component-id id ignore-touched]}]
(letfn [(delete-object [objects id] (letfn [(delete-from-parent [parent]
(let [parent (update parent :shapes without-obj id)]
(cond-> parent
(and (:shape-ref parent)
(not ignore-touched))
(-> (update :touched cph/set-touched-group :shapes-group)
(dissoc :remote-synced?)))))
(delete-from-objects [objects]
(if-let [target (get objects id)] (if-let [target (get objects id)]
(let [parent-id (cph/get-parent id objects) (let [parent-id (or (:parent-id target)
frame-id (:frame-id target) (:frame-id target))
parent (get objects parent-id) children (cph/get-children id objects)]
objects (dissoc objects id)] (-> (reduce dissoc objects children)
(cond-> objects (dissoc id)
(and (not= parent-id frame-id) (d/update-when parent-id delete-from-parent)))
(#{:group :svg-raw} (:type parent)))
(update-in [parent-id :shapes] (fn [s] (filterv #(not= % id) s)))
(and (:shape-ref parent) (not ignore-touched))
(->
(update-in [parent-id :touched] cph/set-touched-group :shapes-group)
(d/dissoc-in [parent-id :remote-synced?]))
(contains? objects frame-id)
(update-in [frame-id :shapes] (fn [s] (filterv #(not= % id) s)))
(seq (:shapes target)) ; Recursive delete all
; dependend objects
(as-> $ (reduce delete-object $ (:shapes target)))))
objects))] objects))]
(if page-id (if page-id
(d/update-in-when data [:pages-index page-id :objects] delete-object id) (d/update-in-when data [:pages-index page-id :objects] delete-from-objects)
(d/update-in-when data [:components component-id :objects] delete-object id)))) (d/update-in-when data [:components component-id :objects] delete-from-objects))))
;; reg-objects operation "regenerates" the geometry and selrect of the parent groups ;; reg-objects operation "regenerates" the geometry and selrect of the parent groups
(defmethod process-change :reg-objects (defmethod process-change :reg-objects
@ -193,23 +207,22 @@
;; and it cannot be moved. ;; and it cannot be moved.
(let [mask-id (first prev-shapes) (let [mask-id (first prev-shapes)
other-ids (rest prev-shapes) other-ids (rest prev-shapes)
not-mask-shapes (strip-id shapes mask-id) not-mask-shapes (without-obj shapes mask-id)
new-index (if (nil? index) nil (max (dec index) 0)) new-index (if (nil? index) nil (max (dec index) 0))
new-shapes (insert-items other-ids new-index not-mask-shapes)] new-shapes (insert-items other-ids new-index not-mask-shapes)]
(d/concat [mask-id] new-shapes)))) (d/concat [mask-id] new-shapes))))
(strip-id [coll id]
(filterv #(not= % id) coll))
(add-to-parent [parent index shapes] (add-to-parent [parent index shapes]
(cond-> parent (let [parent (-> parent
true
(update :shapes check-insert-items parent index shapes) (update :shapes check-insert-items parent index shapes)
;; We need to ensure that no `nil` in the
;; shapes list after adding all the
;; incoming shapes to the parent.
(update :shapes vec-without-nils))]
(cond-> parent
(and (:shape-ref parent) (= (:type parent) :group) (not ignore-touched)) (and (:shape-ref parent) (= (:type parent) :group) (not ignore-touched))
(-> (-> (update :touched cph/set-touched-group :shapes-group)
(update :touched cph/set-touched-group :shapes-group) (dissoc :remote-synced?)))))
(dissoc :remote-synced?))))
(remove-from-old-parent [cpindex objects shape-id] (remove-from-old-parent [cpindex objects shape-id]
(let [prev-parent-id (get cpindex shape-id)] (let [prev-parent-id (get cpindex shape-id)]
@ -225,12 +238,9 @@
(not ignore-touched))] (not ignore-touched))]
(-> objects (-> objects
(d/update-in-when [pid :shapes] strip-id sid) (d/update-in-when [pid :shapes] without-obj sid)
(d/update-in-when [pid :shapes] vec-without-nils)
(cond-> component? (cond-> component? (d/update-when pid #(-> %
(d/update-when
pid
#(-> %
(update :touched cph/set-touched-group :shapes-group) (update :touched cph/set-touched-group :shapes-group)
(dissoc :remote-synced?))))))))) (dissoc :remote-synced?)))))))))
@ -240,8 +250,7 @@
;; Updates the frame-id references that might be outdated ;; Updates the frame-id references that might be outdated
(assign-frame-id [frame-id objects id] (assign-frame-id [frame-id objects id]
(let [objects (-> objects (let [objects (d/update-when objects id assoc :frame-id frame-id)
(d/update-when id assoc :frame-id frame-id))
obj (get objects id)] obj (get objects id)]
(cond-> objects (cond-> objects
;; If we moving frame, the parent frame is the root ;; If we moving frame, the parent frame is the root

View file

@ -214,7 +214,7 @@
(if (some #{id} acc) (if (some #{id} acc)
acc acc
(conj acc id))) (conj acc id)))
prev-ids (vec prev-ids)
ids)) ids))
(defn select-toplevel-shapes (defn select-toplevel-shapes