diff --git a/frontend/src/app/main/data/workspace/colors.cljs b/frontend/src/app/main/data/workspace/colors.cljs index 0b5b53046..0fd1239f1 100644 --- a/frontend/src/app/main/data/workspace/colors.cljs +++ b/frontend/src/app/main/data/workspace/colors.cljs @@ -84,7 +84,9 @@ (defn transform-fill ([state ids color transform] (transform-fill state ids color transform nil)) ([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 %))) text-ids (filter is-text? ids) shape-ids (remove is-text? ids) diff --git a/frontend/src/app/main/data/workspace/layout.cljs b/frontend/src/app/main/data/workspace/layout.cljs index c99deb871..89e8a90d8 100644 --- a/frontend/src/app/main/data/workspace/layout.cljs +++ b/frontend/src/app/main/data/workspace/layout.cljs @@ -187,5 +187,3 @@ (if (= val ::does-not-exist) (swap! storage/user dissoc skey) (swap! storage/user assoc skey val))))) - - diff --git a/frontend/src/app/main/data/workspace/modifiers.cljs b/frontend/src/app/main/data/workspace/modifiers.cljs index 1049bfc3a..21fb5487f 100644 --- a/frontend/src/app/main/data/workspace/modifiers.cljs +++ b/frontend/src/app/main/data/workspace/modifiers.cljs @@ -328,14 +328,17 @@ (defn- calculate-modifiers ([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] - (calculate-modifiers state ignore-constraints ignore-snap-pixel modif-tree nil)) + ([state ignore-constraints ignore-snap-pixel modif-tree page-id] + (calculate-modifiers state ignore-constraints ignore-snap-pixel modif-tree page-id nil)) - ([state ignore-constraints ignore-snap-pixel modif-tree params] - (let [objects - (dsh/lookup-page-objects state) + ([state ignore-constraints ignore-snap-pixel modif-tree page-id params] + (let [page-id + (or page-id (:current-page-id state)) + + objects + (dsh/lookup-page-objects state page-id) snap-pixel? (and (not ignore-snap-pixel) (contains? (:workspace-layout state) :snap-pixel-grid)) @@ -402,7 +405,9 @@ (ptk/reify ::set-modifiers ptk/UpdateEvent (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 xf-rotation-shape @@ -438,11 +443,12 @@ ;; - 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 (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/UpdateEvent (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 (->> shapes (remove #(get % :blocked false)) @@ -466,18 +472,19 @@ (apply-modifiers nil)) ([{: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 ignore-snap-pixel false ignore-touched false}}] (ptk/reify ::apply-modifiers ptk/WatchEvent (watch [_ state _] - (let [text-modifiers (get state :workspace-text-modifier) - objects (dsh/lookup-page-objects state) + (let [text-modifiers (get state :workspace-text-modifier) + page-id (or page-id (:current-page-id state)) + objects (dsh/lookup-page-objects state page-id) object-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)) ids @@ -519,6 +526,7 @@ :ignore-tree ignore-tree :ignore-touched ignore-touched :undo-group undo-group + :page-id page-id ;; Attributes that can change in the transform. This way we don't have to check ;; all the attributes :attrs [:selrect diff --git a/frontend/src/app/main/data/workspace/shape_layout.cljs b/frontend/src/app/main/data/workspace/shape_layout.cljs index 6f3bd016c..9852c7468 100644 --- a/frontend/src/app/main/data/workspace/shape_layout.cljs +++ b/frontend/src/app/main/data/workspace/shape_layout.cljs @@ -524,7 +524,9 @@ (ptk/reify ::update-layout-child ptk/WatchEvent (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 %))) parent-ids (->> ids (map #(cfh/get-parent-id objects %))) undo-id (js/Symbol)] diff --git a/frontend/src/app/main/data/workspace/texts.cljs b/frontend/src/app/main/data/workspace/texts.cljs index f8a3399ce..829239531 100644 --- a/frontend/src/app/main/data/workspace/texts.cljs +++ b/frontend/src/app/main/data/workspace/texts.cljs @@ -446,8 +446,10 @@ (when (or (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])))) - (let [objects (dsh/lookup-page-objects state) - shape (get objects id) + (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) update-node? (some-fn txt/is-text-node? txt/is-paragraph-node?) shape-ids diff --git a/frontend/src/app/main/data/workspace/transforms.cljs b/frontend/src/app/main/data/workspace/transforms.cljs index a611d5f7d..5b3988427 100644 --- a/frontend/src/app/main/data/workspace/transforms.cljs +++ b/frontend/src/app/main/data/workspace/transforms.cljs @@ -314,7 +314,10 @@ (ptk/reify ::update-dimensions ptk/UpdateEvent (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 (fn [shape] (ctm/change-dimensions-modifiers shape attr value)) modif-tree @@ -403,18 +406,18 @@ "Rotate shapes a fixed angle, from a keyboard action." ([ids rotation] (increase-rotation ids rotation nil)) - ([ids rotation params & options] + ([ids rotation params & {:as options}] (ptk/reify ::increase-rotation ptk/WatchEvent (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) - shapes (->> ids (map #(get objects %)))] + shapes (->> ids (map #(get objects %))) + options (assoc options :page-id page-id)] (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)))))))) - - ;; -- Move ---------------------------------------------------------- (declare start-move) @@ -788,13 +791,14 @@ (defn update-position "Move shapes to a new position" ([id position] (update-position id position nil)) - ([id position opts] + ([id position options] (dm/assert! (uuid? id)) (ptk/reify ::update-position ptk/WatchEvent (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) shape (get objects id) ;; FIXME: performance rect @@ -809,8 +813,9 @@ modif-tree (dwm/create-modif-tree [id] (ctm/move-modifiers delta))] (rx/of (dwm/apply-modifiers {:modifiers modif-tree + :page-id page-id :ignore-constraints false - :ignore-touched (:ignore-touched opts) + :ignore-touched (:ignore-touched options) :ignore-snap-pixel true}))))))) (defn position-shapes diff --git a/frontend/src/app/main/ui/workspace/tokens/changes.cljs b/frontend/src/app/main/ui/workspace/tokens/changes.cljs index 688d528df..ceba897e4 100644 --- a/frontend/src/app/main/ui/workspace/tokens/changes.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/changes.cljs @@ -52,8 +52,10 @@ (dwu/start-undo-transaction undo-id) (dwsh/update-shapes shape-ids (fn [shape] (cond-> shape - attributes-to-remove (update :applied-tokens #(apply (partial dissoc %) attributes-to-remove)) - :always (update :applied-tokens merge tokenized-attributes)))) + attributes-to-remove + (update :applied-tokens #(apply (partial dissoc %) attributes-to-remove)) + :always + (update :applied-tokens merge tokenized-attributes)))) (when on-update-shape (on-update-shape resolved-value shape-ids attributes)) (dwu/commit-undo-transaction undo-id)))))))))) @@ -94,122 +96,159 @@ ;; Shape Updates --------------------------------------------------------------- -(defn update-shape-radius-all [value shape-ids] - (dwsh/update-shapes shape-ids - (fn [shape] - (ctsr/set-radius-to-all-corners shape value)) - {:reg-objects? true - :ignore-touched true - :attrs ctt/border-radius-keys})) +(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 + (fn [shape] + (ctsr/set-radius-to-all-corners shape value)) + {:reg-objects? true + :ignore-touched true + :page-id page-id + :attrs ctt/border-radius-keys}))) -(defn update-shape-radius-for-corners [value shape-ids attributes] - (dwsh/update-shapes shape-ids - (fn [shape] - (ctsr/set-radius-for-corners shape attributes value)) - {:reg-objects? true - :ignore-touched true - :attrs ctt/border-radius-keys})) +(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 + (fn [shape] + (ctsr/set-radius-for-corners shape attributes value)) + {:reg-objects? true + :ignore-touched true + :page-id page-id + :attrs ctt/border-radius-keys}))) -(defn update-opacity [value shape-ids] - (when (<= 0 value 1) - (dwsh/update-shapes shape-ids - #(assoc % :opacity value) - {:ignore-touched true}))) +(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) + (dwsh/update-shapes shape-ids + #(assoc % :opacity value) + {:ignore-touched true + :page-id page-id})))) -(defn update-rotation [value shape-ids] - (ptk/reify ::update-shape-rotation - ptk/WatchEvent - (watch [_ _ _] - (rx/of - (udw/trigger-bounding-box-cloaking shape-ids) - (udw/increase-rotation shape-ids value nil :ignore-touched true))))) +;; 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/WatchEvent + (watch [_ _ _] + (rx/of + (udw/trigger-bounding-box-cloaking shape-ids) + (udw/increase-rotation shape-ids value nil + {:page-id page-id + :ignore-touched true})))))) (defn update-stroke-width - [value shape-ids] - (dwsh/update-shapes shape-ids - (fn [shape] - (when (seq (:strokes shape)) - (assoc-in shape [:strokes 0 :stroke-width] value))) - {:reg-objects? true - :ignore-touched true - :attrs [:strokes]})) + ([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 + (fn [shape] + (when (seq (:strokes shape)) + (assoc-in shape [:strokes 0 :stroke-width] value))) + {:reg-objects? true + :ignore-touched true + :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)] (let [hex (tinycolor/->hex-string 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 - [value shape-ids] - (update-color wdc/change-fill value shape-ids)) + ([value shape-ids attributes] (update-fill 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 + (update-color wdc/change-fill value shape-ids page-id))) (defn update-stroke-color - [value shape-ids] - (update-color wdc/change-stroke-color value shape-ids)) + ([value shape-ids attributes] (update-stroke-color 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 + (update-color wdc/change-stroke-color value shape-ids page-id))) -(defn update-fill-stroke [value shape-ids attributes] - (ptk/reify ::update-fill-stroke - ptk/WatchEvent - (watch [_ _ _] - (rx/of - (when (:fill attributes) (update-fill value shape-ids)) - (when (:stroke-color attributes) (update-stroke-color value shape-ids)))))) +(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/WatchEvent + (watch [_ _ _] + (rx/of + (when (:fill attributes) (update-fill value shape-ids attributes page-id)) + (when (:stroke-color attributes) (update-stroke-color value shape-ids attributes page-id))))))) -(defn update-shape-dimensions [value shape-ids attributes] - (ptk/reify ::update-shape-dimensions - ptk/WatchEvent - (watch [_ _ _] - (rx/of - (when (:width attributes) (dwt/update-dimensions shape-ids :width value {:ignore-touched true})) - (when (:height attributes) (dwt/update-dimensions shape-ids :height value {:ignore-touched true})))))) +(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/WatchEvent + (watch [_ _ _] + (rx/of + (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 :page-id page-id}))))))) (defn- attributes->layout-gap [attributes value] (let [layout-gap (-> (set/intersection attributes #{:column-gap :row-gap}) (zipmap (repeat value)))] {:layout-gap layout-gap})) -(defn- shape-ids-with-layout [state shape-ids] - (->> (dsh/lookup-shapes state shape-ids) +(defn- shape-ids-with-layout [state page-id shape-ids] + (->> (dsh/lookup-shapes state page-id shape-ids) (eduction (filter ctsl/any-layout?) (map :id)))) -(defn update-layout-padding [value shape-ids attrs] - (ptk/reify ::update-layout-padding - ptk/WatchEvent - (watch [_ state _] - (let [ids-with-layout (shape-ids-with-layout state shape-ids)] - (rx/of - (dwsl/update-layout ids-with-layout - {:layout-padding (zipmap attrs (repeat value))} - {:ignore-touched true})))))) +(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/WatchEvent + (watch [_ state _] + (let [ids-with-layout (shape-ids-with-layout state (or page-id (:current-page-id state)) shape-ids)] + (rx/of + (dwsl/update-layout ids-with-layout + {:layout-padding (zipmap attrs (repeat value))} + {:ignore-touched true + :page-id page-id}))))))) -(defn update-layout-spacing [value shape-ids attributes] - (ptk/reify ::update-layout-spacing - ptk/WatchEvent - (watch [_ state _] - (let [ids-with-layout (shape-ids-with-layout state shape-ids) - layout-attributes (attributes->layout-gap attributes value)] - (rx/of - (dwsl/update-layout ids-with-layout - layout-attributes - {:ignore-touched true})))))) +(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/WatchEvent + (watch [_ state _] + (let [ids-with-layout (shape-ids-with-layout state page-id shape-ids) + layout-attributes (attributes->layout-gap attributes value)] + (rx/of + (dwsl/update-layout ids-with-layout + layout-attributes + {:ignore-touched true + :page-id page-id}))))))) -(defn update-shape-position [value shape-ids attributes] - (ptk/reify ::update-shape-position - ptk/WatchEvent - (watch [_ _ _] - (rx/concat - (map #(dwt/update-position % (zipmap attributes (repeat value)) {:ignore-touched true}) shape-ids))))) +(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/WatchEvent + (watch [_ _ _] + (rx/concat + (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] - (ptk/reify ::update-layout-sizing-limits - ptk/WatchEvent - (watch [_ _ _] - (let [props (-> {:layout-item-min-w value - :layout-item-min-h value - :layout-item-max-w value - :layout-item-max-h value} - (select-keys attributes))] - (dwsl/update-layout-child shape-ids props {:ignore-touched true}))))) +(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/WatchEvent + (watch [_ _ _] + (let [props (-> {:layout-item-min-w value + :layout-item-min-h value + :layout-item-max-w value + :layout-item-max-h value} + (select-keys attributes))] + (dwsl/update-layout-child shape-ids props {:ignore-touched true + :page-id page-id})))))) diff --git a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs index 6e4859724..369c389f3 100644 --- a/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/sidebar.cljs @@ -110,7 +110,6 @@ (fn [event token] (dom/stop-propagation event) (when (seq selected-shapes) - (st/emit! (wtch/toggle-token {:token token :shapes selected-shapes diff --git a/frontend/src/app/main/ui/workspace/tokens/update.cljs b/frontend/src/app/main/ui/workspace/tokens/update.cljs index 4af49340d..3845a8973 100644 --- a/frontend/src/app/main/ui/workspace/tokens/update.cljs +++ b/frontend/src/app/main/ui/workspace/tokens/update.cljs @@ -86,30 +86,36 @@ (->> (map (fn [[value attrs]] [attrs {value #{object-id}}]) attrs-values-map) (into {}))) -(defn collect-shapes-update-info [resolved-tokens shapes] +(defn collect-shapes-update-info [resolved-tokens objects] (reduce - (fn [acc [object-id {:keys [applied-tokens] :as shape}]] + (fn [acc [shape-id {:keys [applied-tokens] :as shape}]] (if (seq applied-tokens) (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))] (deep-merge acc applied-tokens)) 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]] (let [action (some attribute-actions-map attrs)] (map (fn [[v shape-ids]] - (action v shape-ids attrs)) + (action v shape-ids attrs page-id)) update-infos))) shapes-update-info)) -(defn update-tokens [state resolved-tokens] - (->> (dsh/lookup-page-objects state) +(defn update-tokens-in-page [state page-id resolved-tokens] + (->> (dsh/lookup-page-objects state page-id) (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 [] (ptk/reify ::update-workspace-tokens