Forráskód Böngészése

enhance: ask other windows to persist db

Junyi Du 3 éve
szülő
commit
7bdbe82920

+ 46 - 29
src/electron/electron/handler.cljs

@@ -31,15 +31,15 @@
 (defn- readdir
   [dir]
   (->> (tree-seq
-         (fn [^js f]
-           (.isDirectory (fs/statSync f) ()))
-         (fn [d]
-           (let [files (fs/readdirSync d (clj->js {:withFileTypes true}))]
-             (->> files
-                  (remove #(.isSymbolicLink ^js %))
-                  (remove #(string/starts-with? (.-name ^js %) "."))
-                  (map #(.join path d (.-name %))))))
-         dir)
+        (fn [^js f]
+          (.isDirectory (fs/statSync f) ()))
+        (fn [d]
+          (let [files (fs/readdirSync d (clj->js {:withFileTypes true}))]
+            (->> files
+                 (remove #(.isSymbolicLink ^js %))
+                 (remove #(string/starts-with? (.-name ^js %) "."))
+                 (map #(.join path d (.-name %))))))
+        dir)
        (doall)
        (vec)))
 
@@ -50,8 +50,8 @@
   (if (plugin/dotdir-file? path)
     (fs/unlinkSync path)
     (let [file-name   (-> (string/replace path (str repo "/") "")
-                        (string/replace "/" "_")
-                        (string/replace "\\" "_"))
+                          (string/replace "/" "_")
+                          (string/replace "\\" "_"))
           recycle-dir (str repo "/logseq/.recycle")
           _           (fs-extra/ensureDirSync recycle-dir)
           new-path    (str recycle-dir "/" file-name)]
@@ -147,7 +147,7 @@
   (fs/statSync path))
 
 (defonce allowed-formats
-         #{:org :markdown :md :edn :json :js :css :excalidraw})
+  #{:org :markdown :md :edn :json :js :css :excalidraw})
 
 (defn get-ext
   [p]
@@ -158,16 +158,16 @@
 (defn- get-files
   [path]
   (let [result (->>
-                 (readdir path)
-                 (remove (partial utils/ignored-path? path))
-                 (filter #(contains? allowed-formats (get-ext %)))
-                 (map (fn [path]
-                        (let [stat (fs/statSync path)]
-                          (when-not (.isDirectory stat)
-                            {:path    (utils/fix-win-path! path)
-                             :content (utils/read-file path)
-                             :stat    stat}))))
-                 (remove nil?))]
+                (readdir path)
+                (remove (partial utils/ignored-path? path))
+                (filter #(contains? allowed-formats (get-ext %)))
+                (map (fn [path]
+                       (let [stat (fs/statSync path)]
+                         (when-not (.isDirectory stat)
+                           {:path    (utils/fix-win-path! path)
+                            :content (utils/read-file path)
+                            :stat    stat}))))
+                (remove nil?))]
     (vec (cons {:path (utils/fix-win-path! path)} result))))
 
 (defn open-dir-dialog []
@@ -192,12 +192,12 @@
         (string/replace "/" "++")
         (string/replace ":" "+3A+"))))
 
- (defn- graph-name->path
-   [graph-name]
-   (when graph-name
-     (-> graph-name
-         (string/replace "+3A+" ":")
-         (string/replace "++" "/"))))
+(defn- graph-name->path
+  [graph-name]
+  (when graph-name
+    (-> graph-name
+        (string/replace "+3A+" ":")
+        (string/replace "++" "/"))))
 
 (defn- get-graphs-dir
   []
@@ -399,6 +399,23 @@
 (defmethod handle :default [args]
   (println "Error: no ipc handler for: " (bean/->js args)))
 
+(defmethod handle :persistGraph [^js win [_ graph]]
+  ;; call a window holds the specific graph to persist
+  (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)]
+    (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
+
+(defmethod handle :persistGraphDone [^js _win [_ graph]]
+  ;; when graph is persisted, broadcast it to all windows
+  (let [windows (win/get-all-windows)]
+    (doseq [window windows]
+      (utils/send-to-renderer window "persistGraphDone" graph))))
+
 (defn set-ipc-handler! [window]
   (let [main-channel "main"]
     (.handle ipcMain main-channel
@@ -410,6 +427,6 @@
                    (when-not (contains? #{"mkdir" "stat"} (nth args-js 0))
                      (println "IPC error: " {:event event
                                              :args args-js}
-                             e))
+                              e))
                    e))))
     #(.removeHandler ipcMain main-channel)))

+ 26 - 6
src/main/electron/listener.cljs

@@ -1,5 +1,6 @@
 (ns electron.listener
   (:require [frontend.state :as state]
+            [frontend.context.i18n :refer [t]]
             [frontend.handler.route :as route-handler]
             [frontend.handler.ui :as ui-handler]
             [cljs-bean.core :as bean]
@@ -13,11 +14,13 @@
 
 (defn persist-dbs!
   []
-  (repo-handler/persist-all-dbs! {:before     #(notification/show!
-                                                (ui/loading "Logseq is saving the graphs to your local file system, please wait for several seconds.")
-                                                :warning)
-                                  :on-success #(ipc/ipc "persistent-dbs-saved")
-                                  :on-error   #(ipc/ipc "persistent-dbs-error")}))
+  ;; only persist current db!
+  ;; TODO rename to persist-db
+  (repo-handler/persist-db! {:before     #(notification/show!
+                                           (ui/loading (t :graph/persist))
+                                           :warning)
+                             :on-success #(ipc/ipc "persistent-dbs-saved")
+                             :on-error   #(ipc/ipc "persistent-dbs-error")}))
 
 (defn listen-persistent-dbs!
   []
@@ -69,7 +72,24 @@
                              tx-data (db/string->db (:data tx-data))]
                          (when-let [conn (db/get-conn graph false)]
                            (d/transact! conn tx-data {:dbsync? true}))
-                         (ui-handler/re-render-root!)))))
+                         (ui-handler/re-render-root!))))
+
+  (js/window.apis.on "persistGraph"
+                     ;; electron is requesting window for persisting a graph in it's db
+                     (fn [data]
+                       (let [repo (bean/->clj data)
+                             before-f #(notification/show!
+                                        (ui/loading (t :graph/persist))
+                                        :warning)
+                             after-f #(ipc/ipc "persistGraphDone" repo)
+                             error-f (fn []
+                                       (after-f)
+                                       (notification/show! (t :graph/persist-error)
+                                                           :error))
+                             handlers {:before     before-f
+                                       :on-success after-f
+                                       :on-error   error-f}]
+                         (repo-handler/persist-db! repo handlers)))))
 
 (defn listen!
   []

+ 4 - 4
src/main/frontend/dicts.cljs

@@ -305,8 +305,8 @@
         :new-graph "Add new graph"
         :graph "Graph"
         :graph-view "View graph"
-        :graph/open-new-window "Logseq is syncing internal status before opening new window, please wait for several seconds."
-        :graph/open-new-window-error "Internal status sync failed. Unable to open new window."
+        :graph/persist "Logseq is syncing internal status, please wait for several seconds."
+        :graph/persist-error "Internal status sync failed."
         :graph/save "Saving..."
         :graph/save-success "Saved successfully"
         :graph/save-error "Save failed"
@@ -1204,8 +1204,8 @@
            :new-page "新页面"
            :new-file "新文件"
            :graph "图谱"
-           :graph/open-new-window "打开新窗口前,Logseq正在同步内部状态,请等待片刻。"
-           :graph/open-new-window-error "内部状态同步失败。无法打开新窗口。"
+           :graph/persist "打开新窗口前,Logseq正在同步内部状态,请等待片刻。"
+           :graph/persist-error "内部状态同步失败。无法打开新窗口。"
            :graph/save "保存中……"
            :graph/save-success "保存成功"
            :graph/save-error "保存失败"

+ 39 - 30
src/main/frontend/handler/events.cljs

@@ -54,8 +54,8 @@
       "Please make sure that you've installed the logseq app for the repo %s on GitHub. "
       repo-url)
      (ui/button
-       "Install Logseq on GitHub"
-       :href (str "https://github.com/apps/" config/github-app-name "/installations/new"))]]
+      "Install Logseq on GitHub"
+      :href (str "https://github.com/apps/" config/github-app-name "/installations/new"))]]
    :error
    false))
 
