Browse Source

fix: enable promise usage in outliner-ui/transact!

Tienson Qin 1 year ago
parent
commit
95cd7d51fc

+ 5 - 11
deps/outliner/src/logseq/outliner/core.cljs

@@ -1131,27 +1131,21 @@
 
 ;;; ### write-operations have side-effects (do transactions) ;;;;;;;;;;;;;;;;
 
-(def ^:private ^:dynamic *transaction-data*
+(def *transaction-data
   "Stores transaction-data that are generated by one or more write-operations,
   see also `logseq.outliner.transaction/transact!`"
-  nil)
+  (atom nil))
 
-(def ^:private ^:dynamic #_:clj-kondo/ignore *transaction-opts*
+(def #_:clj-kondo/ignore *transaction-opts
   "Stores transaction opts that are generated by one or more write-operations,
   see also `logseq.outliner.transaction/transact!`"
-  nil)
-
-(def ^:private ^:dynamic #_:clj-kondo/ignore *transaction-args*
-  "Stores transaction args which can be fetched in all op-transact functions."
-  nil)
+  (atom nil))
 
 (defn- op-transact!
   [fn-var & args]
   {:pre [(var? fn-var)]}
-  (when (nil? *transaction-data*)
-    (throw (js/Error. (str (:name (meta fn-var)) " is not used in (transact! ...)"))))
   (let [result (apply @fn-var args)]
-    (conj! *transaction-data* (select-keys result [:tx-data :tx-meta]))
+    (swap! *transaction-data conj (select-keys result [:tx-data :tx-meta]))
     result))
 
 (defn save-block!

+ 26 - 22
deps/outliner/src/logseq/outliner/transaction.cljc

@@ -2,7 +2,8 @@
   "Provides a wrapper around logseq.outliner.datascript/transact! using
    transient state from logseq.outliner.core"
   #?(:cljs (:require-macros [logseq.outliner.transaction]))
-  #?(:cljs (:require [malli.core :as m])))
+  #?(:cljs (:require [malli.core :as m]
+                     [promesa.core :as p])))
 
 #_:clj-kondo/ignore
 (def ^:private transact-opts [:or :symbol :map])
@@ -28,35 +29,38 @@
     (move-blocks! ...)
     (delete-blocks! ...))"
   [opts & body]
