♻️ Refactor bool shape creation and modification events

This commit is contained in:
Andrey Antukh 2025-03-28 17:18:12 +01:00
parent b242eb5b32
commit f545d7b3ea
5 changed files with 114 additions and 98 deletions

View file

@ -479,9 +479,12 @@
(let [old-val (get old attr) (let [old-val (get old attr)
new-val (get new attr)] new-val (get new attr)]
(not= old-val new-val))) (not= old-val new-val)))
new-obj (if with-objects?
new-obj
(if with-objects?
(update-fn object objects) (update-fn object objects)
(update-fn object))] (update-fn object))]
(when-not (= object new-obj) (when-not (= object new-obj)
(let [attrs (or attrs (d/concat-set (keys object) (keys new-obj)))] (let [attrs (or attrs (d/concat-set (keys object) (keys new-obj)))]
(filter (partial changed? object new-obj) attrs))))) (filter (partial changed? object new-obj) attrs)))))

View file

@ -24,43 +24,92 @@
[cuerdas.core :as str] [cuerdas.core :as str]
[potok.v2.core :as ptk])) [potok.v2.core :as ptk]))
(defn selected-shapes-idx (defn- create-bool-shape
[state] [id type name shapes objects]
(let [objects (dsh/lookup-page-objects state)] (let [shape-id
(->> (dsh/lookup-selected state) (or id (uuid/next))
(cph/clean-loops objects))))
(defn create-bool-data shapes
[bool-type name shapes objects] (mapv #(stp/convert-to-path % objects) shapes)
(let [shapes (mapv #(stp/convert-to-path % objects) shapes)
head (if (= bool-type :difference) (first shapes) (last shapes)) head
head (cond-> head (if (= type :difference) (first shapes) (last shapes))
head
(cond-> head
(and (contains? head :svg-attrs) (empty? (:fills head))) (and (contains? head :svg-attrs) (empty? (:fills head)))
(assoc :fills stp/default-bool-fills)) (assoc :fills stp/default-bool-fills))
head-data (select-keys head stp/style-properties) shape
{:id shape-id
bool-shape
(-> {:id (uuid/next)
:type :bool :type :bool
:bool-type bool-type :bool-type type
:frame-id (:frame-id head) :frame-id (:frame-id head)
:parent-id (:parent-id head) :parent-id (:parent-id head)
:name name :name name
:shapes (->> shapes (mapv :id))} :shapes (mapv :id shapes)}
(merge head-data)
shape
(-> shape
(merge (select-keys head stp/style-properties))
(cts/setup-shape) (cts/setup-shape)
(gsh/update-bool-selrect shapes objects))] (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 (defn group->bool
[group bool-type objects] [type group objects]
(let [shapes (->> (:shapes group) (let [shapes (->> (:shapes group)
(map #(get objects %)) (map #(get objects %))
(mapv #(stp/convert-to-path % 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 head (cond-> head
(and (contains? head :svg-attrs) (empty? (:fills head))) (and (contains? head :svg-attrs) (empty? (:fills head)))
(assoc :fills stp/default-bool-fills)) (assoc :fills stp/default-bool-fills))
@ -68,86 +117,46 @@
(-> group (-> group
(assoc :type :bool) (assoc :type :bool)
(assoc :bool-type bool-type) (assoc :bool-type type)
(merge head-data) (merge head-data)
(gsh/update-bool-selrect shapes objects)))) (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 (defn group-to-bool
[shape-id bool-type] [shape-id type]
(ptk/reify ::group-to-bool (ptk/reify ::group-to-bool
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [objects (dsh/lookup-page-objects state) (let [objects (dsh/lookup-page-objects state)
change-to-bool update-fn (partial group->bool type)]
(fn [shape] (group->bool shape bool-type objects))]
(when-not (ctn/has-any-copy-parent? objects (get objects shape-id)) (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 (defn bool-to-group
[shape-id] [shape-id]
(ptk/reify ::bool-to-group (ptk/reify ::bool-to-group
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [objects (dsh/lookup-page-objects state) (let [objects (dsh/lookup-page-objects state)]
change-to-group
(fn [shape] (bool->group shape objects))]
(when-not (ctn/has-any-copy-parent? objects (get objects shape-id)) (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 (defn change-bool-type
[shape-id bool-type] [shape-id type]
(ptk/reify ::change-bool-type (ptk/reify ::change-bool-type
ptk/WatchEvent ptk/WatchEvent
(watch [_ state _] (watch [_ state _]
(let [objects (dsh/lookup-page-objects state) (let [objects (dsh/lookup-page-objects state)
change-type 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)) (when-not (ctn/has-any-copy-parent? objects (get objects shape-id))
(rx/of (dwsh/update-shapes [shape-id] change-type {:reg-objects? true}))))))) (rx/of (dwsh/update-shapes [shape-id] change-type {:reg-objects? true})))))))

View file

@ -8,7 +8,8 @@
(:require-macros [app.main.style :as stl]) (:require-macros [app.main.style :as stl])
(:require (:require
[app.common.data :as d] [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.data.workspace.shortcuts :as sc]
[app.main.refs :as refs] [app.main.refs :as refs]
[app.main.store :as st] [app.main.store :as st]
@ -43,19 +44,21 @@
(mf/deps selected is-group? is-bool?) (mf/deps selected is-group? is-bool?)
(fn [bool-type] (fn [bool-type]
(let [bool-type (keyword bool-type)] (let [bool-type (keyword bool-type)]
(cond (cond
(> (count selected) 1) (> (count selected) 1)
(st/emit! (dw/create-bool bool-type)) (st/emit! (dwb/create-bool bool-type))
(and (= (count selected) 1) is-group?) (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?) (and (= (count selected) 1) is-bool?)
(if (= head-bool-type bool-type) (if (= head-bool-type bool-type)
(st/emit! (dw/bool-to-group (:id head))) (st/emit! (dwb/bool-to-group (:id head)))
(st/emit! (dw/change-bool-type (:id head) bool-type))))))) (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)) (when (not (and disabled-bool-btns disabled-flatten))
[:div {:class (stl/css :boolean-options)} [:div {:class (stl/css :boolean-options)}

View file

@ -46,6 +46,7 @@
ids (hooks/use-equal-memo ids) ids (hooks/use-equal-memo ids)
parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids)) parents-by-ids-ref (mf/use-memo (mf/deps ids) #(refs/parents-by-ids ids))
parents (mf/deref parents-by-ids-ref)] parents (mf/deref parents-by-ids-ref)]
[:* [:*
[:& layer-menu {:ids ids [:& layer-menu {:ids ids
:type type :type type

View file

@ -377,9 +377,9 @@
:else :else
(let [ids (into #{} (map #(obj/get % "$id")) shapes) (let [ids (into #{} (map #(obj/get % "$id")) shapes)
id-ret (atom nil)] shape-id (uuid/next)]
(st/emit! (dwb/create-bool bool-type ids {:id-ret id-ret})) (st/emit! (dwb/create-bool bool-type :ids ids :force-shape-id shape-id))
(shape/shape-proxy plugin-id @id-ret))))) (shape/shape-proxy plugin-id shape-id)))))
:generateMarkup :generateMarkup
(fn [shapes options] (fn [shapes options]