Browse Source

fix: undo && redo

batch-txs need to be sorted first.
Tienson Qin 1 year ago
parent
commit
ea566f7d5f

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

@@ -44,7 +44,7 @@
     (p/do!
      @*last-request
      (when-let [repo (state/get-current-repo)]
-       (when-let [current-page-uuid-str (some->> (page-util/get-editing-page-id)
+       (when-let [current-page-uuid-str (some->> (page-util/get-latest-edit-page-id)
                                                  db/entity
                                                  :block/uuid
                                                  str)]
@@ -64,7 +64,7 @@
     (p/do!
      @*last-request
      (when-let [repo (state/get-current-repo)]
-       (when-let [current-page-uuid-str (some->> (page-util/get-editing-page-id)
+       (when-let [current-page-uuid-str (some->> (page-util/get-latest-edit-page-id)
                                                  db/entity
                                                  :block/uuid
                                                  str)]

+ 4 - 3
src/main/frontend/util/page.cljs

@@ -20,12 +20,13 @@
     (or (and page-name (:db/id (db/entity [:block/name page-name])))
         (get-in (first (state/get-editor-args)) [:block :block/page :db/id]))))
 
-(defn get-editing-page-id
-  "Fetch the editing page id. If there is an edit-input-id set, we are probably still 
+(defn get-latest-edit-page-id
+  "Fetch the editing page id. If there is an edit-input-id set, we are probably still
    on editing mode"
   []
-  (if (or (state/editing?) (state/get-edit-input-id))
+  (or
     (get-in (first (state/get-editor-args)) [:block :block/page :db/id])
+    ;; not found
     (get-current-page-id)))
 
 (defn get-page-file-rpath

+ 8 - 8
src/main/frontend/worker/batch_tx.clj

@@ -7,11 +7,11 @@
   2. run body
   3. exit batch-tx mode"
   [conn & body]
-  `(do (d/transact! ~conn [{:db/ident :logseq.kv/tx-batch-mode? :editor/tx-batch-mode? true}]
-                    {:tx-batch? true
-                     :gen-undo-op? false})
-       ~@body
-       (d/transact! ~conn [{:db/ident :logseq.kv/tx-batch-mode? :editor/tx-batch-mode? false}]
-                    {:tx-batch? true
-                     :gen-undo-op? false})
-       (frontend.worker.batch-tx/clear-batch-txs!)))
+  `(do
+     (d/transact! ~conn [{:db/ident :logseq.kv/tx-batch-mode? :editor/tx-batch-mode? true}]
+                  {:gen-undo-op? false})
+     (frontend.worker.batch-tx/set-batch-db-before! @~conn)
+     ~@body
+     (d/transact! ~conn [{:db/ident :logseq.kv/tx-batch-mode? :editor/tx-batch-mode? false}]
+                  {:gen-undo-op? false})
+     (frontend.worker.batch-tx/exit-batch-txs-mode!)))

+ 15 - 5
src/main/frontend/worker/batch_tx.cljs

@@ -5,17 +5,27 @@
             [frontend.schema-register :include-macros true :as sr]))
 
 
-(sr/defkeyword :tx/batch-txs
+(sr/defkeyword :batch/txs
   "store all tx-data when batch-processing")
 
 (defn get-batch-txs
   []
-  (:tx/batch-txs @worker-state/*state))
+  (->> (:batch/txs @worker-state/*state)
+       (sort-by :tx)))
+
+(defn set-batch-db-before!
+  [db]
+  (swap! worker-state/*state assoc :batch/db-before db))
+
+(defn get-batch-db-before
+  []
+  (:batch/db-before @worker-state/*state))
 
 (defn conj-batch-txs!
   [tx-data]
-  (swap! worker-state/*state update :tx/batch-txs (fn [data] (into data tx-data))))
+  (swap! worker-state/*state update :batch/txs (fn [data] (into data tx-data))))
 
-(defn clear-batch-txs!
+(defn exit-batch-txs-mode!
   []
-  (swap! worker-state/*state assoc :tx/batch-txs nil))
+  (swap! worker-state/*state assoc :batch/txs nil)
+  (swap! worker-state/*state assoc :batch/db-before nil))

+ 21 - 20
src/main/frontend/worker/db_listener.cljs

@@ -35,27 +35,28 @@
 
 (defmethod listen-db-changes :sync-db-to-main-thread
   [_ {:keys [tx-meta repo conn] :as tx-report}]
-  (let [{:keys [pipeline-replace? from-disk?]} tx-meta
-                     result (worker-pipeline/invoke-hooks repo conn tx-report (worker-state/get-context))
-                     tx-report' (or (:tx-report result) tx-report)]
-                 (when-not pipeline-replace?
-                   (let [data (merge
-                               {:request-id (:request-id tx-meta)
-                                :repo repo
-                                :tx-data (:tx-data tx-report')
-                                :tx-meta tx-meta}
-                               (dissoc result :tx-report))]
-                     (worker-util/post-message :sync-db-changes data))
+  (let [{:keys [pipeline-replace? from-disk?]} tx-meta]
+    (when-not pipeline-replace?
+      (let [result (worker-pipeline/invoke-hooks repo conn tx-report (worker-state/get-context))
+            tx-report' (:tx-report result)]
+        (when result
+          (let [data (merge
+                      {:request-id (:request-id tx-meta)
+                       :repo repo
+                       :tx-data (:tx-data tx-report')
+                       :tx-meta tx-meta}
+                      (dissoc result :tx-report))]
+            (worker-util/post-message :sync-db-changes data))
 
-                   (when-not from-disk?
-                     (p/do!
-                      (let [{:keys [blocks-to-remove-set blocks-to-add]} (search/sync-search-indice repo tx-report')
-                            ^js wo (worker-state/get-worker-object)]
-                        (when wo
-                          (when (seq blocks-to-remove-set)
-                            (.search-delete-blocks wo repo (bean/->js blocks-to-remove-set)))
-                          (when (seq blocks-to-add)
-                            (.search-upsert-blocks wo repo (bean/->js blocks-to-add))))))))))
+          (when-not from-disk?
+            (p/do!
+             (let [{:keys [blocks-to-remove-set blocks-to-add]} (search/sync-search-indice repo tx-report')
+                   ^js wo (worker-state/get-worker-object)]
+               (when wo
+                 (when (seq blocks-to-remove-set)
+                   (.search-delete-blocks wo repo (bean/->js blocks-to-remove-set)))
+                 (when (seq blocks-to-add)
+                   (.search-upsert-blocks wo repo (bean/->js blocks-to-add))))))))))))
 
 
 (defn listen-db-changes!

+ 63 - 51
src/main/frontend/worker/pipeline.cljs

@@ -76,61 +76,73 @@
 
 (defn invoke-hooks
   [repo conn {:keys [db-before db-after] :as tx-report} context]
-  (when-not (:pipeline-replace? (:tx-meta tx-report))
-    (let [tx-meta (:tx-meta tx-report)
-          {:keys [from-disk? new-graph?]} tx-meta]
-      (if (or from-disk? new-graph?)
-        {:tx-report tx-report}
-        (let [{:keys [pages blocks]} (ds-report/get-blocks-and-pages tx-report)
-              _ (when (sqlite-util/local-file-based-graph? repo)
-                  (let [page-ids (distinct (map :db/id pages))]
-                    (doseq [page-id page-ids]
-                      (when (d/entity @conn page-id)
-                        (file/sync-to-file repo page-id tx-meta)))))
-              deleted-block-uuids (set (outliner-pipeline/filter-deleted-blocks (:tx-data tx-report)))
-              replace-tx (concat
+  (let [tx-meta (:tx-meta tx-report)
+        {:keys [from-disk? new-graph?]} tx-meta
+        now-batch-processing? (:editor/tx-batch-mode? (d/entity db-after :logseq.kv/tx-batch-mode?))]
+    (cond
+      now-batch-processing?
+      (do
+        (batch-tx/conj-batch-txs! (:tx-data tx-report))
+        nil)
+
+      (or from-disk? new-graph?)
+      {:tx-report tx-report}
+
+      :else
+      (let [exiting-batch-mode? (:editor/tx-batch-mode? (d/entity db-before :logseq.kv/tx-batch-mode?))
+            db-before (if exiting-batch-mode?
+                        (batch-tx/get-batch-db-before)
+                        (:db-before tx-report))
+            tx-data (if exiting-batch-mode?
+                      (batch-tx/get-batch-txs)
+                      (:tx-data tx-report))
+            tx-report (assoc tx-report
+                             :db-before db-before
+                             :tx-data tx-data)
+            {:keys [pages blocks]} (ds-report/get-blocks-and-pages tx-report)
+            _ (when (sqlite-util/local-file-based-graph? repo)
+                (let [page-ids (distinct (map :db/id pages))]
+                  (doseq [page-id page-ids]
+                    (when (d/entity @conn page-id)
+                      (file/sync-to-file repo page-id tx-meta)))))
+            deleted-block-uuids (set (outliner-pipeline/filter-deleted-blocks (:tx-data tx-report)))
+            replace-tx (concat
                             ;; block path refs
-                          (set (compute-block-path-refs-tx tx-report blocks))
+                        (set (compute-block-path-refs-tx tx-report blocks))
 
                             ;; delete empty property parent block
-                          (when (seq deleted-block-uuids)
-                            (delete-property-parent-block-if-empty tx-report deleted-block-uuids))
+                        (when (seq deleted-block-uuids)
+                          (delete-property-parent-block-if-empty tx-report deleted-block-uuids))
 
                             ;; update block/tx-id
-                          (let [updated-blocks (remove (fn [b] (contains? (set deleted-block-uuids) (:block/uuid b))) blocks)
-                                tx-id (get-in tx-report [:tempids :db/current-tx])]
-                            (->>
-                             (map (fn [b]
-                                    (when-let [db-id (:db/id b)]
-                                      {:db/id db-id
-                                       :block/tx-id tx-id})) updated-blocks)
-                             (remove nil?))))
-              tx-report' (or
-                          (when (seq replace-tx)
+                        (let [updated-blocks (remove (fn [b] (contains? (set deleted-block-uuids) (:block/uuid b)))
+                                                     (concat pages blocks))
+                              tx-id (get-in tx-report [:tempids :db/current-tx])]
+                          (->>
+                           (map (fn [b]
+                                  (when-let [db-id (:db/id b)]
+                                    {:db/id db-id
+                                     :block/tx-id tx-id})) updated-blocks)
+                           (remove nil?))))
+            tx-report' (or
+                        (when (seq replace-tx)
                             ;; TODO: remove this since transact! is really slow
-                            (ldb/transact! conn replace-tx {:replace? true
-                                                            :pipeline-replace? true}))
-                          (do
-                            (d/store @conn)
-                            tx-report))
-              fix-tx-data (validate-and-fix-db! repo conn tx-report context)
-              before-batch-mode? (:editor/tx-batch-mode? (d/entity db-before :logseq.kv/tx-batch-mode?))
-              now-batch-processing? (:editor/tx-batch-mode? (d/entity db-after :logseq.kv/tx-batch-mode?))
-              exiting-batch-mode? (and before-batch-mode? (not now-batch-processing?))
-              full-tx-data (concat (:tx-data tx-report)
+                          (ldb/transact! conn replace-tx {:replace? true
+                                                          :pipeline-replace? true}))
+                        (do
+                          (d/store @conn)
+                          tx-report))
+            fix-tx-data (validate-and-fix-db! repo conn tx-report context)
+            full-tx-data (if exiting-batch-mode?
+                           (:tx-data tx-report)
+                           (concat (:tx-data tx-report)
                                    fix-tx-data
-                                   (:tx-data tx-report')
-                                   (when exiting-batch-mode?
-                                     (batch-tx/get-batch-txs)))
-              final-tx-report (assoc tx-report'
-                                     :tx-data full-tx-data
-                                     :db-before (:db-before tx-report))
-              affected-query-keys (when-not (or (:importing? context) now-batch-processing?)
-                                    (worker-react/get-affected-queries-keys final-tx-report))]
-          (when now-batch-processing?
-            (batch-tx/conj-batch-txs! full-tx-data))
-          {:tx-report final-tx-report
-           :affected-keys affected-query-keys
-           :deleted-block-uuids deleted-block-uuids
-           :pages pages
-           :blocks blocks})))))
+                                   (:tx-data tx-report')))
+            final-tx-report (assoc tx-report' :tx-data full-tx-data)
+            affected-query-keys (when-not (:importing? context)
+                                  (worker-react/get-affected-queries-keys final-tx-report))]
+        {:tx-report final-tx-report
+         :affected-keys affected-query-keys
+         :deleted-block-uuids deleted-block-uuids
+         :pages pages
+         :blocks blocks}))))

+ 2 - 1
src/main/frontend/worker/state.cljs

@@ -19,7 +19,8 @@
                        :config {}
                        :git/current-repo nil
 
-                       :tx/batch-txs nil
+                       :batch/txs []
+                       :batch/db-before nil
 
                        :rtc/downloading-graph? false