-  `(let [transact-data# logseq.outliner.core/*transaction-data*
-         transaction-opts# logseq.outliner.core/*transaction-opts*
+  `(let [transact-data# logseq.outliner.core/*transaction-data
+         transaction-opts# logseq.outliner.core/*transaction-opts
          opts*# ~opts
          _# (assert (or (map? opts*#) (symbol? opts*#)) (str "opts is not a map or symbol, type: " (type opts*#)))
-         opts# (if transact-data#
+         opts# (if @transact-data#
                  (assoc opts*# :nested-transaction? true)
                  opts*#)]
-     (if transact-data#
+     (if @transact-data#
        (do
-         (when transaction-opts#
-           (conj! transaction-opts# opts#))
+         (when @transaction-opts#
+           (swap! transaction-opts# conj opts#))
          ~@body)
        (let [transaction-args# (cond-> {}
                                  (get opts*# :persist-op? true)
                                  (assoc :persist-op? true))]
-         (binding [logseq.outliner.core/*transaction-data* (transient [])
-                   logseq.outliner.core/*transaction-opts* (transient [])
-                   logseq.outliner.core/*transaction-args* transaction-args#]
-           (conj! logseq.outliner.core/*transaction-opts* opts#)
-           ~@body
-           (let [r# (persistent! logseq.outliner.core/*transaction-data*)
-                 tx# (mapcat :tx-data r#)
+         (reset! logseq.outliner.core/*transaction-data [])
+         (reset! logseq.outliner.core/*transaction-opts [opts#])
+         (p/do!
+          ~@body
+          (let [r# @logseq.outliner.core/*transaction-data
+                tx# (mapcat :tx-data r#)
                  ;; FIXME: should we merge all the tx-meta?
-                 tx-meta# (first (map :tx-meta r#))
-                 all-tx# (concat tx# (:additional-tx opts#))
-                 o# (persistent! logseq.outliner.core/*transaction-opts*)
-                 full-opts# (apply merge (reverse o#))
-                 opts## (merge (dissoc full-opts# :additional-tx :current-block :nested-transaction?) tx-meta#)]
+                tx-meta# (first (map :tx-meta r#))
+                all-tx# (concat tx# (:additional-tx opts#))
+                o# @logseq.outliner.core/*transaction-opts
+                full-opts# (apply merge (reverse o#))
+                opts## (merge (dissoc full-opts# :additional-tx :current-block :nested-transaction?) tx-meta#)]
 
-             (when (seq all-tx#) ;; If it's empty, do nothing
-               (when-not (:nested-transaction? opts#) ; transact only for the whole transaction
-                 (logseq.outliner.datascript/transact! all-tx# (dissoc opts## :transact-opts) (:transact-opts opts##))))))))))
+            (when (seq all-tx#) ;; If it's empty, do nothing
+              (when-not (:nested-transaction? opts#) ; transact only for the whole transaction
+                (prn :debug :data @transact-data#)
+                (logseq.outliner.datascript/transact! all-tx# (dissoc opts## :transact-opts) (:transact-opts opts##))))
+
+            (reset! logseq.outliner.core/*transaction-data nil)
+            (reset! logseq.outliner.core/*transaction-opts nil)))))))

+ 12 - 0
src/main/frontend/db/async.cljs

@@ -212,3 +212,15 @@
             (->> result
                  db-model/sort-by-left-recursive
                  db-utils/group-by-page)))))))
+
+;; TODO: perf improvement, some operations such as delete-block doesn't need to load the full page
+;; instead, the db worker should provide those calls
+(defn <ensure-page-loaded
+  [block-uuid-or-page-name]
+  (p/let [repo (state/get-current-repo)
+          result (<get-block repo (str block-uuid-or-page-name))
+          block (if (:block result) (:block result) result)
+          _ (when-let [page-id (:db/id (:block/page block))]
+              (when-let [page-uuid (:block/uuid (db/entity page-id))]
+                (<get-block repo page-uuid)))]
+    block))

+ 2 - 1
src/main/frontend/handler/dnd.cljs

@@ -8,7 +8,8 @@
             [logseq.common.util.block-ref :as block-ref]
             [frontend.state :as state]
             [frontend.db :as db]
-            [frontend.handler.block :as block-handler]))
+            [frontend.handler.block :as block-handler]
+            [promesa.core :as p]))
 
 (defn move-blocks
   [^js event blocks target-block original-block move-to]

+ 56 - 57
src/main/frontend/handler/editor.cljs

@@ -345,15 +345,14 @@
 
                    :else
                    (not has-children?))]
-    (p/do!
-     (ui-outliner-tx/transact!
-      {:outliner-op :insert-blocks}
-       (save-current-block! {:current-block current-block})
-       (outliner-core/insert-blocks! (state/get-current-repo) (db/get-db false)
-                                    [new-block] current-block {:sibling? sibling?
-                                                               :keep-uuid? keep-uuid?
-                                                               :ordered-list? ordered-list?
-                                                               :replace-empty-target? replace-empty-target?})))))
+    (ui-outliner-tx/transact!
+     {:outliner-op :insert-blocks}
+     (save-current-block! {:current-block current-block})
+     (outliner-core/insert-blocks! (state/get-current-repo) (db/get-db false)
+                                   [new-block] current-block {:sibling? sibling?
+                                                              :keep-uuid? keep-uuid?
+                                                              :ordered-list? ordered-list?
+                                                              :replace-empty-target? replace-empty-target?}))))
 
 
 (defn- block-self-alone-when-insert?
@@ -791,45 +790,46 @@
                                                    (:block/properties (db/entity (:db/id block))))]
                          (if (seq (:block/_refs (db/entity (:db/id block))))
                            (let [block-right (outliner-core/get-right-sibling (db/get-db) (:db/id block))]
-                             (delete-block-fn prev-block)
-                             (save-block! repo block new-content {})
-                             (outliner-save-block! {:db/id (:db/id block)
-                                                    :block/parent (:db/id (:block/parent prev-block))
-                                                    :block/left (or (:db/id (:block/left prev-block))
-                                                                    (:db/id (:block/parent prev-block)))})
-
-                             ;; block->right needs to point its `left` to block->left
-                             (when (and block-right (not= (:db/id (:block/parent prev-block))
-                                                          (:db/id (:block/parent block))))
-                               (outliner-save-block! {:db/id (:db/id block-right)
-                                                      :block/left (:db/id (:block/left block))}))
+                             (p/do!
+                              (delete-block-fn prev-block)
+                              (save-block! repo block new-content {})
+                              (outliner-save-block! {:db/id (:db/id block)
+                                                     :block/parent (:db/id (:block/parent prev-block))
+                                                     :block/left (or (:db/id (:block/left prev-block))
+                                                                     (:db/id (:block/parent prev-block)))})
+
+;; block->right needs to point its `left` to block->left
+                              (when (and block-right (not= (:db/id (:block/parent prev-block))
+                                                           (:db/id (:block/parent block))))
+                                (outliner-save-block! {:db/id (:db/id block-right)
+                                                       :block/left (:db/id (:block/left block))}))
 
                              ;; update prev-block's children to point to the refed block
-                             (when (or (:block/collapsed? prev-block)
-                                       (= (:db/id prev-block) (:db/id (:block/parent block))))
-                               (let [children (:block/_parent prev-block)]
-                                 (doseq [child children]
-                                   (when-not (= (:db/id child) (:db/id block))
-                                     (outliner-save-block! {:db/id (:db/id child)
-                                                            :block/parent (:db/id block)
-                                                            :block/left (:db/id block)})))))
+                              (when (or (:block/collapsed? prev-block)
+                                        (= (:db/id prev-block) (:db/id (:block/parent block))))
+                                (let [children (:block/_parent prev-block)]
+                                  (doseq [child children]
+                                    (when-not (= (:db/id child) (:db/id block))
+                                      (outliner-save-block! {:db/id (:db/id child)
+                                                             :block/parent (:db/id block)
+                                                             :block/left (:db/id block)})))))
 
                              ;; parent will be removed
-                             (when (= (:db/id prev-block) (:db/id (:block/parent block)))
-                               (when-let [parent-right (outliner-core/get-right-sibling (db/get-db) (:db/id prev-block))]
-                                 (outliner-save-block! {:db/id (:db/id parent-right)
-                                                        :block/left (:db/id block)})))
-
-                             (when db-based?
-                               (outliner-save-block! {:db/id (:db/id block)
-                                                      :block/properties new-properties})))
-
-                           (do
-                             (delete-block-fn block)
-                             (save-block! repo prev-block new-content {})
-                             (when db-based?
-                               (outliner-save-block! {:db/id (:db/id prev-block)
-                                                      :block/properties new-properties})))))
+                              (when (= (:db/id prev-block) (:db/id (:block/parent block)))
+                                (when-let [parent-right (outliner-core/get-right-sibling (db/get-db) (:db/id prev-block))]
+                                  (outliner-save-block! {:db/id (:db/id parent-right)
+                                                         :block/left (:db/id block)})))
+
+                              (when db-based?
+                                (outliner-save-block! {:db/id (:db/id block)
+                                                       :block/properties new-properties}))))
+
+                           (p/do!
+                            (delete-block-fn block)
+                            (save-block! repo prev-block new-content {})
+                            (when db-based?
+                              (outliner-save-block! {:db/id (:db/id prev-block)
+                                                     :block/properties new-properties})))))
 
                        :else
                        (delete-block-fn block)))))))))))))
@@ -2864,19 +2864,18 @@
   (let [editor (state/get-input)
         pos (some-> editor cursor/pos)
         {:keys [block]} (get-state)]
-    (p/do!
-     (when block
-       (state/set-editor-last-pos! pos)
-       (ui-outliner-tx/transact!
-        {:outliner-op :move-blocks
-         :real-outliner-op :indent-outdent}
-        (save-current-block!)
-        (outliner-core/indent-outdent-blocks! (state/get-current-repo)
-                                              (db/get-db false)
-                                              (block-handler/get-top-level-blocks [block])
-                                              indent?
-                                              {:get-first-block-original block-handler/get-first-block-original
-                                               :logical-outdenting? (state/logical-outdenting?)}))))))
+    (when block
+      (state/set-editor-last-pos! pos)
+      (ui-outliner-tx/transact!
+       {:outliner-op :move-blocks
+        :real-outliner-op :indent-outdent}
+       (save-current-block!)
+       (outliner-core/indent-outdent-blocks! (state/get-current-repo)
+                                             (db/get-db false)
+                                             (block-handler/get-top-level-blocks [block])
+                                             indent?
+                                             {:get-first-block-original block-handler/get-first-block-original
+                                              :logical-outdenting? (state/logical-outdenting?)})))))
 
 (defn keydown-tab-handler
   [direction]

+ 2 - 1
src/main/frontend/handler/file_based/editor.cljs

@@ -17,7 +17,8 @@
             [frontend.handler.file-based.property :as file-property-handler]
             [frontend.handler.file-based.property.util :as property-util]
             [logseq.db.frontend.schema :as db-schema]
-            [logseq.common.util.block-ref :as block-ref]))
+            [logseq.common.util.block-ref :as block-ref]
+            [promesa.core :as p]))
 
 (defn- remove-non-existed-refs!
   [refs]

+ 2 - 1
src/main/frontend/handler/file_based/page_property.cljs

@@ -5,7 +5,8 @@
             [logseq.outliner.core :as outliner-core]
             [frontend.modules.outliner.ui :as ui-outliner-tx]
             [frontend.state :as state]
-            [frontend.util :as util]))
+            [frontend.util :as util]
+            [promesa.core :as p]))
 
 (defn insert-property
   [format content key value]

+ 2 - 1
src/main/frontend/modules/outliner/ui.cljc

@@ -3,7 +3,8 @@
   #?(:cljs (:require-macros [frontend.modules.outliner.ui]))
   #?(:cljs (:require [frontend.state :as state]
                      [frontend.config :as config]
-                     [frontend.db :as db])))
+                     [frontend.db :as db]
+                     [promesa.core :as p])))
 
 #?(:cljs
    (do

+ 11 - 23
src/main/logseq/api.cljs

@@ -615,24 +615,12 @@
         (let [{:keys [pos] :or {pos :max}} (bean/->clj opts)]
           (editor-handler/edit-block! block pos block-uuid))))))
 
-;; TODO: perf improvement, some operations such as delete-block doesn't need to load the full page
-;; instead, the db worker should provide those calls
-(defn- <ensure-page-loaded
-  [block-uuid-or-page-name]
-  (p/let [repo (state/get-current-repo)
-          result (db-async/<get-block repo (str block-uuid-or-page-name))
-          block (if (:block result) (:block result) result)
-          _ (when-let [page-id (:db/id (:block/page block))]
-              (when-let [page-uuid (:block/uuid (db/entity page-id))]
-                (db-async/<get-block repo page-uuid)))]
-    block))
-
 (def ^:export insert_block
   (fn [block-uuid-or-page-name content ^js opts]
     (when (string/blank? block-uuid-or-page-name)
       (throw (js/Error. "Page title or block UUID shouldn't be empty.")))
     (p/let [block? (util/uuid-string? (str block-uuid-or-page-name))
-            block (<ensure-page-loaded block-uuid-or-page-name)]
+            block (db-async/<ensure-page-loaded block-uuid-or-page-name)]
       (if (and block? (not block))
         (throw (js/Error. "Block not exists"))
         (p/let [{:keys [before sibling focus customUUID properties autoOrderedList]} (bean/->clj opts)
@@ -679,7 +667,7 @@
 
 (def ^:export insert_batch_block
   (fn [block-uuid ^js batch-blocks ^js opts]
-    (p/let [block (<ensure-page-loaded block-uuid)]
+    (p/let [block (db-async/<ensure-page-loaded block-uuid)]
       (when block
         (when-let [bb (bean/->clj batch-blocks)]
           (let [bb (if-not (vector? bb) (vector bb) bb)
@@ -700,21 +688,21 @@
 (def ^:export remove_block
   (fn [block-uuid ^js _opts]
     (p/let [repo            (state/get-current-repo)
-            _ (<ensure-page-loaded block-uuid)]
+            _ (db-async/<ensure-page-loaded block-uuid)]
       (editor-handler/delete-block-aux!
        {:block/uuid (sdk-utils/uuid-or-throw-error block-uuid) :repo repo} true))))
 
 (def ^:export update_block
   (fn [block-uuid content ^js opts]
     (p/let [repo (state/get-current-repo)
-            _ (<ensure-page-loaded block-uuid)]
+            _ (db-async/<ensure-page-loaded block-uuid)]
       (editor-handler/save-block! repo
                                   (sdk-utils/uuid-or-throw-error block-uuid) content (bean/->clj opts)))))
 
 (def ^:export move_block
   (fn [src-block-uuid target-block-uuid ^js opts]
-    (p/let [_ (<ensure-page-loaded src-block-uuid)
-            _ (<ensure-page-loaded target-block-uuid)]
+    (p/let [_ (db-async/<ensure-page-loaded src-block-uuid)
+            _ (db-async/<ensure-page-loaded target-block-uuid)]
       (let [{:keys [before children]} (bean/->clj opts)
            move-to      (cond
                           (boolean before)
@@ -747,7 +735,7 @@
 (def ^:export get_previous_sibling_block
   (fn [block-uuid]
     (p/let [id (sdk-utils/uuid-or-throw-error block-uuid)
-            _ (<ensure-page-loaded id)]
+            _ (db-async/<ensure-page-loaded id)]
       (when-let [block (db-model/query-block-by-uuid (sdk-utils/uuid-or-throw-error block-uuid))]
        (let [{:block/keys [parent left]} block
              block (when-not (= parent left) (db-utils/pull (:db/id left)))]
@@ -756,7 +744,7 @@
 (def ^:export get_next_sibling_block
   (fn [block-uuid]
     (p/let [id (sdk-utils/uuid-or-throw-error block-uuid)
-            _ (<ensure-page-loaded id)]
+            _ (db-async/<ensure-page-loaded id)]
       (when-let [block (db-model/query-block-by-uuid id)]
        (when-let [right-sibling (outliner-core/get-right-sibling (db/get-db) (:db/id block))]
          (let [block (db/pull (:db/id right-sibling))]
@@ -822,7 +810,7 @@
 
 (def ^:export get_page_blocks_tree
   (fn [id-or-page-name]
-    (p/let [_ (<ensure-page-loaded id-or-page-name)]
+    (p/let [_ (db-async/<ensure-page-loaded id-or-page-name)]
       (when-let [page-name (:block/name (db-model/get-page id-or-page-name))]
         (let [blocks (db-model/get-page-blocks-no-cache page-name)
               blocks (outliner-tree/blocks->vec-tree blocks page-name)
@@ -861,7 +849,7 @@
 
 (defn ^:export prepend_block_in_page
   [uuid-or-page-name content ^js opts]
-  (p/let [_               (<ensure-page-loaded uuid-or-page-name)
+  (p/let [_               (db-async/<ensure-page-loaded uuid-or-page-name)
           page?           (not (util/uuid-string? uuid-or-page-name))
           page-not-exist? (and page? (nil? (db-model/get-page uuid-or-page-name)))
           _               (and page-not-exist? (page-handler/<create! uuid-or-page-name
@@ -875,7 +863,7 @@
 
 (defn ^:export append_block_in_page
   [uuid-or-page-name content ^js opts]
-  (p/let [_               (<ensure-page-loaded uuid-or-page-name)
+  (p/let [_               (db-async/<ensure-page-loaded uuid-or-page-name)
           page?           (not (util/uuid-string? uuid-or-page-name))
           page-not-exist? (and page? (nil? (db-model/get-page uuid-or-page-name)))
           _               (and page-not-exist? (page-handler/<create! uuid-or-page-name