♻️ Simplify container type management

This commit is contained in:
Andrés Moya 2020-11-18 13:55:45 +01:00
parent ebb7410e5b
commit 2582766a89
3 changed files with 172 additions and 171 deletions

View file

@ -435,10 +435,10 @@
:internal.file/recent-colors :internal.file/recent-colors
:internal.file/media])) :internal.file/media]))
(s/def ::container-type #{:page :component}) (s/def :internal.container/type #{:page :component})
(s/def ::container (s/def ::container
(s/keys :req-un [::container-type (s/keys :req-un [:internal.container/type
::id ::id
::name ::name
:internal.page/objects])) :internal.page/objects]))

View file

@ -43,24 +43,24 @@
nil))) nil)))
(defn make-container (defn make-container
[page-or-component container-type] [page-or-component type]
(assoc page-or-component (assoc page-or-component
:container-type container-type)) :type type))
(defn is-page (defn page?
[container] [container]
(= (:container-type container) :page)) (= (:type container) :page))
(defn is-component (defn component?
[container] [container]
(= (:container-type container) :component)) (= (:type container) :component))
(defn get-container (defn get-container
[container-id container-type local-file] [id type local-file]
(-> (if (= container-type :page) (-> (if (= type :page)
(get-in local-file [:pages-index container-id]) (get-in local-file [:pages-index id])
(get-in local-file [:components container-id])) (get-in local-file [:components id]))
(assoc :container-type container-type))) (assoc :type type)))
(defn get-shape (defn get-shape
[container shape-id] [container shape-id]

View file

@ -179,7 +179,7 @@
(a page or a component) that are linked to the given library." (a page or a component) that are linked to the given library."
[asset-type library-id state container] [asset-type library-id state container]
(if (= (:container-type container) :page) (if (cph/page? container)
(log/debug :msg "Sync page in local file" :page-id (:id container)) (log/debug :msg "Sync page in local file" :page-id (:id container))
(log/debug :msg "Sync component in local library" :component-id (:id container))) (log/debug :msg "Sync component in local library" :component-id (:id container)))
@ -250,36 +250,36 @@
(get state :workspace-libraries) (get state :workspace-libraries)
false)) false))
(defn- generate-sync-text-shape [shape page-id component-id update-node] (defn- generate-sync-text-shape [shape container update-node]
(let [old-content (:content shape) (let [old-content (:content shape)
new-content (ut/map-node update-node old-content) new-content (ut/map-node update-node old-content)
rchanges [(d/without-nils {:type :mod-obj rchanges [(as-> {:type :mod-obj
:page-id page-id :id (:id shape)
:component-id component-id :operations [{:type :set
:id (:id shape) :attr :content
:operations [{:type :set :val new-content}]} $
:attr :content (if (cph/page? container)
:val new-content}]})] (assoc $ :page-id (:id container))
lchanges [(d/without-nils {:type :mod-obj (assoc $ :component-id (:id container))))]
:page-id page-id uchanges [(as-> {:type :mod-obj
:component-id component-id :id (:id shape)
:id (:id shape) :operations [{:type :set
:operations [{:type :set :attr :content
:attr :content :val old-content}]} $
:val old-content}]})]] (if (cph/page? container)
(assoc $ :page-id (:id container))
(assoc $ :component-id (:id container))))]]
(if (= new-content old-content) (if (= new-content old-content)
empty-changes empty-changes
[rchanges lchanges]))) [rchanges uchanges])))
(defmethod generate-sync-shape :colors (defmethod generate-sync-shape :colors
[_ library-id state container shape] [_ library-id state container shape]
;; Synchronize a shape that uses some colors of the library. The value of the ;; Synchronize a shape that uses some colors of the library. The value of the
;; color in the library is copied to the shape. ;; color in the library is copied to the shape.
(let [page-id (when (cph/is-page container) (:id container)) (let [colors (get-assets library-id :colors state)]
component-id (when (cph/is-component container) (:id container))
colors (get-assets library-id :colors state)]
(if (= :text (:type shape)) (if (= :text (:type shape))
(let [update-node (fn [node] (let [update-node (fn [node]
(if-let [color (get colors (:fill-color-ref-id node))] (if-let [color (get colors (:fill-color-ref-id node))]
@ -288,7 +288,7 @@
:fill-opacity (:opacity color) :fill-opacity (:opacity color)
:fill-color-gradient (:gradient color)) :fill-color-gradient (:gradient color))
node))] node))]
(generate-sync-text-shape shape page-id component-id update-node)) (generate-sync-text-shape shape container update-node))
(loop [attrs (seq color-sync-attrs) (loop [attrs (seq color-sync-attrs)
roperations [] roperations []
uoperations []] uoperations []]
@ -296,16 +296,18 @@
(if (nil? attr) (if (nil? attr)
(if (empty? roperations) (if (empty? roperations)
empty-changes empty-changes
(let [rchanges [(d/without-nils {:type :mod-obj (let [rchanges [(as-> {:type :mod-obj
:page-id page-id :id (:id shape)
:component-id component-id :operations roperations} $
:id (:id shape) (if (cph/page? container)
:operations roperations})] (assoc $ :page-id (:id container))
uchanges [(d/without-nils {:type :mod-obj (assoc $ :component-id (:id container))))]
:page-id page-id uchanges [(as-> {:type :mod-obj
:component-id component-id :id (:id shape)
:id (:id shape) :operations uoperations} $
:operations uoperations})]] (if (cph/page? container)
(assoc $ :page-id (:id container))
(assoc $ :component-id (:id container))))]]
[rchanges uchanges])) [rchanges uchanges]))
(if-not (contains? shape attr-ref-id) (if-not (contains? shape attr-ref-id)
(recur (next attrs) (recur (next attrs)
@ -329,14 +331,12 @@
;; Synchronize a shape that uses some typographies of the library. The attributes ;; Synchronize a shape that uses some typographies of the library. The attributes
;; of the typography are copied to the shape." ;; of the typography are copied to the shape."
(let [page-id (when (cph/is-page container) (:id container)) (let [typographies (get-assets library-id :typographies state)
component-id (when (cph/is-component container) (:id container))
typographies (get-assets library-id :typographies state)
update-node (fn [node] update-node (fn [node]
(if-let [typography (get typographies (:typography-ref-id node))] (if-let [typography (get typographies (:typography-ref-id node))]
(merge node (d/without-keys typography [:name :id])) (merge node (d/without-keys typography [:name :id]))
node))] node))]
(generate-sync-text-shape shape page-id component-id update-node))) (generate-sync-text-shape shape container update-node)))
;; ---- Component synchronization helpers ---- ;; ---- Component synchronization helpers ----
@ -764,36 +764,38 @@
(defn- remove-shape (defn- remove-shape
[shape container] [shape container]
(let [page-id (when (cph/is-page container) (:id container)) (let [objects (get container :objects)
component-id (when (cph/is-component container) (:id container))
objects (get container :objects)
parents (cph/get-parents (:id shape) objects) parents (cph/get-parents (:id shape) objects)
children (cph/get-children (:id shape) objects) children (cph/get-children (:id shape) objects)
add-change (fn [id] add-change (fn [id]
(let [shape' (get objects id)] (let [shape' (get objects id)]
(d/without-nils {:type :add-obj (as-> {:type :add-obj
:id id :id id
:page-id page-id :index (cph/position-on-parent id objects)
:component-id component-id :parent-id (:parent-id shape')
:index (cph/position-on-parent id objects) :obj shape'} $
:frame-id (:frame-id shape') (cond-> $
:parent-id (:parent-id shape') (:frame-id shape')
:obj shape'}))) (assoc :frame-id (:frame-id shape')))
(if (cph/page? container)
(assoc $ :page-id (:id container))
(assoc $ :component-id (:id container))))))
rchanges [(d/without-nils {:type :del-obj rchanges [(as-> {:type :del-obj
:page-id page-id :id (:id shape)} $
:component-id component-id (if (cph/page? container)
:id (:id shape)})] (assoc $ :page-id (:id container))
(assoc $ :component-id (:id container))))]
uchanges (d/concat uchanges (d/concat
[(add-change (:id shape))] [(add-change (:id shape))]
(map add-change children) (map add-change children)
[(d/without-nils {:type :reg-objects [(as-> {:type :reg-objects
:page-id page-id :shapes (vec parents)} $
:component-id component-id (if (cph/page? container)
:shapes (vec parents)})])] (assoc $ :page-id (:id container))
(assoc $ :component-id (:id container))))])]
[rchanges uchanges])) [rchanges uchanges]))
(defn- move-shape (defn- move-shape
@ -804,102 +806,102 @@
index-before index-before
" -> " " -> "
index-after)) index-after))
(let [page-id (when (cph/is-page container) (:id container)) (let [rchanges [(as-> {:type :mov-objects
component-id (when (cph/is-component container) (:id container))] :parent-id (:parent-id shape)
(let [rchanges [(d/without-nils {:type :mov-objects :shapes [(:id shape)]
:parent-id (:parent-id shape) :index index-after} $
:shapes [(:id shape)] (if (cph/page? container)
:index index-after (assoc $ :page-id (:id container))
:page-id page-id (assoc $ :component-id (:id container))))]
:component-id component-id})] uchanges [(as-> {:type :mov-objects
uchanges [(d/without-nils {:type :mov-objects :parent-id (:parent-id shape)
:parent-id (:parent-id shape) :shapes [(:id shape)]
:shapes [(:id shape)] :index index-before} $
:index index-before (if (cph/page? container)
:page-id page-id (assoc $ :page-id (:id container))
:component-id component-id})]] (assoc $ :component-id (:id container))))]]
[rchanges uchanges]))) [rchanges uchanges]))
(defn- remove-component-and-ref (defn- remove-component-and-ref
[shape container] [shape container]
(let [page-id (when (cph/is-page container) (:id container)) [[(as-> {:type :mod-obj
component-id (when (cph/is-component container) (:id container))] :id (:id shape)
[[(d/without-nils {:type :mod-obj :operations [{:type :set
:id (:id shape) :attr :component-root?
:page-id page-id :val nil}
:component-id component-id {:type :set
:operations [{:type :set :attr :component-id
:attr :component-root? :val nil}
:val nil} {:type :set
{:type :set :attr :component-file
:attr :component-id :val nil}
:val nil} {:type :set
{:type :set :attr :shape-ref
:attr :component-file :val nil}
:val nil} {:type :set-touched
{:type :set :touched nil}]} $
:attr :shape-ref (if (cph/page? container)
:val nil} (assoc $ :page-id (:id container))
{:type :set-touched (assoc $ :component-id (:id container))))]
:touched nil}]})] [(as-> {:type :mod-obj
[(d/without-nils {:type :mod-obj :id (:id shape)
:id (:id shape) :operations [{:type :set
:page-id page-id :attr :component-root?
:component-id component-id :val (:component-root? shape)}
:operations [{:type :set {:type :set
:attr :component-root? :attr :component-id
:val (:component-root? shape)} :val (:component-id shape)}
{:type :set {:type :set
:attr :component-id :attr :component-file
:val (:component-id shape)} :val (:component-file shape)}
{:type :set {:type :set
:attr :component-file :attr :shape-ref
:val (:component-file shape)} :val (:shape-ref shape)}
{:type :set {:type :set-touched
:attr :shape-ref :touched (:touched shape)}]} $
:val (:shape-ref shape)} (if (cph/page? container)
{:type :set-touched (assoc $ :page-id (:id container))
:touched (:touched shape)}]})]])) (assoc $ :component-id (:id container))))]])
(defn- remove-ref (defn- remove-ref
[shape container] [shape container]
(let [page-id (when (cph/is-page container) (:id container)) [[(as-> {:type :mod-obj
component-id (when (cph/is-component container) (:id container))] :id (:id shape)
[[(d/without-nils {:type :mod-obj :operations [{:type :set
:id (:id shape) :attr :shape-ref
:page-id page-id :val nil}
:component-id component-id {:type :set-touched
:operations [{:type :set :touched nil}]} $
:attr :shape-ref (if (cph/page? container)
:val nil} (assoc $ :page-id (:id container))
{:type :set-touched (assoc $ :component-id (:id container))))]
:touched nil}]})] [(as-> {:type :mod-obj
[(d/without-nils {:type :mod-obj :id (:id shape)
:id (:id shape) :operations [{:type :set
:page-id page-id :attr :shape-ref
:component-id component-id :val (:shape-ref shape)}
:operations [{:type :set {:type :set-touched
:attr :shape-ref :touched (:touched shape)}]} $
:val (:shape-ref shape)} (if (cph/page? container)
{:type :set-touched (assoc $ :page-id (:id container))
:touched (:touched shape)}]})]])) (assoc $ :component-id (:id container))))]])
(defn- reset-touched (defn- reset-touched
[shape container] [shape container]
(let [page-id (when (cph/is-page container) (:id container)) [[(as-> {:type :mod-obj
component-id (when (cph/is-component container) (:id container))] :id (:id shape)
[[(d/without-nils {:type :mod-obj :operations [{:type :set-touched
:id (:id shape) :touched nil}]} $
:page-id page-id (if (cph/page? container)
:component-id component-id (assoc $ :page-id (:id container))
:operations [{:type :set-touched (assoc $ :component-id (:id container))))]
:touched nil}]})] [(as-> {:type :mod-obj
[(d/without-nils {:type :mod-obj :id (:id shape)
:id (:id shape) :operations [{:type :set-touched
:page-id page-id :touched (:touched shape)}]} $
:component-id component-id (if (cph/page? container)
:operations [{:type :set-touched (assoc $ :page-id (:id container))
:touched (:touched shape)}]})]])) (assoc $ :component-id (:id container))))]])
(defn- update-attrs (defn- update-attrs
"The main function that implements the sync algorithm. Copy "The main function that implements the sync algorithm. Copy
@ -920,13 +922,10 @@
(log/info :msg (str "SYNC " (log/info :msg (str "SYNC "
(:name origin-shape) (:name origin-shape)
" -> " " -> "
(if (cph/is-page container) "[P] " "[C] ") (if (cph/page? container) "[P] " "[C] ")
(:name dest-shape))) (:name dest-shape)))
(let [page-id (when (cph/is-page container) (:id container)) (let [; The position attributes need a special sync algorith, because we do
component-id (when (cph/is-component container) (:id container))
; The position attributes need a special sync algorith, because we do
; not synchronize the absolute position, but the position relative of ; not synchronize the absolute position, but the position relative of
; the container shape of the component. ; the container shape of the component.
new-pos (calc-new-pos dest-shape origin-shape dest-root origin-root) new-pos (calc-new-pos dest-shape origin-shape dest-root origin-root)
@ -966,16 +965,18 @@
:else :else
uoperations) uoperations)
rchanges [(d/without-nils {:type :mod-obj rchanges [(as-> {:type :mod-obj
:id (:id dest-shape) :id (:id dest-shape)
:page-id page-id :operations roperations} $
:component-id component-id (if (cph/page? container)
:operations roperations})] (assoc $ :page-id (:id container))
uchanges [(d/without-nils {:type :mod-obj (assoc $ :component-id (:id container))))]
:id (:id dest-shape) uchanges [(as-> {:type :mod-obj
:page-id page-id :id (:id dest-shape)
:component-id component-id :operations uoperations} $
:operations uoperations})]] (if (cph/page? container)
(assoc $ :page-id (:id container))
(assoc $ :component-id (:id container))))]]
[rchanges uchanges]) [rchanges uchanges])
(if-not (contains? dest-shape attr) (if-not (contains? dest-shape attr)