ソースを参照

fix: load transit file on graph switching

Junyi Du 3 年 前
コミット
4f533fd5a8

+ 9 - 6
src/electron/electron/fs_watcher.cljs

@@ -17,6 +17,7 @@
 (defonce file-watcher-chan "file-watcher")
 (defn- send-file-watcher! [dir type payload]
   ;; Should only send to one window; then dbsync will do his job
+  ;; If no window is on this graph, just ignore
   (some (fn [^js win]
           (when-not (.isDestroyed win)
             (.. win -webContents
@@ -67,21 +68,23 @@
              (println "Watch error happened: "
                       {:path path})))
 
+      ;; electron app extends `EventEmitter`
+      ;; TODO check: duplicated with the logic in "window-all-closed" ?
       (.on app "quit" watcher-del-f)
 
       true)))
 
 (defn close-watcher!
+  "If no `dir` provided, close all watchers;
+   Otherwise, close the specific watcher"
   ([]
    (doseq [[watcher watcher-del-f] (vals @*file-watcher)]
      (.close watcher)
-     (.on app "quit" watcher-del-f))
+     (.removeListener app "quit" watcher-del-f))
    (reset! *file-watcher {}))
   ([dir]
-   (let [wins (window/get-graph-all-windows dir)
-         [watcher watcher-del-f] (get @*file-watcher dir)]
-     (when (and (<= (count wins) 1)
-                watcher)
+   (let [[watcher watcher-del-f] (get @*file-watcher dir)]
+     (when watcher ;; when there are multiple windows, 
        (.close watcher)
-       (.on app "quit" watcher-del-f)
+       (.removeListener app "quit" watcher-del-f)
        (swap! *file-watcher dissoc dir)))))

+ 13 - 7
src/electron/electron/handler.cljs

@@ -300,11 +300,6 @@
   (clear-cache!)
   (search/ensure-search-dir!))
 
-(defmethod handle :addDirWatcher [window [_ dir]]
-  (when dir
-    (watcher/close-watcher! dir)
-    (watcher/watch-dir! window dir)))
-
 (defmethod handle :openDialog [^js _window _messages]
   (open-dir-dialog))
 
@@ -385,6 +380,18 @@
         windows (filter #(.isVisible %) windows)]
     (> (count windows) 1)))
 
+(defmethod handle :addDirWatcher [^js window [_ dir]]
+  ;; Windows on same dir share the same watcher
+  ;; Only close file watcher when:
+  ;;    1. there is no one window on the same dir (TODO: check this on a window is closed)
+  ;;    2. reset file watcher to resend `add` event on window refreshing
+  (when dir
+    ;; adding dir watcher when the window has watcher already - must be cmd + r refreshing
+    ;; TODO: handle duplicated adding dir watcher when multiple windows
+    (when (not (graph-has-other-windows? window dir))
+      (watcher/close-watcher! dir))
+    (watcher/watch-dir! window dir)))
+
 (defmethod handle :searchVersionChanged?
   [^js _win [_ graph]]
   (search/version-changed? graph))
@@ -404,8 +411,7 @@
   (let [dir (utils/get-graph-dir graph)
         windows (win/get-graph-all-windows dir)
         windows (filter #(.isVisible %) windows)
-        tar-graph-win (first windows)
-        _ (prn "persist graph" graph)]
+        tar-graph-win (first windows)]
     (if tar-graph-win
       (utils/send-to-renderer tar-graph-win "persistGraph" graph)
       (utils/send-to-renderer win "persistGraphDone" graph)))) ;; if no such graph, skip directly

+ 30 - 25
src/main/frontend/db.cljs

@@ -159,35 +159,40 @@
                 (assoc option
                        :listen-handler listen-and-persist!))))
 
+(defn restore-graph!
+  "Restore db from serialized db cache, and swap into the current db status"
+  [repo me]
+  (p/let [db-name (datascript-db repo)
+          db-conn (d/create-conn db-schema/schema)
+          _ (swap! conns assoc db-name db-conn)
+          stored (db-persist/get-serialized-graph db-name)
+          logged? (:name me)
+          _ (if stored
+              (let [stored-db (try (string->db stored)
+                                   (catch js/Error _e
+                                     (js/console.warn "Invalid graph cache")
+                                     (d/empty-db db-schema/schema)))
+                    attached-db (d/db-with stored-db (concat
+                                                      [(me-tx stored-db me)]
+                                                      default-db/built-in-pages)) ;; TODO bug overriding uuids?
+                    db (if (old-schema? attached-db)
+                         (db-migrate/migrate attached-db)
+                         attached-db)]
+                (conn/reset-conn! db-conn db))
+              (when logged?
+                (d/transact! db-conn [(me-tx (d/db db-conn) me)])))]
+    (d/transact! db-conn [{:schema/version db-schema/version}])))
+
 ;; TODO: only restore the current graph instead of all the graphs to speedup and
 ;; reduce memory usage. pub event :graph/ready when a graph is restored, and finish the TODOs in :graph/ready
 (defn restore!
   [{:keys [repos] :as me} _old-db-schema restore-config-handler]
-  (let [logged? (:name me)]
-    (doall
-     (for [{:keys [url]} repos]
-       (let [repo url]
-         (p/let [db-name (datascript-db repo)
-                 db-conn (d/create-conn db-schema/schema)
-                 _ (swap! conns assoc db-name db-conn)
-                 stored (db-persist/get-serialized-graph db-name)
-                 _ (if stored
-                     (let [stored-db (try (string->db stored)
-                                          (catch js/Error _e
-                                            (js/console.warn "Invalid graph cache")
-                                            (d/empty-db db-schema/schema)))
-                           attached-db (d/db-with stored-db (concat
-                                                             [(me-tx stored-db me)]
-                                                             default-db/built-in-pages))
-                           db (if (old-schema? attached-db)
-                                (db-migrate/migrate attached-db)
-                                attached-db)]
-                       (conn/reset-conn! db-conn db))
-                     (when logged?
-                       (d/transact! db-conn [(me-tx (d/db db-conn) me)])))]
-           (d/transact! db-conn [{:schema/version db-schema/version}])
-           (restore-config-handler repo)
-           (listen-and-persist! repo)))))))
+  (doall
+   (for [{:keys [url]} repos]
+     (let [repo url]
+       (p/let [_ (restore-graph! repo me)]
+         (restore-config-handler repo)
+         (listen-and-persist! repo))))))
 
 (defn run-batch-txs!
   []

+ 5 - 1
src/main/frontend/fs/protocol.cljs

@@ -15,4 +15,8 @@
   (stat [this dir path])
   (open-dir [this ok-handler])
   (get-files [this path-or-handle ok-handler])
-  (watch-dir! [this dir]))
+  (watch-dir! [this dir]) 
+  ;; Ensure the dir is watched, window agnostic.
+  ;; Implementation should handle the actual watcher's construction / destruction.
+  ;; So shouldn't consider `unwatch-dir!`.
+  )

