Browse Source

persist edit-operation

rcmerci 2 years ago
parent
commit
aff2620505

+ 3 - 3
deps/db/src/logseq/db/sqlite/rtc.cljs

@@ -11,10 +11,10 @@
   (let [stmt (sqlite-db/prepare db "CREATE TABLE IF NOT EXISTS rtc_ops (
                          id   INTEGER PRIMARY KEY AUTOINCREMENT,
                          v    TEXT NOT NULL)"
-                                (str db-name))
-        init-stmt (sqlite-db/prepare db "INSERT INTO rtc_ops (v) VALUES (@v)" (str db-name))]
+                                (str db-name))]
     (.run ^object stmt)
-    (.run ^object init-stmt (clj->js (ds-op->sqlite-op {:local-tx 0})))))
+    (let [init-stmt (sqlite-db/prepare db "INSERT INTO rtc_ops (v) VALUES (@v)" (str db-name))]
+      (.run ^object init-stmt (clj->js (ds-op->sqlite-op {:local-tx 0}))))))
 
 (defn init!
   [graphs-dir repo]

+ 2 - 1
src/electron/electron/handler.cljs

@@ -33,7 +33,8 @@
             [logseq.db.sqlite.db :as sqlite-db]
             [logseq.db.sqlite.util :as sqlite-util]
             [logseq.common.graph :as common-graph]
-            [promesa.core :as p]))
+            [promesa.core :as p]
+            [electron.rtc-handler]))
 
 (defmethod handle :mkdir [_window [_ dir]]
   (fs/mkdirSync dir))

+ 8 - 1
src/main/frontend/db/rtc/core.cljs

@@ -4,7 +4,8 @@
             [frontend.util :as util]
             [frontend.config :as config]
             [cljs.core.async :as async :refer [<! >! chan go go-loop offer!
-                                               poll! timeout]]))
+                                               poll! timeout]]
+            [electron.ipc :as ipc]))
 
 (def ws-addr config/RTC-WS-URL)
 
@@ -31,3 +32,9 @@
                                      (>! data-from-ws-chan data))))
 
   (set! (.-onclose (:ws @*ws)) (fn [_e] (println :ws-stopped))))
+
+
+(defn init-rtc-op-db
+  [repo]
+  (when (config/db-based-graph? repo)
+    (ipc/ipc :rtc/init repo)))

+ 9 - 17
src/main/frontend/db/rtc/op.cljs

