Sfoglia il codice sorgente

refactor: diff instead a alerting when a file has been modified

Tienson Qin 4 anni fa
parent
commit
6f2a86e79d

+ 5 - 0
resources/css/common.css

@@ -181,6 +181,11 @@ textarea {
   font-weight: inherit;
   letter-spacing: inherit;
   text-size-adjust: 100%;
+  background: var(--ls-primary-background-color);
+}
+
+.dark-theme textarea {
+  background: var(--ls-tertiary-background-color);
 }
 
 ul {

+ 75 - 0
src/main/frontend/components/diff.cljs

@@ -230,3 +230,78 @@
 
        :else
        [:div "No diffs"])]))
+
+(rum/defcs local-file < rum/reactive
+  [state repo path disk-content local-content]
+  (let [content disk-content
+        edit? (util/react *edit?)]
+    [:div.cp__diff-file
+     [:div.cp__diff-file-header
+      [:span.cp__diff-file-header-content {:style {:word-break "break-word"}}
+       path]]
+     (when (not= content local-content)
+       (let [local-content (or local-content "")
+             content (or content "")
+             diff (medley/indexed (diff/diff local-content content))
+             diff? (some (fn [[_idx {:keys [added removed]}]]
+                           (or added removed))
+                         diff)
+             diff-cp [:div.overflow-y-scroll
+                      [:div {:style {:max-height "65vh"}}
+                       (diff-cp diff)]]]
+         [:div.pre-line-white-space.p-2.overflow-y-hidden
+          (if edit?
+            [:div.grid.grid-cols-2.gap-1
+             diff-cp
+             (ui/textarea
+              {:default-value local-content
+               :auto-focus true
+               :style {:border "1px solid"}
+               :on-change (fn [e]
+                            (reset! *edit-content (util/evalue e)))})]
+            diff-cp)
+
+          (cond
+            edit?
+            [:div.mt-2
+             (ui/button "Save"
+               :on-click
+               (fn []
+                 (reset! *edit? false)
+                 (let [new-content @*edit-content]
+                   (file/alter-file repo path new-content
+                                    {:re-render-root? true
+                                     :skip-compare? true})
+                   (state/close-modal!))))]
+
+            diff?
+            [:div.mt-2
+             (ui/button "Use latest changes from the disk"
+               :on-click
+               (fn []
+                 (file/alter-file repo path content
+                                  {:re-render-root? true
+                                   :skip-compare? true})
+                 (state/close-modal!))
+               :background "green")
+
+             [:span.pl-2.pr-2 "or"]
+
+             (ui/button "Keep local changes in Logseq"
+               :on-click
+               (fn []
+                 (file/alter-file repo path local-content
+                                  {:re-render-root? true
+                                   :skip-compare? true})
+                 (state/close-modal!))
+               :background "pink")
+
+             [:span.pl-2.pr-2 "or"]
+
+             (ui/button "Edit"
+               :on-click
+               (fn []
+                 (reset! *edit? true)))]
+
+            :else
+            nil)]))]))

+ 2 - 2
src/main/frontend/extensions/pdf/assets.cljs

@@ -70,7 +70,7 @@
     (let [repo-cur (state/get-current-repo)
           repo-dir (config/get-repo-dir repo-cur)
           data (pr-str {:highlights highlights})]
-      (fs/write-file! repo-cur repo-dir hls-file data {:skip-mtime? true}))))
+      (fs/write-file! repo-cur repo-dir hls-file data {:skip-compare? true}))))
 
 (defn resolve-hls-data-by-key$
   [target-key]
@@ -115,7 +115,7 @@
                                    new-fpath (str fdir "/" fname "_" fstamp ".png")
                                    old-fpath (and old-fstamp (str fdir "/" fname "_" old-fstamp ".png"))
                                    _ (and old-fpath (apply fs/rename! repo-cur (map #(util/node-path.join repo-dir %) [old-fpath new-fpath])))
-                                   _ (fs/write-file! repo-cur repo-dir new-fpath png {:skip-mtime? true})]
+                                   _ (fs/write-file! repo-cur repo-dir new-fpath png {:skip-compare? true})]
 
                              (js/console.timeEnd :write-area-image))
 

+ 23 - 24
src/main/frontend/fs/nfs.cljs

@@ -10,6 +10,7 @@
             [frontend.config :as config]
             [frontend.state :as state]
             [frontend.handler.notification :as notification]
+            [frontend.encrypt :as encrypt]
             ["/frontend/utils" :as utils]))
 
 ;; We need to cache the file handles in the memory so that
