From 6339d76db02cc93ef6f576d215e30cc113374353 Mon Sep 17 00:00:00 2001 From: rcmerci Date: Wed, 3 Apr 2024 12:04:19 +0800 Subject: [PATCH] refactor: use defmethod to collect all db-listen-handlers --- src/main/frontend/db_worker.cljs | 7 +- src/main/frontend/worker/db_listener.cljs | 45 +++++++++ src/main/frontend/worker/undo_redo.cljs | 106 ++++++++-------------- 3 files changed, 89 insertions(+), 69 deletions(-) create mode 100644 src/main/frontend/worker/db_listener.cljs diff --git a/src/main/frontend/db_worker.cljs b/src/main/frontend/db_worker.cljs index 77f4f5c42..ce27c181a 100644 --- a/src/main/frontend/db_worker.cljs +++ b/src/main/frontend/db_worker.cljs @@ -10,6 +10,7 @@ [datascript.core :as d] [datascript.storage :refer [IStorage]] [frontend.worker.async-util :include-macros true :refer [vec [iter] diff --git a/src/main/frontend/worker/db_listener.cljs b/src/main/frontend/worker/db_listener.cljs new file mode 100644 index 000000000..b43de140c --- /dev/null +++ b/src/main/frontend/worker/db_listener.cljs @@ -0,0 +1,45 @@ +(ns frontend.worker.db-listener + (:require [datascript.core :as d])) + + +(defn- entity-datoms=>attr->datom + [entity-datoms] + (reduce + (fn [m datom] + (let [[_e a _v t add?] datom] + (if-let [[_e _a _v old-t old-add?] (get m a)] + (cond + (and (= old-t t) + (true? add?) + (false? old-add?)) + (assoc m a datom) + + (< old-t t) + (assoc m a datom) + + :else + m) + (assoc m a datom)))) + {} entity-datoms)) + + +(defmulti listen-db-changes + (fn [listen-key & _] listen-key)) + +(defn listen-db-changes! + [repo conn] + (let [handlers (methods listen-db-changes)] + (prn :listen-db-changes! (keys handlers)) + (d/unlisten! conn ::listen-db-changes!) + (d/listen! conn ::listen-db-changes! + (fn [{:keys [tx-data] :as args}] + (let [datom-vec-coll (map vec tx-data) + id->same-entity-datoms (group-by first datom-vec-coll) + id-order (distinct (map first datom-vec-coll)) + same-entity-datoms-coll (map id->same-entity-datoms id-order) + id->attr->datom (update-vals id->same-entity-datoms entity-datoms=>attr->datom)] + (doseq [[k handler-fn] handlers] + (handler-fn k (assoc args + :repo repo + :id->attr->datom id->attr->datom + :same-entity-datoms-coll same-entity-datoms-coll)))))))) diff --git a/src/main/frontend/worker/undo_redo.cljs b/src/main/frontend/worker/undo_redo.cljs index 5081c987a..c84b6b05a 100644 --- a/src/main/frontend/worker/undo_redo.cljs +++ b/src/main/frontend/worker/undo_redo.cljs @@ -1,6 +1,7 @@ (ns frontend.worker.undo-redo "undo/redo related fns and op-schema" - (:require [datascript.core :as d] + (:require [frontend.worker.db-listener :as db-listener] + [datascript.core :as d] [malli.util :as mu] [malli.core :as m])) @@ -82,28 +83,6 @@ (cond-> {:block-uuid block-uuid} block-origin-content (assoc :block-origin-content block-origin-content))])))) -(defn- entity-datoms=>attr->datom - [entity-datoms] - (reduce - (fn [m datom] - (let [[_e a _v t add?] datom] - (if-let [[_e _a _v old-t old-add?] (get m a)] - (cond - (and (= old-t t) - (true? add?) - (false? old-add?)) - (assoc m a datom) - - (< old-t t) - (assoc m a datom) - - :else - m) - (assoc m a datom)))) - {} entity-datoms)) - - - (def entity-map-pull-pattern [:block/uuid {:block/left [:block/uuid]} @@ -130,55 +109,50 @@ (defn entity-datoms=>op - [db-before db-after entity-datoms] + [db-before db-after id->attr->datom entity-datoms] {:post [(or (nil? %) (undo-op-validator %))]} - (let [attr->datom (entity-datoms=>attr->datom entity-datoms)] - (when (seq attr->datom) - (let [e (some-> attr->datom first second first) - {[_ _ block-uuid _ add1?] :block/uuid - [_ _ block-content _ add2?] :block/content - [_ _ _ _ add3?] :block/left - [_ _ _ _ add4?] :block/parent} attr->datom - entity-before (d/entity db-before e) - entity-after (d/entity db-after e)] - (cond - (and (not add1?) block-uuid - (normal-block? entity-before)) - [:remove-block - {:block-uuid (:block/uuid entity-before) - :block-entity-map (->block-entity-map db-before e)}] + (when-let [e (ffirst entity-datoms)] + (let [attr->datom (id->attr->datom e)] + (when (seq attr->datom) + (let [{[_ _ block-uuid _ add1?] :block/uuid + [_ _ block-content _ add2?] :block/content + [_ _ _ _ add3?] :block/left + [_ _ _ _ add4?] :block/parent} attr->datom + entity-before (d/entity db-before e) + entity-after (d/entity db-after e)] + (cond + (and (not add1?) block-uuid + (normal-block? entity-before)) + [:remove-block + {:block-uuid (:block/uuid entity-before) + :block-entity-map (->block-entity-map db-before e)}] - (and add1? block-uuid - (normal-block? entity-after)) - [:insert-block {:block-uuid (:block/uuid entity-after)}] + (and add1? block-uuid + (normal-block? entity-after)) + [:insert-block {:block-uuid (:block/uuid entity-after)}] - (and (or add3? add4?) - (normal-block? entity-after)) - [:move-block - {:block-uuid (:block/uuid entity-after) - :block-origin-left (:block/uuid (:block/left entity-before)) - :block-origin-parent (:block/uuid (:block/parent entity-before))}] + (and (or add3? add4?) + (normal-block? entity-after)) + [:move-block + {:block-uuid (:block/uuid entity-after) + :block-origin-left (:block/uuid (:block/left entity-before)) + :block-origin-parent (:block/uuid (:block/parent entity-before))}] - (and add2? block-content - (normal-block? entity-after)) - [:update-block - {:block-uuid (:block/uuid entity-after) - :block-origin-content (:block/content entity-before)}]))))) + (and add2? block-content + (normal-block? entity-after)) + [:update-block + {:block-uuid (:block/uuid entity-after) + :block-origin-content (:block/content entity-before)}])))))) (defn generate-undo-ops - [_repo db-before db-after datoms] - (let [datom-vec-coll (map vec datoms) - id->same-entity-datoms (group-by first datom-vec-coll) - id-order (distinct (map first datom-vec-coll)) - same-entity-datoms-coll (map id->same-entity-datoms id-order) - ops (keep (partial entity-datoms=>op db-before db-after) same-entity-datoms-coll)] + [_repo db-before db-after same-entity-datoms-coll id->attr->datom] + (let [ops (keep (partial entity-datoms=>op db-before db-after id->attr->datom) same-entity-datoms-coll)] (prn ::debug-undo-ops ops))) -(defn listen-to-db-changes! - [repo conn] - (d/unlisten! conn :gen-undo-ops) - (d/listen! conn :gen-undo-ops - (fn [{:keys [tx-data tx-meta db-before db-after]}] - (when (:gen-undo-op? tx-meta true) - (generate-undo-ops repo db-before db-after tx-data))))) + +(defmethod db-listener/listen-db-changes :gen-undo-ops + [_ {:keys [_tx-data tx-meta db-before db-after + repo id->attr->datom same-entity-datoms-coll]}] + (when (:gen-undo-op? tx-meta true) + (generate-undo-ops repo db-before db-after same-entity-datoms-coll id->attr->datom)))