Apply token value changes to shapes in all pages

This commit is contained in:
Andrés Moya 2025-01-24 16:44:53 +01:00
parent e486bb4bec
commit f4f0478975
9 changed files with 193 additions and 132 deletions

View file

@ -84,7 +84,9 @@
(defn transform-fill (defn transform-fill
([state ids color transform] (transform-fill state ids color transform nil)) ([state ids color transform] (transform-fill state ids color transform nil))
([state ids color transform options] ([state ids color transform options]
(let [objects (dsh/lookup-page-objects state) (let [page-id (or (get options :page-id)
(get state :current-page-id))
objects (dsh/lookup-page-objects state page-id)
is-text? #(= :text (:type (get objects %))) is-text? #(= :text (:type (get objects %)))
text-ids (filter is-text? ids) text-ids (filter is-text? ids)
shape-ids (remove is-text? ids) shape-ids (remove is-text? ids)

View file

@ -187,5 +187,3 @@
(if (= val ::does-not-exist) (if (= val ::does-not-exist)
(swap! storage/user dissoc skey) (swap! storage/user dissoc skey)
(swap! storage/user assoc skey val))))) (swap! storage/user assoc skey val)))))

View file

@ -328,14 +328,17 @@
(defn- calculate-modifiers (defn- calculate-modifiers
([state modif-tree] ([state modif-tree]
(calculate-modifiers state false false modif-tree)) (calculate-modifiers state false false modif-tree nil))
([state ignore-constraints ignore-snap-pixel modif-tree] ([state ignore-constraints ignore-snap-pixel modif-tree page-id]
(calculate-modifiers state ignore-constraints ignore-snap-pixel modif-tree nil)) (calculate-modifiers state ignore-constraints ignore-snap-pixel modif-tree page-id nil))
([state ignore-constraints ignore-snap-pixel modif-tree params] ([state ignore-constraints ignore-snap-pixel modif-tree page-id params]
(let [objects (let [page-id
(dsh/lookup-page-objects state) (or page-id (:current-page-id state))
objects
(dsh/lookup-page-objects state page-id)
snap-pixel? snap-pixel?
(and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid)) (and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid))
@ -402,7 +405,9 @@
(ptk/reify ::set-modifiers (ptk/reify ::set-modifiers
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(assoc state :workspace-modifiers (calculate-modifiers state ignore-constraints ignore-snap-pixel modif-tree params)))))) (let [page-id (:current-page-id state)
modifiers (calculate-modifiers state ignore-constraints ignore-snap-pixel modif-tree page-id params)]
(assoc state :workspace-modifiers modifiers))))))
(def ^:private (def ^:private
xf-rotation-shape xf-rotation-shape
@ -438,11 +443,12 @@
;; - It consideres the center for everyshape instead of the center of the total selrect ;; - It consideres the center for everyshape instead of the center of the total selrect
;; - The angle param is the desired final value, not a delta ;; - The angle param is the desired final value, not a delta
(defn set-delta-rotation-modifiers (defn set-delta-rotation-modifiers
[angle shapes {:keys [center delta?] :or {center nil delta? false}}] [angle shapes {:keys [center delta? page-id] :or {center nil delta? false}}]
(ptk/reify ::set-delta-rotation-modifiers (ptk/reify ::set-delta-rotation-modifiers
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [objects (dsh/lookup-page-objects state) (let [page-id (or page-id (:current-page-id state))
objects (dsh/lookup-page-objects state page-id)
ids ids
(->> shapes (->> shapes
(remove #(get % :blocked false)) (remove #(get % :blocked false))
@ -466,18 +472,19 @@
(apply-modifiers nil)) (apply-modifiers nil))
([{:keys [modifiers undo-transation? stack-undo? ignore-constraints ([{:keys [modifiers undo-transation? stack-undo? ignore-constraints
ignore-snap-pixel ignore-touched undo-group] ignore-snap-pixel ignore-touched undo-group page-id]
:or {undo-transation? true stack-undo? false ignore-constraints false :or {undo-transation? true stack-undo? false ignore-constraints false
ignore-snap-pixel false ignore-touched false}}] ignore-snap-pixel false ignore-touched false}}]
(ptk/reify ::apply-modifiers (ptk/reify ::apply-modifiers
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [text-modifiers (get state :workspace-text-modifier) (let [text-modifiers (get state :workspace-text-modifier)
objects (dsh/lookup-page-objects state) page-id (or page-id (:current-page-id state))
objects (dsh/lookup-page-objects state page-id)
object-modifiers object-modifiers
(if (some? modifiers) (if (some? modifiers)
(calculate-modifiers state ignore-constraints ignore-snap-pixel modifiers) (calculate-modifiers state ignore-constraints ignore-snap-pixel modifiers page-id)
(get state :workspace-modifiers)) (get state :workspace-modifiers))
ids ids
@ -519,6 +526,7 @@
:ignore-tree ignore-tree :ignore-tree ignore-tree
:ignore-touched ignore-touched :ignore-touched ignore-touched
:undo-group undo-group :undo-group undo-group
:page-id page-id
;; Attributes that can change in the transform. This way we don't have to check ;; Attributes that can change in the transform. This way we don't have to check
;; all the attributes ;; all the attributes
:attrs [:selrect :attrs [:selrect

View file

@ -524,7 +524,9 @@
(ptk/reify ::update-layout-child (ptk/reify ::update-layout-child
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [objects (dsh/lookup-page-objects state) (let [page-id (or (get options :page-id)
(get state :current-page-id))
objects (dsh/lookup-page-objects state page-id)
children-ids (->> ids (mapcat #(cfh/get-children-ids objects %))) children-ids (->> ids (mapcat #(cfh/get-children-ids objects %)))
parent-ids (->> ids (map #(cfh/get-parent-id objects %))) parent-ids (->> ids (map #(cfh/get-parent-id objects %)))
undo-id (js/Symbol)] undo-id (js/Symbol)]

View file

@ -446,7 +446,9 @@
(when (or (when (or
(and (features/active-feature? state "text-editor/v2") (nil? (:workspace-editor state))) (and (features/active-feature? state "text-editor/v2") (nil? (:workspace-editor state)))
(and (not (features/active-feature? state "text-editor/v2")) (nil? (get-in state [:workspace-editor-state id])))) (and (not (features/active-feature? state "text-editor/v2")) (nil? (get-in state [:workspace-editor-state id]))))
(let [objects (dsh/lookup-page-objects state) (let [page-id (or (get options :page-id)
(get state :current-page-id))
objects (dsh/lookup-page-objects state page-id)
shape (get objects id) shape (get objects id)
update-node? (some-fn txt/is-text-node? txt/is-paragraph-node?) update-node? (some-fn txt/is-text-node? txt/is-paragraph-node?)

View file

@ -314,7 +314,10 @@
(ptk/reify ::update-dimensions (ptk/reify ::update-dimensions
ptk/UpdateEvent ptk/UpdateEvent
(update [_ state] (update [_ state]
(let [objects (dsh/lookup-page-objects state) (let [page-id (or (get options :page-id)
(get state :current-page-id))
objects (dsh/lookup-page-objects state page-id)
get-modifier get-modifier
(fn [shape] (ctm/change-dimensions-modifiers shape attr value)) (fn [shape] (ctm/change-dimensions-modifiers shape attr value))
modif-tree modif-tree
@ -403,18 +406,18 @@
"Rotate shapes a fixed angle, from a keyboard action." "Rotate shapes a fixed angle, from a keyboard action."
([ids rotation] ([ids rotation]
(increase-rotation ids rotation nil)) (increase-rotation ids rotation nil))
([ids rotation params & options] ([ids rotation params & {:as options}]
(ptk/reify ::increase-rotation (ptk/reify ::increase-rotation
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [page-id (:current-page-id state) (let [page-id (or (:page-id options)
(:current-page-id state))
objects (dsh/lookup-page-objects state page-id) objects (dsh/lookup-page-objects state page-id)
shapes (->> ids (map #(get objects %)))] shapes (->> ids (map #(get objects %)))
options (assoc options :page-id page-id)]
(rx/concat (rx/concat
(rx/of (dwm/set-delta-rotation-modifiers rotation shapes params)) (rx/of (dwm/set-delta-rotation-modifiers rotation shapes (assoc params :page-id page-id)))
(rx/of (dwm/apply-modifiers options)))))))) (rx/of (dwm/apply-modifiers options))))))))
;; -- Move ---------------------------------------------------------- ;; -- Move ----------------------------------------------------------
(declare start-move) (declare start-move)
@ -788,13 +791,14 @@
(defn update-position (defn update-position
"Move shapes to a new position" "Move shapes to a new position"
([id position] (update-position id position nil)) ([id position] (update-position id position nil))
([id position opts] ([id position options]
(dm/assert! (uuid? id)) (dm/assert! (uuid? id))
(ptk/reify ::update-position (ptk/reify ::update-position
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [page-id (:current-page-id state) (let [page-id (or (get options :page-id)
(get state :current-page-id))
objects (dsh/lookup-page-objects state page-id) objects (dsh/lookup-page-objects state page-id)
shape (get objects id) shape (get objects id)
;; FIXME: performance rect ;; FIXME: performance rect
@ -809,8 +813,9 @@
modif-tree (dwm/create-modif-tree [id] (ctm/move-modifiers delta))] modif-tree (dwm/create-modif-tree [id] (ctm/move-modifiers delta))]
(rx/of (dwm/apply-modifiers {:modifiers modif-tree (rx/of (dwm/apply-modifiers {:modifiers modif-tree
:page-id page-id
:ignore-constraints false :ignore-constraints false
:ignore-touched (:ignore-touched opts) :ignore-touched (:ignore-touched options)
:ignore-snap-pixel true}))))))) :ignore-snap-pixel true})))))))
(defn position-shapes (defn position-shapes

View file

@ -52,8 +52,10 @@
(dwu/start-undo-transaction undo-id) (dwu/start-undo-transaction undo-id)
(dwsh/update-shapes shape-ids (fn [shape] (dwsh/update-shapes shape-ids (fn [shape]
(cond-> shape (cond-> shape
attributes-to-remove (update :applied-tokens #(apply (partial dissoc %) attributes-to-remove)) attributes-to-remove
:always (update :applied-tokens merge tokenized-attributes)))) (update :applied-tokens #(apply (partial dissoc %) attributes-to-remove))
:always
(update :applied-tokens merge tokenized-attributes))))
(when on-update-shape (when on-update-shape
(on-update-shape resolved-value shape-ids attributes)) (on-update-shape resolved-value shape-ids attributes))
(dwu/commit-undo-transaction undo-id)))))))))) (dwu/commit-undo-transaction undo-id))))))))))
@ -94,116 +96,152 @@
;; Shape Updates --------------------------------------------------------------- ;; Shape Updates ---------------------------------------------------------------
(defn update-shape-radius-all [value shape-ids] (defn update-shape-radius-all
([value shape-ids attributes] (update-shape-radius-all value shape-ids attributes nil))
([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions
(dwsh/update-shapes shape-ids (dwsh/update-shapes shape-ids
(fn [shape] (fn [shape]
(ctsr/set-radius-to-all-corners shape value)) (ctsr/set-radius-to-all-corners shape value))
{:reg-objects? true {:reg-objects? true
:ignore-touched true :ignore-touched true
:attrs ctt/border-radius-keys})) :page-id page-id
:attrs ctt/border-radius-keys})))
(defn update-shape-radius-for-corners [value shape-ids attributes] (defn update-shape-radius-for-corners
([value shape-ids attributes] (update-shape-radius-for-corners value shape-ids attributes nil))
([value shape-ids attributes page-id]
(dwsh/update-shapes shape-ids (dwsh/update-shapes shape-ids
(fn [shape] (fn [shape]
(ctsr/set-radius-for-corners shape attributes value)) (ctsr/set-radius-for-corners shape attributes value))
{:reg-objects? true {:reg-objects? true
:ignore-touched true :ignore-touched true
:attrs ctt/border-radius-keys})) :page-id page-id
:attrs ctt/border-radius-keys})))
(defn update-opacity [value shape-ids] (defn update-opacity
([value shape-ids attributes] (update-opacity value shape-ids attributes nil))
([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions
(when (<= 0 value 1) (when (<= 0 value 1)
(dwsh/update-shapes shape-ids (dwsh/update-shapes shape-ids
#(assoc % :opacity value) #(assoc % :opacity value)
{:ignore-touched true}))) {:ignore-touched true
:page-id page-id}))))
(defn update-rotation [value shape-ids] ;; FIXME: if attributes are not always present, maybe we have an
;; options here for pass optional value and preserve the correct and
;; uniform api across all functions (?)
(defn update-rotation
([value shape-ids attributes] (update-rotation value shape-ids attributes nil))
([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions
(ptk/reify ::update-shape-rotation (ptk/reify ::update-shape-rotation
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]
(rx/of (rx/of
(udw/trigger-bounding-box-cloaking shape-ids) (udw/trigger-bounding-box-cloaking shape-ids)
(udw/increase-rotation shape-ids value nil :ignore-touched true))))) (udw/increase-rotation shape-ids value nil
{:page-id page-id
:ignore-touched true}))))))
(defn update-stroke-width (defn update-stroke-width
[value shape-ids] ([value shape-ids attributes] (update-stroke-width value shape-ids attributes nil))
([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions
(dwsh/update-shapes shape-ids (dwsh/update-shapes shape-ids
(fn [shape] (fn [shape]
(when (seq (:strokes shape)) (when (seq (:strokes shape))
(assoc-in shape [:strokes 0 :stroke-width] value))) (assoc-in shape [:strokes 0 :stroke-width] value)))
{:reg-objects? true {:reg-objects? true
:ignore-touched true :ignore-touched true
:attrs [:strokes]})) :page-id page-id
:attrs [:strokes]})))
(defn update-color [f value shape-ids] (defn update-color [f value shape-ids page-id]
(when-let [tc (tinycolor/valid-color value)] (when-let [tc (tinycolor/valid-color value)]
(let [hex (tinycolor/->hex-string tc) (let [hex (tinycolor/->hex-string tc)
opacity (tinycolor/alpha tc)] opacity (tinycolor/alpha tc)]
(f shape-ids {:color hex :opacity opacity} 0 {:ignore-touched true})))) (f shape-ids {:color hex :opacity opacity} 0 {:ignore-touched true
:page-id page-id}))))
(defn update-fill (defn update-fill
[value shape-ids] ([value shape-ids attributes] (update-fill value shape-ids attributes nil))
(update-color wdc/change-fill value shape-ids)) ([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions
(update-color wdc/change-fill value shape-ids page-id)))
(defn update-stroke-color (defn update-stroke-color
[value shape-ids] ([value shape-ids attributes] (update-stroke-color value shape-ids attributes nil))
(update-color wdc/change-stroke-color value shape-ids)) ([value shape-ids _attributes page-id] ; The attributes param is needed to have the same arity that other update functions
(update-color wdc/change-stroke-color value shape-ids page-id)))
(defn update-fill-stroke [value shape-ids attributes] (defn update-fill-stroke
([value shape-ids attributes] (update-fill-stroke value shape-ids attributes nil))
([value shape-ids attributes page-id]
(ptk/reify ::update-fill-stroke (ptk/reify ::update-fill-stroke
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]
(rx/of (rx/of
(when (:fill attributes) (update-fill value shape-ids)) (when (:fill attributes) (update-fill value shape-ids attributes page-id))
(when (:stroke-color attributes) (update-stroke-color value shape-ids)))))) (when (:stroke-color attributes) (update-stroke-color value shape-ids attributes page-id)))))))
(defn update-shape-dimensions [value shape-ids attributes] (defn update-shape-dimensions
([value shape-ids attributes] (update-shape-dimensions value shape-ids attributes nil))
([value shape-ids attributes page-id]
(ptk/reify ::update-shape-dimensions (ptk/reify ::update-shape-dimensions
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]
(rx/of (rx/of
(when (:width attributes) (dwt/update-dimensions shape-ids :width value {:ignore-touched true})) (when (:width attributes) (dwt/update-dimensions shape-ids :width value {:ignore-touched true :page-id page-id}))
(when (:height attributes) (dwt/update-dimensions shape-ids :height value {:ignore-touched true})))))) (when (:height attributes) (dwt/update-dimensions shape-ids :height value {:ignore-touched true :page-id page-id})))))))
(defn- attributes->layout-gap [attributes value] (defn- attributes->layout-gap [attributes value]
(let [layout-gap (-> (set/intersection attributes #{:column-gap :row-gap}) (let [layout-gap (-> (set/intersection attributes #{:column-gap :row-gap})
(zipmap (repeat value)))] (zipmap (repeat value)))]
{:layout-gap layout-gap})) {:layout-gap layout-gap}))
(defn- shape-ids-with-layout [state shape-ids] (defn- shape-ids-with-layout [state page-id shape-ids]
(->> (dsh/lookup-shapes state shape-ids) (->> (dsh/lookup-shapes state page-id shape-ids)
(eduction (eduction
(filter ctsl/any-layout?) (filter ctsl/any-layout?)
(map :id)))) (map :id))))
(defn update-layout-padding [value shape-ids attrs] (defn update-layout-padding
([value shape-ids attrs] (update-layout-padding value shape-ids attrs nil))
([value shape-ids attrs page-id]
(ptk/reify ::update-layout-padding (ptk/reify ::update-layout-padding
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [ids-with-layout (shape-ids-with-layout state shape-ids)] (let [ids-with-layout (shape-ids-with-layout state (or page-id (:current-page-id state)) shape-ids)]
(rx/of (rx/of
(dwsl/update-layout ids-with-layout (dwsl/update-layout ids-with-layout
{:layout-padding (zipmap attrs (repeat value))} {:layout-padding (zipmap attrs (repeat value))}
{:ignore-touched true})))))) {:ignore-touched true
:page-id page-id})))))))
(defn update-layout-spacing [value shape-ids attributes] (defn update-layout-spacing
([value shape-ids attributes] (update-layout-spacing value shape-ids attributes nil))
([value shape-ids attributes page-id]
(ptk/reify ::update-layout-spacing (ptk/reify ::update-layout-spacing
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [ids-with-layout (shape-ids-with-layout state shape-ids) (let [ids-with-layout (shape-ids-with-layout state page-id shape-ids)
layout-attributes (attributes->layout-gap attributes value)] layout-attributes (attributes->layout-gap attributes value)]
(rx/of (rx/of
(dwsl/update-layout ids-with-layout (dwsl/update-layout ids-with-layout
layout-attributes layout-attributes
{:ignore-touched true})))))) {:ignore-touched true
:page-id page-id})))))))
(defn update-shape-position [value shape-ids attributes] (defn update-shape-position
([value shape-ids attributes] (update-shape-position value shape-ids attributes nil))
([value shape-ids attributes page-id]
(ptk/reify ::update-shape-position (ptk/reify ::update-shape-position
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]
(rx/concat (rx/concat
(map #(dwt/update-position % (zipmap attributes (repeat value)) {:ignore-touched true}) shape-ids))))) (map #(dwt/update-position % (zipmap attributes (repeat value)) {:ignore-touched true :page-id page-id}) shape-ids))))))
(defn update-layout-sizing-limits [value shape-ids attributes] (defn update-layout-sizing-limits
([value shape-ids attributes] (update-layout-sizing-limits value shape-ids attributes nil))
([value shape-ids attributes page-id]
(ptk/reify ::update-layout-sizing-limits (ptk/reify ::update-layout-sizing-limits
ptk/WatchEvent ptk/WatchEvent
(watch [_ _ _] (watch [_ _ _]
@ -212,4 +250,5 @@
:layout-item-max-w value :layout-item-max-w value
:layout-item-max-h value} :layout-item-max-h value}
(select-keys attributes))] (select-keys attributes))]
(dwsl/update-layout-child shape-ids props {:ignore-touched true}))))) (dwsl/update-layout-child shape-ids props {:ignore-touched true
:page-id page-id}))))))

View file

@ -110,7 +110,6 @@
(fn [event token] (fn [event token]
(dom/stop-propagation event) (dom/stop-propagation event)
(when (seq selected-shapes) (when (seq selected-shapes)
(st/emit! (st/emit!
(wtch/toggle-token {:token token (wtch/toggle-token {:token token
:shapes selected-shapes :shapes selected-shapes

View file

@ -86,30 +86,36 @@
(->> (map (fn [[value attrs]] [attrs {value #{object-id}}]) attrs-values-map) (->> (map (fn [[value attrs]] [attrs {value #{object-id}}]) attrs-values-map)
(into {}))) (into {})))
(defn collect-shapes-update-info [resolved-tokens shapes] (defn collect-shapes-update-info [resolved-tokens objects]
(reduce (reduce
(fn [acc [object-id {:keys [applied-tokens] :as shape}]] (fn [acc [shape-id {:keys [applied-tokens] :as shape}]]
(if (seq applied-tokens) (if (seq applied-tokens)
(let [applied-tokens (-> (invert-collect-key-vals applied-tokens resolved-tokens shape) (let [applied-tokens (-> (invert-collect-key-vals applied-tokens resolved-tokens shape)
(shape-ids-by-values object-id) (shape-ids-by-values shape-id)
(split-attribute-groups))] (split-attribute-groups))]
(deep-merge acc applied-tokens)) (deep-merge acc applied-tokens))
acc)) acc))
{} shapes)) {} objects))
(defn actionize-shapes-update-info [shapes-update-info] (defn actionize-shapes-update-info [page-id shapes-update-info]
(mapcat (fn [[attrs update-infos]] (mapcat (fn [[attrs update-infos]]
(let [action (some attribute-actions-map attrs)] (let [action (some attribute-actions-map attrs)]
(map (map
(fn [[v shape-ids]] (fn [[v shape-ids]]
(action v shape-ids attrs)) (action v shape-ids attrs page-id))
update-infos))) update-infos)))
shapes-update-info)) shapes-update-info))
(defn update-tokens [state resolved-tokens] (defn update-tokens-in-page [state page-id resolved-tokens]
(->> (dsh/lookup-page-objects state) (->> (dsh/lookup-page-objects state page-id)
(collect-shapes-update-info resolved-tokens) (collect-shapes-update-info resolved-tokens)
(actionize-shapes-update-info))) (actionize-shapes-update-info page-id)))
(defn update-tokens [state resolved-tokens]
(reduce (fn [events page-id]
(rx/concat events (update-tokens-in-page state page-id resolved-tokens)))
(rx/empty)
(dsh/get-all-page-ids state)))
(defn update-workspace-tokens [] (defn update-workspace-tokens []
(ptk/reify ::update-workspace-tokens (ptk/reify ::update-workspace-tokens