@@ -54,6 +55,14 @@
       (when handle
         (verify-permission repo handle true)))))
 
+(defn- contents-matched?
+  [disk-content db-content]
+  (when (and (string? disk-content) (string? db-content))
+    (if (encrypt/encrypted-db? (state/get-current-repo))
+      (p/let [decrypted-content (encrypt/decrypt disk-content)]
+        (= (string/trim decrypted-content) (string/trim db-content)))
+      (p/resolved (= (string/trim disk-content) (string/trim db-content))))))
+
 (defrecord Nfs []
   protocol/Fs
   (mkdir! [this dir]
@@ -155,35 +164,25 @@
           (if file-handle
             (-> (p/let [local-file (.getFile file-handle)
                         local-content (.text local-file)
-                        local-last-modified-at (gobj/get local-file "lastModified")
-                        current-time (util/time-ms)
-                        new? (> current-time local-last-modified-at)
-                        new-created? (nil? last-modified-at)
-                        not-changed? (= last-modified-at local-last-modified-at)
-                        format (-> (util/get-file-ext path)
-                                   (config/get-file-format))
                         pending-writes (state/get-write-chan-length)
-                        draw? (and path (string/ends-with? path ".excalidraw"))
-                        config? (and path (string/ends-with? path "/config.edn"))]
-                  (p/let [_ (verify-permission repo file-handle true)
-                          _ (utils/writeFile file-handle content)
-                          file (.getFile file-handle)]
-                    (if (and local-content new?
-                             (or
-                              draw?
-                              config?
-                             ;; Writing not finished
-                              (> pending-writes 0)
-                             ;; not changed by other editors
-                              not-changed?
-                              new-created?))
+                        ext (string/lower-case (util/get-file-ext path))
+                        db-content (db/get-file repo path)]
+                  (when local-content
+                    (if (and
+                         (not (string/blank? db-content))
+                         (not (:skip-compare? opts))
+                         (not (contents-matched? local-content (or db-content "")))
+                         (not (contains? #{"excalidraw" "edn"} ext)))
+                      (state/pub-event! [:file/not-matched-from-disk path local-content content])
                       (p/let [_ (verify-permission repo file-handle true)
                               _ (utils/writeFile file-handle content)
                               file (.getFile file-handle)]
                         (when file
-                          (nfs-saved-handler repo path file)))
-                      (js/alert (str "The file has been modified on your local disk! File path: " path
-                                     ", please save your changes and click the refresh button to reload it.")))))
+                          (p/let [content (if (encrypt/encrypted-db? (state/get-current-repo))
+                                            (encrypt/decrypt content)
+                                            content)]
+                            (db/set-file-content! repo path content))
+                          (nfs-saved-handler repo path file))))))
                 (p/catch (fn [e]
                            (js/console.error e))))
             ;; create file handle

+ 3 - 15
src/main/frontend/fs/node.cljs

@@ -36,8 +36,8 @@
       (p/resolved (= (string/trim disk-content) (string/trim db-content))))))
 
 (defn- write-file-impl!
-  [this repo dir path content {:keys [ok-handler error-handler skip-mtime?] :as opts} stat]
-  (if skip-mtime?
+  [this repo dir path content {:keys [ok-handler error-handler skip-compare?] :as opts} stat]
+  (if skip-compare?
     (p/catch
         (p/let [result (ipc/ipc "writeFile" path content)]
           (when ok-handler
@@ -56,22 +56,10 @@
             db-content (or (db/get-file repo path) "")
             contents-matched? (contents-matched? disk-content db-content)]
       (cond
-        ;; (and (not page-empty?) (nil? disk-content) )
-        ;; (notification/show!
-        ;;  (str "The file has been renamed or deleted on your local disk! File path: " path
-        ;;       ", please save your changes and click the refresh button to reload it.")
-        ;;  :error
-        ;;  false)
-
         (and
          (not contents-matched?)
-         ;; FIXME:
          (not (contains? #{"excalidraw" "edn"} ext)))
-        (notification/show!
-         (str "The file has been modified on your local disk! File path: " path
-              ", please save your changes and click the refresh button to reload it.")
-         :warning
-         false)
+        (state/pub-event! [:file/not-matched-from-disk path disk-content content])
 
         :else
         (->

+ 6 - 0
src/main/frontend/handler/events.cljs

@@ -13,6 +13,7 @@
             [frontend.components.encryption :as encryption]
             [frontend.components.shell :as shell]
             [frontend.components.git :as git-component]
+            [frontend.components.diff :as diff]
             [frontend.fs.nfs :as nfs]
             [frontend.db.conn :as conn]
             [frontend.extensions.srs :as srs]
@@ -152,6 +153,11 @@
 (defmethod handle :page/create-today-journal [[_ repo]]
   (page-handler/create-today-journal!))
 
+(defmethod handle :file/not-matched-from-disk [[_ path disk-content db-content]]
+  (state/clear-edit!)
+  (when-let [repo (state/get-current-repo)]
+    (state/set-modal! #(diff/local-file repo path disk-content db-content))))
+
 (defmethod handle :after-db-restore [[_ repos]]
   (mapv (fn [{url :url} repo]
           ;; compare :ast/version

+ 6 - 3
src/main/frontend/handler/file.cljs

@@ -158,17 +158,20 @@
 
 ;; TODO: Remove this function in favor of `alter-files`
 (defn alter-file
-  [repo path content {:keys [reset? re-render-root? add-history? update-status? from-disk?]
+  [repo path content {:keys [reset? re-render-root? add-history? update-status? from-disk? skip-compare?]
                       :or {reset? true
                            re-render-root? false
                            add-history? true
                            update-status? false
-                           from-disk? false}}]
+                           from-disk? false
+                           skip-compare? false}}]
   (let [edit-block (state/get-edit-block)
         original-content (db/get-file-no-sub repo path)
         write-file! (if from-disk?
                       #(p/resolved nil)
-                      #(fs/write-file! repo (config/get-repo-dir repo) path content (when original-content {:old-content original-content})))]
+                      #(fs/write-file! repo (config/get-repo-dir repo) path content
+                                       (assoc (when original-content {:old-content original-content})
+                                              :skip-compare? skip-compare?)))]
     (p/let [_ (if reset?
                 (do
                   (when-let [page-id (db/get-file-page-id path)]

+ 4 - 4
src/main/logseq/api.cljs

@@ -94,7 +94,7 @@
   (fn [path ^js data]
     (let [repo ""
           path (util/node-path.join path "package.json")]
-      (fs/write-file! repo "" path (js/JSON.stringify data nil 2) {:skip-mtime? true}))))
+      (fs/write-file! repo "" path (js/JSON.stringify data nil 2) {:skip-compare? true}))))
 
 (defn ^:private write_dotdir_file
   [file content sub-root]
@@ -109,7 +109,7 @@
           user-path-root (util/node-path.dirname user-path)
           exist? (fs/file-exists? user-path-root "")
           _ (when-not exist? (fs/mkdir-recur! user-path-root))
-          _ (fs/write-file! repo "" user-path content {:skip-mtime? true})]
+          _ (fs/write-file! repo "" user-path content {:skip-compare? true})]
     user-path))
 
 (defn ^:private read_dotdir_file
@@ -191,7 +191,7 @@
       (p/let [repo ""
               path (plugin-handler/get-ls-dotdir-root)
               path (util/node-path.join path "preferences.json")]
-        (fs/write-file! repo "" path (js/JSON.stringify data nil 2) {:skip-mtime? true})))))
+        (fs/write-file! repo "" path (js/JSON.stringify data nil 2) {:skip-compare? true})))))
 
 (def ^:export load_plugin_user_settings
   (fn [key]
@@ -209,7 +209,7 @@
     (p/let [repo ""
             path (plugin-handler/get-ls-dotdir-root)
             path (util/node-path.join path "settings" (str key ".json"))]
-      (fs/write-file! repo "" path (js/JSON.stringify data nil 2) {:skip-mtime? true}))))
+      (fs/write-file! repo "" path (js/JSON.stringify data nil 2) {:skip-compare? true}))))
 
 (def ^:export register_plugin_slash_command
   (fn [pid ^js cmd-actions]