@@ -1,22 +1,16 @@
 (ns frontend.db.rtc.op
   (:require [electron.ipc :as ipc]
             [malli.core :as m]
-            [cljs.core.async :as async]
-            [cljs.core.async.interop :refer [p->c]]
-            [frontend.components.select :as select]))
+            [cljs.core.async.interop :refer [p->c]]))
 
 (def op-schema
   [:or
    [:catn
     [:op [:= "move"]]
-    [:value [:map
-             [:block-uuid :string]
-             [:target-uuid :string]
-             [:sibling? :boolean]]]]
+    [:value [:map [:block-uuids [:sequential :string]]]]]
    [:catn
     [:op [:= "remove"]]
-    [:value [:map
-             [:block-uuids [:sequential :string]]]]]
+    [:value [:map [:block-uuids [:sequential :string]]]]]
    [:catn
     [:op [:= "update"]]
     [:value [:map
@@ -27,25 +21,23 @@
 
 
 (defn <move-block-op!
-  [repo block-uuid target-uuid sibling?]
-  (let [op ["move" {:block-uuid (str block-uuid)
-                    :target-uuid (str target-uuid)
-                    :sibling? sibling?}]]
-    (assert (op-validator op) "illegal op")
-    (p->c (ipc/ipc :rtc/add-ops repo (pr-str op)))))
+  [repo block-uuids]
+  (let [op ["move" {:block-uuids (mapv str block-uuids)}]]
+    (assert (op-validator op) op)
+    (p->c (ipc/ipc :rtc/add-ops repo (pr-str [op])))))
 
 (defn <remove-blocks-op!
   [repo block-uuids]
   (let [op ["remove" {:block-uuids (mapv str block-uuids)}]]
     (assert (op-validator op) "illegal op")
-    (p->c (ipc/ipc :rtc/add-ops repo (pr-str op)))))
+    (p->c (ipc/ipc :rtc/add-ops repo (pr-str [op])))))
 
 (defn <update-block-op!
   [repo block-uuid attrs-map]
   (let [op ["update" (merge {:block-uuid (str block-uuid)}
                             (select-keys attrs-map [:content]))]]
     (assert (op-validator op) "illegal op")
-    (p->c (ipc/ipc :rtc/add-ops repo (pr-str op)))))
+    (p->c (ipc/ipc :rtc/add-ops repo (pr-str [op])))))
 
 (defn <get-ops&local-tx
   [repo]

+ 2 - 0
src/main/frontend/handler.cljs

@@ -45,6 +45,7 @@
             [promesa.core :as p]
             [frontend.mobile.core :as mobile]
             [frontend.db.listener :as db-listener]
+            [frontend.db.rtc.core :as rtc-core]
             [cljs-bean.core :as bean]))
 
 (defn- set-global-error-notification!
@@ -87,6 +88,7 @@
     (-> (db-restore/restore-graph! repo)
         (p/then
          (fn []
+           (rtc-core/init-rtc-op-db repo)
            (db-listener/listen-and-persist! repo)
            ;; try to load custom css only for current repo
            (ui-handler/add-style-if-exists!)

+ 5 - 2
src/main/frontend/handler/block.cljs

@@ -60,9 +60,12 @@
 
 (defn indent-outdent-block!
   [block direction]
-  (let [opts {:outliner-op :move-blocks}]
+  (let [repo (state/get-current-repo)
+        opts (cond-> {:outliner-op :move-blocks}
+               (config/db-based-graph? repo)
+               (assoc :persist-op? true :repo repo))]
     (outliner-tx/transact! opts
-      (outliner-core/indent-outdent-blocks! [block] (= direction :right)))))
+                           (outliner-core/indent-outdent-blocks! [block] (= direction :right)))))
 
 (defn select-block!
   [block-uuid]

+ 18 - 15
src/main/frontend/handler/dnd.cljs

@@ -7,7 +7,8 @@
             [frontend.modules.outliner.transaction :as outliner-tx]
             [logseq.graph-parser.util.block-ref :as block-ref]
             [frontend.state :as state]
-            [frontend.db :as db]))
+            [frontend.db :as db]
+            [frontend.config :as config]))
 
 (defn move-blocks
   [^js event blocks target-block move-to]
@@ -17,7 +18,8 @@
         nested? (= move-to :nested)
         alt-key? (and event (.-altKey event))
         current-format (:block/format first-block)
-        target-format (:block/format target-block)]
+        target-format (:block/format target-block)
+        repo (state/get-current-repo)]
     (cond
       ;; alt pressed, make a block-ref
       (and alt-key? (= (count blocks) 1))
@@ -36,22 +38,23 @@
                           :status :warning
                           :clear? true}])
 