@@ -93,9 +93,18 @@
   (srs/update-cards-due-count!)
   (state/pub-event! [:graph/ready graph]))
 
+(defn- graph-switch-on-persisted [graph]
+  (p/let [;; save current db
+          _ (repo-handler/persist-db!)
+          ;; ask other windows to persist the targeting db
+          _ (repo-handler/persist-otherwindow-db! graph)]
+    (graph-switch graph)))
+
 (defmethod handle :graph/switch [[_ graph]]
   (if (outliner-file/writes-finished?)
-    (graph-switch graph)
+    (if (util/electron?)
+      (graph-switch-on-persisted graph)
+      (graph-switch graph))
     (notification/show!
      "Please wait seconds until all changes are saved for the current graph."
      :warning)))
@@ -124,19 +133,19 @@
 (defn ask-permission
   [repo]
   (when
-      (and (not (util/electron?))
-           (not (mobile-util/is-native-platform?)))
+   (and (not (util/electron?))
+        (not (mobile-util/is-native-platform?)))
     (fn [close-fn]
       [:div
        [:p
         "Grant native filesystem permission for directory: "
         [:b (config/get-local-dir repo)]]
        (ui/button
-         "Grant"
-         :class "ui__modal-enter"
-         :on-click (fn []
-                     (nfs/check-directory-permission! repo)
-                     (close-fn)))])))
+        "Grant"
+        :class "ui__modal-enter"
+        :on-click (fn []
+                    (nfs/check-directory-permission! repo)
+                    (close-fn)))])))
 
 (defmethod handle :modal/nfs-ask-permission []
   (when-let [repo (get-local-repo)]
@@ -244,9 +253,9 @@
 (defmethod handle :go/plugins-settings [[_ pid nav? title]]
   (if pid
     (do
-     (state/set-state! :plugin/focused-settings pid)
-     (state/set-state! :plugin/navs-settings? (not (false? nav?)))
-     (plugin/open-focused-settings-modal! title))
+      (state/set-state! :plugin/focused-settings pid)
+      (state/set-state! :plugin/navs-settings? (not (false? nav?)))
+      (plugin/open-focused-settings-modal! title))
     (state/close-sub-modal! "ls-focused-settings-modal")))
 
 
@@ -280,24 +289,24 @@
     (when-let [coming (and (not downloading?)
                            (get-in @state/state [:plugin/updates-coming id]))]
       (notification/show!
-        (str "Checked: " (:title coming))
-        :success))
+       (str "Checked: " (:title coming))
+       :success))
 
     (if (and updated? downloading?)
       ;; try to start consume downloading item
       (if-let [n (state/get-next-selected-coming-update)]
         (plugin-handler/check-or-update-marketplace-plugin
-          (assoc n :only-check false :error-code nil)
-          (fn [^js e] (js/console.error "[Download Err]" n e)))
+         (assoc n :only-check false :error-code nil)
+         (fn [^js e] (js/console.error "[Download Err]" n e)))
         (plugin-handler/close-updates-downloading))
 
       ;; try to start consume pending item
       (if-let [n (second (first (:plugin/updates-pending @state/state)))]
         (plugin-handler/check-or-update-marketplace-plugin
-          (assoc n :only-check true :error-code nil)
-          (fn [^js e]
-            (notification/show! (.toString e) :error)
-            (js/console.error "[Check Err]" n e)))
+         (assoc n :only-check true :error-code nil)
+         (fn [^js e]
+           (notification/show! (.toString e) :error)
+           (js/console.error "[Check Err]" n e)))
         ;; try to open waiting updates list
         (when (and pending? (seq (state/all-available-coming-updates)))
           (plugin/open-waiting-updates-modal!))))))
