瀏覽代碼

fix: disable editing when the graph's directory is renamed or deleted

related to #5549
Tienson Qin 3 年之前
父節點
當前提交
781062a4ce

+ 41 - 22
src/electron/electron/fs_watcher.cljs

@@ -4,7 +4,8 @@
             ["chokidar" :as watcher]
             [electron.utils :as utils]
             ["electron" :refer [app]]
-            [electron.window :as window]))
+            [electron.window :as window]
+            ["path" :as path]))
 
 ;; TODO: explore different solutions for different platforms
 ;; 1. https://github.com/Axosoft/nsfw
@@ -29,10 +30,13 @@
 
 (defn- publish-file-event!
   [dir path event]
-  (let [content (when (and (not= event "unlink")
+  (let [dir-path? (= dir path)
+        content (when (and (not= event "unlink")
+                           (not dir-path?)
                            (utils/should-read-content? path))
                   (utils/read-file path))
-        stat (when (not= event "unlink")
+        stat (when (and (not= event "unlink")
+                        (not dir-path?))
                (fs/statSync path))]
     (send-file-watcher! dir event {:dir (utils/fix-win-path! dir)
                                    :path (utils/fix-win-path! path)
@@ -44,38 +48,53 @@
   [_win dir]
   (when (and (fs/existsSync dir)
              (not (get @*file-watcher dir)))
-    (let [watcher (.watch watcher dir
-                          (clj->js
-                           {:ignored (fn [path]
-                                       (utils/ignored-path? dir path))
-                            :ignoreInitial false
-                            :ignorePermissionErrors true
-                            :interval polling-interval
-                            :binaryInterval polling-interval
-                            :persistent true
-                            :disableGlobbing true
-                            :usePolling false
-                            :awaitWriteFinish true}))
-          watcher-del-f #(.close watcher)]
-      (swap! *file-watcher assoc dir [watcher watcher-del-f])
+    (let [watcher-opts (clj->js
+                        {:ignored (fn [path]
+                                    (utils/ignored-path? dir path))
+                         :ignoreInitial false
+                         :ignorePermissionErrors true
+                         :interval polling-interval
+                         :binaryInterval polling-interval
+                         :persistent true
+                         :disableGlobbing true
+                         :usePolling false
+                         :awaitWriteFinish true})
+          dir-watcher (.watch watcher dir watcher-opts)
+          watcher-del-f #(.close dir-watcher)
+          parent-dir (path/join dir "..")
+          parent-watcher (.watch watcher parent-dir watcher-opts)
+          parent-watcher-del-f #(.close parent-watcher)]
+      (swap! *file-watcher assoc dir
+             [dir-watcher watcher-del-f]
+             [parent-watcher parent-watcher-del-f])
       ;; TODO: batch sender
-      (.on watcher "add"
+      (.on parent-watcher "unlinkDir"
+           (fn [path]
+             (when (= dir path)
+               (publish-file-event! dir dir "unlinkDir"))))
+      (.on parent-watcher "addDir"
+           (fn [path]
+             (when (= dir path)
+               (publish-file-event! dir dir "addDir"))))
+      (.on dir-watcher "add"
            (fn [path]
              (publish-file-event! dir path "add")))
-      (.on watcher "change"
+      (.on dir-watcher "change"
            (fn [path]
              (publish-file-event! dir path "change")))
-      (.on watcher "unlink"
+      (.on dir-watcher "unlink"
            (fn [path]
              (publish-file-event! dir path "unlink")))
-      (.on watcher "error"
+      (.on dir-watcher "error"
            (fn [path]
              (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)
+      (.on app "quit" (fn []
+                        (watcher-del-f)
+                        (parent-watcher-del-f)))
 
       true)))
 

+ 15 - 1
src/main/frontend/fs/watcher_handler.cljs

@@ -48,10 +48,24 @@
           pages-metadata-path (config/get-pages-metadata-path)
           {:keys [mtime]} stat
           db-content (or (db/get-file repo path) "")]
-      (when (and (or content (= type "unlink"))
+      (when (and (or content (contains? #{"unlink" "unlinkDir" "addDir"} type))
                  (not (encrypt/content-encrypted? content))
                  (not (:encryption/graph-parsing? @state/state)))
         (cond
+          (and (= "unlinkDir" type) dir)
+          (do
+            (state/pub-event! [:notification/show
+                               {:content (str "The directory " dir " has been renamed or deleted, the editor will be disabled for this graph, you can unlink the graph.")
+                                :status :error
+                                :clear? false}])
+            (state/update-state! :file/unlinked-dirs (fn [dirs] (conj dirs dir))))
+
+          (= "addDir" type)
+          (state/update-state! :file/unlinked-dirs (fn [dirs] (disj dirs dir)))
+
+          (contains? (:file/unlinked-dirs @state/state) dir)
+          nil
+
           (and (= "add" type)
                (not= (string/trim content) (string/trim db-content))
                (not= path pages-metadata-path))

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

@@ -54,7 +54,9 @@
   (let [f (fn []
             #_:clj-kondo/ignore
             (let [repo (state/get-current-repo)]
-              (when-not (state/nfs-refreshing?)
+              (when (and (not (state/nfs-refreshing?))
+                         (not (contains? (:file/unlinked-dirs @state/state)
+                                         (config/get-repo-dir repo))))
                 ;; Don't create the journal file until user writes something
                 (page-handler/create-today-journal!))))]
     (f)

+ 3 - 1
src/main/frontend/modules/outliner/datascript.cljc

@@ -54,7 +54,9 @@
                                       :block/title :block/body :block/level :block/container :db/other-tx)
                               m)) txs)]
        (when (and (seq txs)
-                  (not (:skip-transact? opts)))
+                  (not (:skip-transact? opts))
+                  (not (contains? (:file/unlinked-dirs @state/state)
+                                  (config/get-repo-dir (state/get-current-repo)))))
          ;; (frontend.util/pprint txs)
          (try
            (let [repo (get opts :repo (state/get-current-repo))

+ 1 - 0
src/main/frontend/state.cljs

@@ -27,6 +27,7 @@
      :system/events                         (async/chan 100)
      :db/batch-txs                          (async/chan 100)
      :file/writes                           (async/chan 100)
+     :file/unlinked-dirs                    #{}
      :reactive/custom-queries               (async/chan 100)
      :notification/show?                    false
      :notification/content                  nil