-
       (every? map? (conj blocks' target-block))
       (let [target-node (outliner-core/block target-block)]
         (outliner-tx/transact!
-          {:outliner-op :move-blocks}
-          (editor-handler/save-current-block!)
-          (if top?
-            (let [first-child?
-                  (= (tree/-get-parent-id target-node)
-                     (tree/-get-left-id target-node))]
-              (if first-child?
-                (let [parent (tree/-get-parent target-node)]
-                  (outliner-core/move-blocks! blocks' (:data parent) false))
-                (let [before-node (tree/-get-left target-node)]
-                  (outliner-core/move-blocks! blocks' (:data before-node) true))))
-            (outliner-core/move-blocks! blocks' target-block (not nested?)))))
+         (cond-> {:outliner-op :move-blocks}
+           (config/db-based-graph? repo)
+           (assoc :persist-op? true :repo repo))
+         (editor-handler/save-current-block!)
+         (if top?
+           (let [first-child?
+                 (= (tree/-get-parent-id target-node)
+                    (tree/-get-left-id target-node))]
+             (if first-child?
+               (let [parent (tree/-get-parent target-node)]
+                 (outliner-core/move-blocks! blocks' (:data parent) false))
+               (let [before-node (tree/-get-left target-node)]
+                 (outliner-core/move-blocks! blocks' (:data before-node) true))))
+           (outliner-core/move-blocks! blocks' target-block (not nested?)))))
 
       :else
       nil)))

+ 126 - 68
src/main/frontend/handler/editor.cljs

@@ -248,7 +248,8 @@
   [block value opts]
   (let [block {:db/id (:db/id block)
                :block/uuid (:block/uuid block)
-               :block/content value}]
+               :block/content value}
+        repo (state/get-current-repo)]
     (profile
      "Save block: "
      (let [original-uuid (:block/uuid (db/entity (:db/id block)))
@@ -260,7 +261,10 @@
            opts' (merge opts (cond-> {:outliner-op :save-block}
                                uuid-changed?
                                (assoc :uuid-changed {:from (:block/uuid block)
-                                                     :to original-uuid})))]
+                                                     :to original-uuid})
+                               (config/db-based-graph? repo)
+                               (assoc :persist-op? true
+                                      :repo repo)))]
 
        (outliner-tx/transact!
         opts'
@@ -339,9 +343,13 @@
                    true
 
                    :else
-                   (not has-children?))]
+                   (not has-children?))
+        repo (state/get-current-repo)
+        opts (cond-> {:outliner-op :insert-blocks}
+               (config/db-based-graph? repo)
+               (assoc :persist-op? true :repo repo))]
     (outliner-tx/transact!
-     {:outliner-op :insert-blocks}
+     opts
      (save-current-block! {:current-block current-block})
      (outliner-core/insert-blocks! [new-block] current-block {:sibling? sibling?
                                                               :keep-uuid? keep-uuid?
@@ -638,12 +646,17 @@
   (when-let [blocks (seq (get-selected-blocks))]
     (let [ids (->> (distinct (map #(when-let [id (dom/attr % "blockid")]
                                      (uuid id)) blocks))
-                   (remove nil?))]
-      (outliner-tx/transact! {:outliner-op :cycle-todos}
-        (doseq [id ids]
-          (let [block (db/pull [:block/uuid id])]
-            (when (not-empty (:block/content block))
-              (set-marker block))))))))
+                   (remove nil?))
+          repo (state/get-current-repo)
+          opts (cond-> {:outliner-op :cycle-todos}
+                 (config/db-based-graph? repo)
+                 (assoc :persist-op? true :repo repo))]
+      (outliner-tx/transact!
+       opts
+       (doseq [id ids]
+         (let [block (db/pull [:block/uuid id])]
+           (when (not-empty (:block/content block))
+             (set-marker block))))))))
 
 (defn cycle-todo!
   []
@@ -672,10 +685,13 @@
 (defn delete-block-aux!
   [{:block/keys [uuid repo] :as _block} children?]
   (let [repo (or repo (state/get-current-repo))
-        block (db/pull repo '[*] [:block/uuid uuid])]
+        block (db/pull repo '[*] [:block/uuid uuid])
+        opts (cond-> {:outliner-op :delete-blocks}
+               (config/db-based-graph? repo)
+               (assoc :persist-op? true :repo repo))]
     (when block
       (outliner-tx/transact!
-       {:outliner-op :delete-blocks}
+       opts
        (outliner-core/delete-blocks! [block] {:children? children?})))))
 
 (defn- move-to-prev-block
@@ -748,7 +764,9 @@
                                       {:outliner-op :delete-blocks}
                                        concat-prev-block?
                                        (assoc :concat-data
-                                              {:last-edit-block (:block/uuid block)}))]
+                                              {:last-edit-block (:block/uuid block)})
+                                       (config/db-based-graph? repo)
+                                       (assoc :persist-op? true :repo repo))]
                    (outliner-tx/transact! transact-opts
                                           (if concat-prev-block?
                                             (let [prev-block' (if (seq (:block/_refs block-e))
@@ -768,10 +786,13 @@
     (let [uuid->dom-block (zipmap block-uuids dom-blocks)
           block (first blocks)
           block-parent (get uuid->dom-block (:block/uuid block))
-          sibling-block (when block-parent (util/get-prev-block-non-collapsed-non-embed block-parent))]
+          sibling-block (when block-parent (util/get-prev-block-non-collapsed-non-embed block-parent))
+          opts (cond-> {:outliner-op :delete-blocks}
+                 (config/db-based-graph? repo)
+                 (assoc :persist-op? true :repo repo))]
       (prn {:blocks blocks})
       (outliner-tx/transact!
-       {:outliner-op :delete-blocks}
+       opts
        (outliner-core/delete-blocks! blocks {}))
       (when sibling-block
         (move-to-prev-block repo sibling-block
@@ -1215,10 +1236,14 @@
 
 (defn save-blocks!
   [blocks]
-  (outliner-tx/transact!
-   {:outliner-op :save-block}
-   (doseq [[block value] blocks]
-     (save-block-if-changed! block value))))
+  (let [repo (state/get-current-repo)
+        opts (cond-> {:outliner-op :save-block}
+               (config/db-based-graph? repo)
+               (assoc :persist-op? true :repo repo))]
+    (outliner-tx/transact!
+     opts
+     (doseq [[block value] blocks]
+       (save-block-if-changed! block value)))))
 
 (defn save-current-block!
   "skip-properties? if set true, when editing block is likely be properties, skip saving"
@@ -1652,9 +1677,13 @@
     (util/stop event)
     (save-current-block!)
     (let [edit-block-id (:block/uuid (state/get-edit-block))
+          repo (state/get-current-repo)
+          transact-opts (cond-> {:outliner-op :move-blocks}
+                          (config/db-based-graph? repo)
+                          (assoc :persist-op? true :repo repo))
           move-nodes (fn [blocks]
                        (outliner-tx/transact!
-                        {:outliner-op :move-blocks}
+                        transact-opts
                         (outliner-core/move-blocks-up-down! blocks up?))
                        (when-let [block-node (util/get-first-block-by-id (:block/uuid (first blocks)))]
                          (.scrollIntoView block-node #js {:behavior "smooth" :block "nearest"})))]
@@ -1683,11 +1712,15 @@
 (defn on-tab
   "`direction` = :left | :right."
   [direction]
-  (let [blocks (get-selected-ordered-blocks)]
+  (let [blocks (get-selected-ordered-blocks)
+        repo (state/get-current-repo)
+        opts (cond-> {:outliner-op :move-blocks
+                      :real-outliner-op :indent-outdent}
+               (config/db-based-graph? repo)
+               (assoc :persist-op? true :repo repo))]
     (when (seq blocks)
       (outliner-tx/transact!
-       {:outliner-op :move-blocks
-        :real-outliner-op :indent-outdent}
+       opts
        (outliner-core/indent-outdent-blocks! blocks (= direction :right))))))
 
 (defn- get-link [format link label]
@@ -1972,12 +2005,16 @@
 
     (when has-unsaved-edits
       (outliner-tx/transact!
-       {:outliner-op :save-block}
+       (cond-> {:outliner-op :save-block}
+         (config/db-based-graph? repo)
+         (assoc :persist-op? true :repo repo))
        (outliner-core/save-block! editing-block)))
 
     (outliner-tx/transact!
-     {:outliner-op :insert-blocks
-      :additional-tx revert-cut-txs}
+     (cond-> {:outliner-op :insert-blocks
+              :additional-tx revert-cut-txs}
+       (config/db-based-graph? repo)
+       (assoc :persist-op? true :repo repo))
      (when target-block'
        (let [format (or (:block/format target-block') (state/get-preferred-format))
              blocks' (map (fn [block]
@@ -2084,16 +2121,19 @@
                          false
 
                          :else
-                         true)]
+                         true)
+             transact-opts (cond-> {:outliner-op :insert-blocks
+                                    :created-from-journal-template? journal?}
+                             (config/db-based-graph? repo)
+                             (assoc :persist-op? true :repo repo))]
          (outliner-tx/transact!
-           {:outliner-op :insert-blocks
-            :created-from-journal-template? journal?}
-           (save-current-block!)
-           (let [result (outliner-core/insert-blocks! blocks'
-                                                      target
-                                                      (assoc opts
-                                                             :sibling? sibling?'))]
-             (edit-last-block-after-inserted! result))))))))
+          transact-opts
+          (save-current-block!)
+          (let [result (outliner-core/insert-blocks! blocks'
+                                                     target
+                                                     (assoc opts
+                                                            :sibling? sibling?'))]
+            (edit-last-block-after-inserted! result))))))))
 
 (defn template-on-chosen-handler
   [element-id]
@@ -2147,11 +2187,15 @@
 (defn outdent-on-enter
   [node]
   (when-not (parent-is-page? node)
-    (let [parent-node (tree/-get-parent node)]
+    (let [parent-node (tree/-get-parent node)
+          repo (state/get-current-repo)
+          opts (cond-> {:outliner-op :move-blocks
+                        :real-outliner-op :indent-outdent}
+                 (config/db-based-graph? repo)
+                 (assoc :persist-op? true :repo repo))]
       (save-current-block!)
       (outliner-tx/transact!
-       {:outliner-op :move-blocks
-        :real-outliner-op :indent-outdent}
+       opts
        (outliner-core/move-blocks! [(:data node)] (:data parent-node) true)))))
 
 (defn- last-top-level-child?
@@ -2409,10 +2453,15 @@
             (outdent-on-enter current-node)
 
             :else
-            (profile
-             "Insert block"
-             (outliner-tx/transact! {:outliner-op :insert-blocks}
-               (insert-new-block! state)))))))))
+            (let [repo (state/get-current-repo)
+                  opts (cond-> {:outliner-op :insert-blocks}
+                         (config/db-based-graph? repo)
+                         (assoc :persist-op? true :repo repo))]
+              (profile
+               "Insert block"
+               (outliner-tx/transact!
+                opts
+                (insert-new-block! state))))))))))
 
 (defn- inside-of-single-block
   "When we are in a single block wrapper, we should always insert a new line instead of new block"
@@ -2578,9 +2627,6 @@
 
       :else
       (let [edit-block (state/get-edit-block)
-            transact-opts {:outliner-op :delete-blocks
-                           :concat-data {:last-edit-block (:block/uuid edit-block)
-                                         :end? true}}
             next-block-has-refs? (some? (:block/_refs (db/entity (:db/id next-block))))
             new-content (if next-block-has-refs?
                           (str value ""
@@ -2593,10 +2639,16 @@
                           (assoc edit-block
                                  :block/uuid (:block/uuid next-block)
                                  :block.temp/additional-properties (dissoc (:block/properties next-block) :block/uuid))
-                          edit-block)]
-        (outliner-tx/transact! transact-opts
-          (delete-block-aux! next-block false)
-          (save-block! repo edit-block' new-content {:editor/op :delete}))
+                          edit-block)
+            transact-opts (cond-> {:outliner-op :delete-blocks
+                                   :concat-data {:last-edit-block (:block/uuid edit-block)
+                                                 :end? true}}
+                            (config/db-based-graph? repo)
+                            (assoc :persist-op? true :repo repo))]
+        (outliner-tx/transact!
+         transact-opts
+         (delete-block-aux! next-block false)
+         (save-block! repo edit-block' new-content {:editor/op :delete}))
         (let [block (if next-block-has-refs? next-block edit-block)]
           (edit-block! block current-pos (:block/uuid block)))))))
 
@@ -2717,12 +2769,16 @@
   (save-current-block!)
   (state/set-editor-op! :indent-outdent)
   (let [pos (some-> (state/get-input) cursor/pos)
-        {:keys [block]} (get-state)]
+        {:keys [block]} (get-state)
+        repo (state/get-current-repo)
+        opts (cond-> {:outliner-op :move-blocks
+                      :real-outliner-op :indent-outdent}
+               (config/db-based-graph? repo)
+               (assoc :persist-op? true :repo repo))]
     (when block
       (state/set-editor-last-pos! pos)
       (outliner-tx/transact!
-       {:outliner-op :move-blocks
-        :real-outliner-op :indent-outdent}
+       opts
        (outliner-core/indent-outdent-blocks! [block] indent?)))
     (state/set-editor-op! :nil)))
 
@@ -3378,18 +3434,21 @@
         repo (state/get-current-repo)
         value (boolean value)]
     (when repo
-      (save-current-block!) ;; Save the input contents before collapsing
-      (outliner-tx/transact! ;; Save the new collapsed state as an undo transaction (if it changed)
-        {:outliner-op :collapse-expand-blocks}
+      (let [opts (cond-> {:outliner-op :collapse-expand-blocks}
+                   (config/db-based-graph? repo)
+                   (assoc :persist-op? true :repo repo))]
+        (save-current-block!) ;; Save the input contents before collapsing
+        (outliner-tx/transact! ;; Save the new collapsed state as an undo transaction (if it changed)
+         opts
+         (doseq [block-id block-ids]
+           (when-let [block (db/entity [:block/uuid block-id])]
+             (let [current-value (boolean (:block/collapsed? block))]
+               (when-not (= current-value value)
+                 (let [block {:block/uuid block-id
+                              :block/collapsed? value}]
+                   (outliner-core/save-block! block)))))))
         (doseq [block-id block-ids]
-          (when-let [block (db/entity [:block/uuid block-id])]
-            (let [current-value (boolean (:block/collapsed? block))]
-              (when-not (= current-value value)
-                (let [block {:block/uuid block-id
-                             :block/collapsed? value}]
-                  (outliner-core/save-block! block)))))))
-      (doseq [block-id block-ids]
-        (state/set-collapsed-block! block-id value)))))
+          (state/set-collapsed-block! block-id value))))))
 
 (defn collapse-block! [block-id]
   (when (collapsable? block-id)
@@ -3724,10 +3783,10 @@
     (if (config/db-based-graph? repo)
       (property-handler/batch-set-block-property! repo block-ids :heading heading)
       (outliner-tx/transact!
-        {:outliner-op :save-block}
-        (doseq [block-id block-ids]
-          (when-let [block (set-heading-aux! repo block-id heading)]
-            (outliner-core/save-block! block)))))))
+       {:outliner-op :save-block}
+       (doseq [block-id block-ids]
+         (when-let [block (set-heading-aux! repo block-id heading)]
+           (outliner-core/save-block! block)))))))
 
 (defn set-heading!
   [block-id heading]
@@ -3737,7 +3796,6 @@
   [block-id]
   (set-heading! block-id nil))
 
