♻️ Refactor update attrs

* Extract token update from update-attrs

* Split update-attrs in smaller functions for legibility and reusability
This commit is contained in:
Pablo Alba 2025-05-05 18:14:04 +02:00 committed by GitHub
parent 86a498fc29
commit ee0ba15f9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1605,6 +1605,75 @@
:val dest-tokens :val dest-tokens
:ignore-touched true}]})))))) :ignore-touched true}]}))))))
(defn- generate-update-tokens
[changes container dest-shape origin-shape touched omit-touched?]
(let [attrs (->> (seq (keys ctk/sync-attrs))
;; We don't update the flex-child attrs
(remove #(= :layout-grid-cells %)))
applied-tokens (reduce (fn [applied-tokens attr]
(let [attr-group (get ctk/sync-attrs attr)
token-attrs (cto/shape-attr->token-attrs attr)]
(if (not (and (touched attr-group)
omit-touched?))
(into applied-tokens token-attrs)
applied-tokens)))
#{}
attrs)]
(cond-> changes
(seq applied-tokens)
(update-tokens container dest-shape origin-shape applied-tokens))))
(defn- add-update-attr-changes
[changes dest-shape container roperations uoperations]
(let [all-parents (cfh/get-parent-ids (:objects container)
(:id dest-shape))]
(-> changes
(update :redo-changes conj (make-change
container
{:type :mod-obj
:id (:id dest-shape)
:operations roperations}))
(update :redo-changes conj (make-change
container
{:type :reg-objects
:shapes all-parents}))
(update :undo-changes conj (make-change
container
{:type :mod-obj
:id (:id dest-shape)
:operations (vec uoperations)}))
(update :undo-changes concat [(make-change
container
{:type :reg-objects
:shapes all-parents})]))))
(defn- add-update-attr-operations
[attr dest-shape origin-shape roperations uoperations touched]
(let [;; position-data is a special case because can be affected by :geometry-group and :content-group
;; so, if the position-data changes but the geometry is touched we need to reset the position-data
;; so it's calculated again
reset-pos-data?
(and (cfh/text-shape? origin-shape)
(= attr :position-data)
(not= (get origin-shape attr) (get dest-shape attr))
(touched :geometry-group))
roperation {:type :set
:attr attr
:val (cond
;; If position data changes and the geometry group is touched
;; we need to put to nil so we can regenerate it
reset-pos-data? nil
:else (get origin-shape attr))
:ignore-touched true}
uoperation {:type :set
:attr attr
:val (get dest-shape attr)
:ignore-touched true}]
[(conj roperations roperation)
(conj uoperations uoperation)]))
(defn- update-attrs (defn- update-attrs
"The main function that implements the attribute sync algorithm. Copy "The main function that implements the attribute sync algorithm. Copy
attributes that have changed in the origin shape to the dest shape. attributes that have changed in the origin shape to the dest shape.
@ -1640,92 +1709,26 @@
(remove ctk/swap-keep-attrs) (remove ctk/swap-keep-attrs)
;; We don't do automatic update of the `layout-grid-cells` property. ;; We don't do automatic update of the `layout-grid-cells` property.
(remove #(= :layout-grid-cells %))) (remove #(= :layout-grid-cells %)))
applied-tokens #{}
roperations [] roperations []
uoperations '()] uoperations '()]
(let [attr (first attrs)] (let [attr (first attrs)]
(if (nil? attr) (if (nil? attr)
(if (and (empty? roperations) (empty? applied-tokens)) (cond-> changes
changes (seq roperations)
(let [all-parents (cfh/get-parent-ids (:objects container) (add-update-attr-changes dest-shape container roperations uoperations)
(:id dest-shape)) :always
(generate-update-tokens container dest-shape origin-shape touched omit-touched?))
;; Sync tokens of attributes ignored above. (let [attr-group (get ctk/sync-attrs attr)
;; FIXME: this probably may be merged with the other calculation [roperations' uoperations']
;; of applied tokens, below, and to the calculation only once (if (or (= (get origin-shape attr) (get dest-shape attr))
;; for all sync-attrs. (and (touched attr-group) omit-touched?))
applied-tokens (reduce (fn [applied-tokens attr] [roperations uoperations]
(let [attr-group (get ctk/sync-attrs attr) (add-update-attr-operations attr dest-shape origin-shape roperations uoperations touched))]
token-attrs (cto/shape-attr->token-attrs attr)] (recur (next attrs)
(if (not (and (touched attr-group) roperations'
omit-touched?)) uoperations')))))))
(into applied-tokens token-attrs)
applied-tokens)))
applied-tokens
ctk/swap-keep-attrs)]
(cond-> changes
(seq roperations)
(-> (update :redo-changes conj (make-change
container
{:type :mod-obj
:id (:id dest-shape)
:operations roperations}))
(update :redo-changes conj (make-change
container
{:type :reg-objects
:shapes all-parents}))
(update :undo-changes conj (make-change
container
{:type :mod-obj
:id (:id dest-shape)
:operations (vec uoperations)}))
(update :undo-changes concat [(make-change
container
{:type :reg-objects
:shapes all-parents})]))
(seq applied-tokens)
(update-tokens container dest-shape origin-shape applied-tokens))))
(let [;; position-data is a special case because can be affected by :geometry-group and :content-group
;; so, if the position-data changes but the geometry is touched we need to reset the position-data
;; so it's calculated again
reset-pos-data?
(and (cfh/text-shape? origin-shape)
(= attr :position-data)
(not= (get origin-shape attr) (get dest-shape attr))
(touched :geometry-group))
roperation {:type :set
:attr attr
:val (cond
;; If position data changes and the geometry group is touched
;; we need to put to nil so we can regenerate it
reset-pos-data? nil
:else (get origin-shape attr))
:ignore-touched true}
uoperation {:type :set
:attr attr
:val (get dest-shape attr)
:ignore-touched true}
attr-group (get ctk/sync-attrs attr)
token-attrs (cto/shape-attr->token-attrs attr)
applied-tokens' (cond-> applied-tokens
(not (and (touched attr-group)
omit-touched?))
(into token-attrs))]
(if (or (= (get origin-shape attr) (get dest-shape attr))
(and (touched attr-group) omit-touched?))
(recur (next attrs)
applied-tokens'
roperations
uoperations)
(recur (next attrs)
applied-tokens'
(conj roperations roperation)
(conj uoperations uoperation)))))))))
(defn- propagate-attrs (defn- propagate-attrs
"Helper that puts the origin attributes (attrs) into dest but only if "Helper that puts the origin attributes (attrs) into dest but only if