@@ -323,15 +332,15 @@
 
 (defmethod handle :graph/open-new-window [[_ repo]]
    ;; persistent current db, then open new window
-   (let [cur-repo (state/get-current-repo)]
-     (repo-handler/persist-db! cur-repo 
-                               {:before     #(notification/show!
-                                              (ui/loading (t :graph/open-new-window))
-                                              :warning)
-                                :on-success #(ui-handler/open-new-window! _ repo)
-                                :on-error   #(notification/show!
-                                              (t :graph/open-new-window-error)
-                                              :error)})))
+  (let [cur-repo (state/get-current-repo)]
+    (repo-handler/persist-db! cur-repo
+                              {:before     #(notification/show!
+                                             (ui/loading (t :graph/persist))
+                                             :warning)
+                               :on-success #(ui-handler/open-new-window! _ repo)
+                               :on-error   #(notification/show!
+                                             (t :graph/persist-error)
+                                             :error)})))
 
 (defn run!
   []

+ 35 - 10
src/main/frontend/handler/repo.cljs

@@ -672,13 +672,38 @@
               (on-error)))))
 
 (defn persist-db!
-  [repo {:keys [before on-success on-error]}]
-  (->
-   (p/do!
-    (before)
-    (metadata-handler/set-pages-metadata! repo)
-    (db/persist! repo)
-    (on-success))
-   (p/catch (fn [error]
-              (js/console.error error)
-              (on-error)))))
+  ([]
+   (persist-db! {}))
+  ([handlers]
+   (persist-db! (state/get-current-repo) handlers))
+  ([repo {:keys [before on-success on-error]}]
+   (->
+    (p/do!
+     (when before
+       (before))
+     (metadata-handler/set-pages-metadata! repo)
+     (db/persist! repo)
+     (when on-success
+       (on-success)))
+    (p/catch (fn [error]
+               (js/console.error error)
+               (when on-error
+                 (on-error)))))))
+
+(defn persist-otherwindow-db!
+  "Call backend to handle persisting a specific db on other window
+     step 1. [In HERE]  a window         --persistGraph----->   electron  
+     step 2.            electron         --persistGraph----->   window holds the graph  
+     step 3.            window w/ graph  --persistGraphDone->   electron  
+     step 4. [In HERE]  electron         --persistGraphDone->   all windows"
+  [graph]
+  (p/create (fn [resolve _]
+              (js/window.apis.on "persistGraphDone"
+                                 (fn [data]
+                                   (let [repo (bean/->clj data)]
+                                     (prn "received persistGraphDone" repo)
+                                     (when (= graph repo)
+                                       ;; js/window.apis.once doesn't work
+                                       (js/window.apis.removeAllListeners "persistGraphDone")
+                                       (resolve repo)))))
+              (ipc/ipc "persistGraph" graph))))