-
 (defn batch-remove-heading!
   [block-ids]
   (batch-set-heading! block-ids nil))

+ 3 - 1
src/main/frontend/handler/repo.cljs

@@ -36,7 +36,8 @@
             [logseq.common.config :as common-config]
             [frontend.db.react :as react]
             [frontend.db.listener :as db-listener]
-            [frontend.modules.outliner.core :as outliner-core]))
+            [frontend.modules.outliner.core :as outliner-core]
+            [frontend.db.rtc.core :as rtc-core]))
 
 ;; Project settings should be checked in two situations:
 ;; 1. User changes the config.edn directly in logseq.com (fn: alter-file)
@@ -409,6 +410,7 @@
   (p/do!
    (state/set-db-restoring! true)
    (db-restore/restore-graph! repo)
+   (rtc-core/init-rtc-op-db repo)
    (repo-config-handler/restore-repo-config! repo)
    (when (config/global-config-enabled?)
      (global-config-handler/restore-global-config!))

+ 32 - 2
src/main/frontend/modules/outliner/core.cljs

@@ -17,7 +17,9 @@
             [cljs.spec.alpha :as s]
             [frontend.format.block :as block]
             [frontend.handler.file-based.property.util :as property-util]
-            [frontend.handler.property.util :as pu]))
+            [frontend.handler.property.util :as pu]
+            [frontend.db.rtc.op :as rtc-op]
+            [clojure.core.async :as async]))
 
 (s/def ::block-map (s/keys :opt [:db/id :block/uuid :block/page :block/left :block/parent]))
 