+ 6 - 4
src/main/frontend/handler.cljs

@@ -89,6 +89,7 @@
                    (when (and @interval js/window.pfs)
                      (js/clearInterval @interval)
                      (reset! interval nil)
+                     ;; `(state/set-db-restoring! true)` already executed before restoring
                      (-> (p/all (db/restore!
                                  (assoc me :repos repos)
                                  old-db-schema
@@ -109,6 +110,7 @@
                                    ;; Not native local directory
                                    (not (some config/local-db? (map :url repos)))
                                    (not (mobile-util/is-native-platform?)))
+                              ;; will execute `(state/set-db-restoring! false)` inside
                               (repo-handler/setup-local-repo-if-not-exists!)
 
                               :else
@@ -192,10 +194,10 @@
               (ipc/ipc "clearCache"))
           _ (idb/clear-local-storage-and-idb!)]
     (js/setTimeout
-      (fn [] (if (util/electron?)
-               (ipc/ipc :reloadWindowPage)
-               (js/window.location.reload)))
-      2000)))
+     (fn [] (if (util/electron?)
+              (ipc/ipc :reloadWindowPage)
+              (js/window.location.reload)))
+     2000)))
 
 (defn- register-components-fns!
   []

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

@@ -97,7 +97,8 @@
   (p/let [;; save current db
           _ (repo-handler/persist-db!)
           ;; ask other windows to persist the targeting db
-          _ (repo-handler/persist-otherwindow-db! graph)]
+          _ (repo-handler/persist-otherwindow-db! graph)
+          _ (repo-handler/restore-and-setup-repo! graph)]
     (graph-switch graph)))
 
 (defmethod handle :graph/switch [[_ graph]]

+ 20 - 28
src/main/frontend/handler/repo.cljs

@@ -556,6 +556,21 @@
              (ui-handler/re-render-root!)))
     (js/setTimeout setup-local-repo-if-not-exists! 100)))
 
+(defn restore-and-setup-repo!
+  "Restore the db of a graph from the persisted data, and setup.
+   Create a new conn, or replace the conn in state with a new one.
+   me: optional, identity data, can be retrieved from `(state/get-me)` or `nil`"
+  ([repo]
+   (restore-and-setup-repo! repo (state/get-me)))
+  ([repo me]
+   (p/let [_ (state/set-db-restoring! true)
+           _ (db/restore-graph! repo me)]
+     (file-handler/restore-config! repo false)
+    ;; Don't have to unlisten the old listerner, as it will be destroyed with the conn
+     (db/listen-and-persist! repo)
+     (ui-handler/add-style-if-exists!)
+     (state/set-db-restoring! false))))
+
 (defn periodically-pull-current-repo
   []
   (js/setInterval
@@ -649,28 +664,6 @@
     (push repo {:commit-message commit-message
                 :custom-commit? true})))
 
-(defn persist-all-dbs!
-  [{:keys [before on-success on-error]}]
-  (->
-   (p/let [repos (db-persist/get-all-graphs)
-           repos (-> repos
-                     (conj (state/get-current-repo))
-                     (distinct))]
-     (if (seq repos)
-       (do
-         (before)
-         (doseq [repo repos]
-           (metadata-handler/set-pages-metadata! repo))
-         (js/setTimeout
-          (fn []
-            (-> (p/all (map db/persist! repos))
-                (p/then on-success)))
-          100))
-       (on-success)))
-   (p/catch (fn [error]
-              (js/console.error error)
-              (on-error)))))
-
 (defn persist-db!
   ([]
    (persist-db! {}))
@@ -699,11 +692,10 @@
   [graph]
   (p/create (fn [resolve _]
               (js/window.apis.on "persistGraphDone"
-                                 (fn [data]
-                                   (let [repo (bean/->clj data)]
-                                     (prn "received persistGraphDone" repo)
-                                     (when (= graph repo)
+                                 #(let [repo (bean/->clj %)]
+                                    (prn "received persistGraphDone" repo)
+                                    (when (= graph repo)
                                        ;; js/window.apis.once doesn't work
-                                       (js/window.apis.removeAllListeners "persistGraphDone")
-                                       (resolve repo)))))
+                                      (js/window.apis.removeAllListeners "persistGraphDone")
+                                      (resolve repo))))
               (ipc/ipc "persistGraph" graph))))