From f545d7b3eaa0a08f5fb108be32be9c3a7fd2a2b5 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Fri, 28 Mar 2025 17:18:12 +0100 Subject: [PATCH] :recycle: Refactor bool shape creation and modification events --- .../src/app/common/files/changes_builder.cljc | 9 +- .../src/app/main/data/workspace/bool.cljs | 179 +++++++++--------- .../workspace/sidebar/options/menus/bool.cljs | 15 +- .../sidebar/options/shapes/bool.cljs | 1 + frontend/src/app/plugins/api.cljs | 8 +- 5 files changed, 114 insertions(+), 98 deletions(-) diff --git a/common/src/app/common/files/changes_builder.cljc b/common/src/app/common/files/changes_builder.cljc index 733482c36..7c78e9339 100644 --- a/common/src/app/common/files/changes_builder.cljc +++ b/common/src/app/common/files/changes_builder.cljc @@ -479,9 +479,12 @@ (let [old-val (get old attr) new-val (get new attr)] (not= old-val new-val))) - new-obj (if with-objects? - (update-fn object objects) - (update-fn object))] + + new-obj + (if with-objects? + (update-fn object objects) + (update-fn object))] + (when-not (= object new-obj) (let [attrs (or attrs (d/concat-set (keys object) (keys new-obj)))] (filter (partial changed? object new-obj) attrs))))) diff --git a/frontend/src/app/main/data/workspace/bool.cljs b/frontend/src/app/main/data/workspace/bool.cljs index e5228cc50..7e6b8eec9 100644 --- a/frontend/src/app/main/data/workspace/bool.cljs +++ b/frontend/src/app/main/data/workspace/bool.cljs @@ -24,43 +24,92 @@ [cuerdas.core :as str] [potok.v2.core :as ptk])) -(defn selected-shapes-idx - [state] - (let [objects (dsh/lookup-page-objects state)] - (->> (dsh/lookup-selected state) - (cph/clean-loops objects)))) +(defn- create-bool-shape + [id type name shapes objects] + (let [shape-id + (or id (uuid/next)) -(defn create-bool-data - [bool-type name shapes objects] - (let [shapes (mapv #(stp/convert-to-path % objects) shapes) - head (if (= bool-type :difference) (first shapes) (last shapes)) - head (cond-> head - (and (contains? head :svg-attrs) (empty? (:fills head))) - (assoc :fills stp/default-bool-fills)) + shapes + (mapv #(stp/convert-to-path % objects) shapes) - head-data (select-keys head stp/style-properties) + head + (if (= type :difference) (first shapes) (last shapes)) - bool-shape - (-> {:id (uuid/next) - :type :bool - :bool-type bool-type - :frame-id (:frame-id head) - :parent-id (:parent-id head) - :name name - :shapes (->> shapes (mapv :id))} - (merge head-data) + head + (cond-> head + (and (contains? head :svg-attrs) (empty? (:fills head))) + (assoc :fills stp/default-bool-fills)) + + shape + {:id shape-id + :type :bool + :bool-type type + :frame-id (:frame-id head) + :parent-id (:parent-id head) + :name name + :shapes (mapv :id shapes)} + + shape + (-> shape + (merge (select-keys head stp/style-properties)) (cts/setup-shape) (gsh/update-bool-selrect shapes objects))] - [bool-shape (cph/get-position-on-parent objects (:id head))])) + [shape (cph/get-position-on-parent objects (:id head))])) + +(defn create-bool + [type & {:keys [ids force-shape-id]}] + + (assert (or (nil? ids) (every? uuid? ids))) + + (ptk/reify ::create-bool-union + ptk/WatchEvent + (watch [it state _] + (let [page-id (:current-page-id state) + objects (dsh/lookup-page-objects state page-id) + + name + (-> type d/name str/capital) + + ids + (->> (or ids (dsh/lookup-selected state)) + (cph/clean-loops objects)) + + xform + (comp + (map (d/getf objects)) + (remove cph/frame-shape?) + (remove ctc/is-variant?) + (remove #(ctn/has-any-copy-parent? objects %))) + + shapes + (->> (cph/order-by-indexed-shapes objects ids) + (into [] xform) + (not-empty))] + + (when shapes + (let [[shape index] + (create-bool-shape force-shape-id type name (reverse shapes) objects) + + shape-id + (get shape :id) + + changes + (-> (pcb/empty-changes it page-id) + (pcb/with-objects objects) + (pcb/add-object shape {:index (inc index)}) + (pcb/update-shapes (map :id shapes) ctl/remove-layout-item-data) + (pcb/change-parent shape-id shapes))] + + (rx/of (dch/commit-changes changes) + (dws/select-shapes (d/ordered-set shape-id))))))))) (defn group->bool - [group bool-type objects] - + [type group objects] (let [shapes (->> (:shapes group) (map #(get objects %)) (mapv #(stp/convert-to-path % objects))) - head (if (= bool-type :difference) (first shapes) (last shapes)) + head (if (= type :difference) (first shapes) (last shapes)) head (cond-> head (and (contains? head :svg-attrs) (empty? (:fills head))) (assoc :fills stp/default-bool-fills)) @@ -68,86 +117,46 @@ (-> group (assoc :type :bool) - (assoc :bool-type bool-type) + (assoc :bool-type type) (merge head-data) (gsh/update-bool-selrect shapes objects)))) -(defn bool->group - [shape objects] - - (let [children (->> (:shapes shape) - (mapv #(get objects %)))] - (-> shape - (assoc :type :group) - (dissoc :bool-type) - (d/without-keys stp/style-group-properties) - (gsh/update-group-selrect children)))) - -(defn create-bool - ([bool-type] - (create-bool bool-type nil nil)) - ([bool-type ids {:keys [id-ret]}] - (assert (or (nil? ids) (set? ids))) - (ptk/reify ::create-bool-union - ptk/WatchEvent - (watch [it state _] - (let [page-id (:current-page-id state) - objects (dsh/lookup-page-objects state) - name (-> bool-type d/name str/capital) - ids (->> (or ids (dsh/lookup-selected state)) - (cph/clean-loops objects)) - ordered-indexes (cph/order-by-indexed-shapes objects ids) - shapes (->> ordered-indexes - (map (d/getf objects)) - (remove cph/frame-shape?) - (remove ctc/is-variant?) - (remove #(ctn/has-any-copy-parent? objects %)))] - - (when-not (empty? shapes) - (let [[boolean-data index] (create-bool-data bool-type name (reverse shapes) objects) - index (inc index) - shape-id (:id boolean-data) - changes (-> (pcb/empty-changes it page-id) - (pcb/with-objects objects) - (pcb/add-object boolean-data {:index index}) - (pcb/update-shapes (map :id shapes) ctl/remove-layout-item-data) - (pcb/change-parent shape-id shapes))] - (when id-ret - (reset! id-ret shape-id)) - - (rx/of (dch/commit-changes changes) - (dws/select-shapes (d/ordered-set shape-id)))))))))) - (defn group-to-bool - [shape-id bool-type] + [shape-id type] (ptk/reify ::group-to-bool ptk/WatchEvent (watch [_ state _] - (let [objects (dsh/lookup-page-objects state) - change-to-bool - (fn [shape] (group->bool shape bool-type objects))] + (let [objects (dsh/lookup-page-objects state) + update-fn (partial group->bool type)] (when-not (ctn/has-any-copy-parent? objects (get objects shape-id)) - (rx/of (dwsh/update-shapes [shape-id] change-to-bool {:reg-objects? true}))))))) + (rx/of (dwsh/update-shapes [shape-id] update-fn {:with-objects? true :reg-objects? true}))))))) + +(defn- bool->group + [shape objects] + (-> shape + (assoc :type :group) + (dissoc :bool-type) + (d/without-keys stp/style-group-properties) + (gsh/update-group-selrect + (mapv (d/getf objects) + (:shapes shape))))) (defn bool-to-group [shape-id] (ptk/reify ::bool-to-group ptk/WatchEvent (watch [_ state _] - (let [objects (dsh/lookup-page-objects state) - change-to-group - (fn [shape] (bool->group shape objects))] + (let [objects (dsh/lookup-page-objects state)] (when-not (ctn/has-any-copy-parent? objects (get objects shape-id)) - (rx/of (dwsh/update-shapes [shape-id] change-to-group {:reg-objects? true}))))))) - + (rx/of (dwsh/update-shapes [shape-id] bool->group {:with-objects? true :reg-objects? true}))))))) (defn change-bool-type - [shape-id bool-type] + [shape-id type] (ptk/reify ::change-bool-type ptk/WatchEvent (watch [_ state _] (let [objects (dsh/lookup-page-objects state) change-type - (fn [shape] (assoc shape :bool-type bool-type))] + (fn [shape] (assoc shape :bool-type type))] (when-not (ctn/has-any-copy-parent? objects (get objects shape-id)) (rx/of (dwsh/update-shapes [shape-id] change-type {:reg-objects? true}))))))) diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.cljs index c3c2b68de..f644156d9 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/menus/bool.cljs @@ -8,7 +8,8 @@ (:require-macros [app.main.style :as stl]) (:require [app.common.data :as d] - [app.main.data.workspace :as dw] + [app.main.data.workspace.bool :as dwb] + [app.main.data.workspace.path.shapes-to-path :as dwps] [app.main.data.workspace.shortcuts :as sc] [app.main.refs :as refs] [app.main.store :as st] @@ -43,19 +44,21 @@ (mf/deps selected is-group? is-bool?) (fn [bool-type] (let [bool-type (keyword bool-type)] + (cond (> (count selected) 1) - (st/emit! (dw/create-bool bool-type)) + (st/emit! (dwb/create-bool bool-type)) (and (= (count selected) 1) is-group?) - (st/emit! (dw/group-to-bool (:id head) bool-type)) + (st/emit! (dwb/group-to-bool (:id head) bool-type)) (and (= (count selected) 1) is-bool?) (if (= head-bool-type bool-type) - (st/emit! (dw/bool-to-group (:id head))) - (st/emit! (dw/change-bool-type (:id head) bool-type))))))) + (st/emit! (dwb/bool-to-group (:id head))) + (st/emit! (dwb/change-bool-type (:id head) bool-type))))))) - flatten-objects (mf/use-fn #(st/emit! (dw/convert-selected-to-path)))] + flatten-objects + (mf/use-fn #(st/emit! (dwps/convert-selected-to-path)))] (when (not (and disabled-bool-btns disabled-flatten)) [:div {:class (stl/css :boolean-options)} diff --git a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/bool.cljs b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/bool.cljs index f78905082..a623f42ba 100644 --- a/frontend/src/app/main/ui/workspace/sidebar/options/shapes/bool.cljs +++ b/frontend/src/app/main/ui/workspace/sidebar/options/shapes/bool.cljs @@ -46,6 +46,7 @@ ids (hooks/use-equal-memo ids) parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids)) parents (mf/deref parents-by-ids-ref)] + [:* [:& layer-menu {:ids ids :type type diff --git a/frontend/src/app/plugins/api.cljs b/frontend/src/app/plugins/api.cljs index 9ce731f18..2e381ce4d 100644 --- a/frontend/src/app/plugins/api.cljs +++ b/frontend/src/app/plugins/api.cljs @@ -376,10 +376,10 @@ (u/display-not-valid :createBoolean-shapes shapes) :else - (let [ids (into #{} (map #(obj/get % "$id")) shapes) - id-ret (atom nil)] - (st/emit! (dwb/create-bool bool-type ids {:id-ret id-ret})) - (shape/shape-proxy plugin-id @id-ret))))) + (let [ids (into #{} (map #(obj/get % "$id")) shapes) + shape-id (uuid/next)] + (st/emit! (dwb/create-bool bool-type :ids ids :force-shape-id shape-id)) + (shape/shape-proxy plugin-id shape-id))))) :generateMarkup (fn [shapes options]