@@ -974,24 +976,52 @@
 
 (defn save-block!
   [block]
+  (let [repo (:repo (*transaction-opts* 0))
+        persist-op? (:persist-op? (*transaction-opts* 0))]
+    (when (and persist-op? repo)
+      (rtc-op/<update-block-op! repo (:block/uuid block) (select-keys block [:block/content]))))
   (op-transact! #'save-block block))
 
 (defn insert-blocks!
   [blocks target-block opts]
-  (op-transact! #'insert-blocks blocks target-block opts))
+  (let [r (op-transact! #'insert-blocks blocks target-block opts)
+        repo (:repo (*transaction-opts* 0))
+        persist-op? (:persist-op? (*transaction-opts* 0))]
+    (when (and persist-op? repo)
+      (async/go
+        (rtc-op/<move-block-op! repo (keep :block/uuid (:blocks r)))
+        ;; (rtc-op/<update-block-op! repo (:block/uuid))
+        ))
+    r))
 
 (defn delete-blocks!
   [blocks opts]
+  (let [repo (:repo (*transaction-opts* 0))
+        persist-op? (:persist-op? (*transaction-opts* 0))]
+    (when (and persist-op? repo)
+      (rtc-op/<remove-blocks-op! repo (keep :block/uuid blocks))))
   (op-transact! #'delete-blocks blocks opts))
 
 (defn move-blocks!
   [blocks target-block sibling?]
+  (let [repo (:repo (*transaction-opts* 0))
+        persist-op? (:persist-op? (*transaction-opts* 0))]
+    (when (and persist-op? repo)
+      (rtc-op/<move-block-op! repo (keep :block/uuid blocks))))
   (op-transact! #'move-blocks blocks target-block {:sibling? sibling?}))
 
 (defn move-blocks-up-down!
   [blocks up?]
+  (let [repo (:repo (*transaction-opts* 0))
+        persist-op? (:persist-op? (*transaction-opts* 0))]
+    (when (and persist-op? repo)
+      (rtc-op/<move-block-op! repo (keep :block/uuid blocks))))
   (op-transact! #'move-blocks-up-down blocks up?))
 
 (defn indent-outdent-blocks!
   [blocks indent?]
+  (let [repo (:repo (*transaction-opts* 0))
+        persist-op? (:persist-op? (*transaction-opts* 0))]
+    (when (and persist-op? repo)
+      (rtc-op/<move-block-op! repo (keep :block/uuid blocks))))
   (op-transact! #'indent-outdent-blocks blocks indent?))

+ 6 - 3
src/main/frontend/modules/outliner/transaction.cljc

@@ -15,7 +15,9 @@
             {:graph \"Which graph will be transacted to\"
              :outliner-op \"For example, :save-block, :insert-blocks, etc. \"
              :additional-tx \"Additional tx data that can be bundled together
-                              with the body in this macro.\"}
+                              with the body in this macro.\"
+             :persist-op? \"Boolean, store ops into db (sqlite)\"
+             :repo \"Needed when :persist-op? is true\"}
   `Example`:
   (transact! {:graph \"test\"}
     (insert-blocks! ...)
@@ -23,9 +25,10 @@
     (move-blocks! ...)
     (delete-blocks! ...))"
   [opts & body]
-  (assert (or (map? opts) (symbol? opts)) (str "opts is not a map or symbol, type: " (type opts)))
+
   `(let [transact-data# frontend.modules.outliner.core/*transaction-data*
          transaction-opts# frontend.modules.outliner.core/*transaction-opts*
+         _# (assert (or (map? ~opts) (symbol? ~opts)) (str "opts is not a map or symbol, type: " (type ~opts)))
          opts# (if transact-data#
                  (assoc ~opts :nested-transaction? true)
                  ~opts)
@@ -37,7 +40,7 @@
          ~@body)
        (binding [frontend.modules.outliner.core/*transaction-data* (transient [])
                  frontend.modules.outliner.core/*transaction-opts* (transient [])]
-         (conj! frontend.modules.outliner.core/*transaction-opts* transaction-opts# opts#)
+         (conj! frontend.modules.outliner.core/*transaction-opts* opts#)
          ~@body
          (let [r# (persistent! frontend.modules.outliner.core/*transaction-data*)
                tx# (mapcat :tx-data r#)