瀏覽代碼

Disable graph switch if files are not saved yet

Tienson Qin 2 年之前
父節點
當前提交
e22effacf2

+ 5 - 4
src/main/frontend/handler/events.cljs

@@ -188,12 +188,13 @@
 
 (defmethod handle :graph/switch [[_ graph opts]]
   (let [^js sqlite @db-browser/*worker]
-    (p/let [writes-finished? (when sqlite (.file-writes-finished? sqlite))]
-      (if (or writes-finished? (:sync-graph/init? @state/state))
-        (graph-switch-on-persisted graph opts)
+    (p/let [writes-finished? (when sqlite (.file-writes-finished? sqlite))
+            request-finished? (ldb/request-finished?)]
+      (if (or (not request-finished?) (not writes-finished?)) ; TODO: test (:sync-graph/init? @state/state)
         (notification/show!
          "Please wait seconds until all changes are saved for the current graph."
-         :warning)))))
+         :warning)
+        (graph-switch-on-persisted graph opts)))))
 
 (defmethod handle :graph/pull-down-remote-graph [[_ graph dir-name]]
   (if (mobile-util/native-ios?)

+ 27 - 16
src/main/frontend/worker/file.cljs

@@ -2,6 +2,7 @@
   "Save pages to files for file-based graphs"
   (:require [clojure.core.async :as async]
             [clojure.string :as string]
+            [clojure.set :as set]
             [frontend.worker.file.core :as file]
             [logseq.outliner.tree :as otree]
             [lambdaisland.glogi :as log]
@@ -13,17 +14,20 @@
             [malli.core :as m]
             [frontend.worker.state :as state]
             [goog.object :as gobj]
-            [logseq.db.sqlite.util :as sqlite-util]))
+            [logseq.db.sqlite.util :as sqlite-util]
+            [logseq.common.util :as common-util]))
 
 (def *writes file/*writes)
 (def dissoc-request! file/dissoc-request!)
+(def conj-page-write! file/conj-page-write!)
 
 (defonce file-writes-chan
   (let [coercer (m/coercer [:catn
                             [:repo :string]
                             [:page-id :any]
                             [:outliner-op :any]
-                            [:epoch :int]])]
+                            [:epoch :int]
+                            [:request-id :int]])]
     (async/chan 10000 (map coercer))))
 
 (def batch-write-interval 1000)
@@ -55,7 +59,7 @@
     (dissoc block :db/id :block/page)))
 
 (defn do-write-file!
-  [repo conn page-db-id outliner-op context]
+  [repo conn page-db-id outliner-op context request-id]
   (let [page-block (d/pull @conn '[*] page-db-id)
         page-db-id (:db/id page-block)
         whiteboard? (contains? (set (:block/type page-block)) "whiteboard")
@@ -65,7 +69,7 @@
     (when (or (>= blocks-count 1) blocks-just-deleted?)
       (if (and (or (> blocks-count 500) whiteboard?)
                (not (state/tx-idle? repo {:diff 3000})))
-        (async/put! file-writes-chan [repo page-db-id outliner-op (tc/to-long (t/now))])
+        (async/put! file-writes-chan [repo page-db-id outliner-op (tc/to-long (t/now)) request-id])
         (let [pull-keys (if whiteboard? whiteboard-blocks-pull-keys-with-persisted-ids '[*])
               blocks (ldb/get-page-blocks @conn (:block/name page-block) {:pull-keys pull-keys})
               blocks (if whiteboard? (map cleanup-whiteboard-block blocks) blocks)]
@@ -76,22 +80,28 @@
             (let [tree-or-blocks (if whiteboard? blocks
                                      (otree/blocks->vec-tree repo @conn blocks (:block/name page-block)))]
               (if page-block
-                (file/save-tree! repo conn page-block tree-or-blocks blocks-just-deleted? context)
+                (file/save-tree! repo conn page-block tree-or-blocks blocks-just-deleted? context request-id)
                 (js/console.error (str "can't find page id: " page-db-id))))))))))
 
 (defn write-files!
   [conn pages context]
   (when (seq pages)
-    (doseq [[repo page-id outliner-op] (set (map #(take 3 %) pages))] ; remove time to dedupe pages to write
-      (try (do-write-file! repo conn page-id outliner-op context)
-           (catch :default e
-             (worker-util/post-message :notification
-                                       (pr-str
-                                        [[:div
-                                          [:p "Write file failed, please copy the changes to other editors in case of losing data."]
-                                          "Error: " (str (gobj/get e "stack"))]
-                                         :error]))
-             (log/error :file/write-file-error {:error e}))))))
+    (let [all-request-ids (set (map last pages))
+          distincted-pages (common-util/distinct-by #(take 3 %) pages)
+          repeated-ids (set/difference all-request-ids (set (map last distincted-pages)))]
+      (doseq [id repeated-ids]
+        (dissoc-request! id))
+
+      (doseq [[repo page-id outliner-op _time request-id] distincted-pages]
+        (try (do-write-file! repo conn page-id outliner-op context request-id)
+             (catch :default e
+               (worker-util/post-message :notification
+                                         (pr-str
+                                          [[:div
+                                            [:p "Write file failed, please copy the changes to other editors in case of losing data."]
+                                            "Error: " (str (gobj/get e "stack"))]
+                                           :error]))
+               (log/error :file/write-file-error {:error e})))))))
 
 (defn sync-to-file
   [repo page-id tx-meta]
@@ -99,7 +109,8 @@
              page-id
              (not (:created-from-journal-template? tx-meta))
              (not (:delete-files? tx-meta)))
-    (async/put! file-writes-chan [repo page-id (:outliner-op tx-meta) (tc/to-long (t/now))])))
+    (let [request-id (conj-page-write! page-id)]
+      (async/put! file-writes-chan [repo page-id (:outliner-op tx-meta) (tc/to-long (t/now)) request-id]))))
 
 (defn <ratelimit-file-writes!
   []

+ 4 - 5
src/main/frontend/worker/file/core.cljs

@@ -151,7 +151,7 @@
 (defn- remove-transit-ids [block] (dissoc block :db/id :block/file))
 
 (defn save-tree-aux!
-  [repo db page-block tree blocks-just-deleted? context]
+  [repo db page-block tree blocks-just-deleted? context request-id]
   (let [page-block (d/pull db '[*] (:db/id page-block))
         file-db-id (-> page-block :block/file :db/id)
         file-path (-> (d/entity db file-db-id) :file/path)]
@@ -165,8 +165,7 @@
         (when-not (and (string/blank? new-content) (not blocks-just-deleted?))
           (let [files [[file-path new-content]]]
             (when (seq files)
-              (let [page-id (:db/id page-block)
-                    request-id (conj-page-write! page-id)]
+              (let [page-id (:db/id page-block)]
                 (util/post-message :write-files (pr-str {:request-id request-id
                                                          :page-id page-id
                                                          :repo repo
@@ -175,10 +174,10 @@
       (js/console.error "File path from page-block is not valid" page-block tree))))
 
 (defn save-tree!
-  [repo conn page-block tree blocks-just-deleted? context]
+  [repo conn page-block tree blocks-just-deleted? context request-id]
   {:pre [(map? page-block)]}
   (when repo
-    (let [ok-handler #(save-tree-aux! repo @conn page-block tree blocks-just-deleted? context)
+    (let [ok-handler #(save-tree-aux! repo @conn page-block tree blocks-just-deleted? context request-id)
           file (or (:block/file page-block)
                    (when-let [page-id (:db/id (:block/page page-block))]
                      (:block/file (d/entity @conn page-id))))]

+ 4 - 2
src/main/frontend/worker/pipeline.cljs

@@ -75,8 +75,10 @@
       (if (or from-disk? new-graph?)
         {:tx-report tx-report}
         (let [{:keys [pages blocks]} (ds-report/get-blocks-and-pages tx-report)
-              _ (doseq [page pages]
-                  (file/sync-to-file repo (:db/id page) tx-meta))
+              _ (when (sqlite-util/local-file-based-graph? repo)
+                  (let [page-ids (distinct (map :db/id pages))]
+                    (doseq [page-id page-ids]
+                      (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