瀏覽代碼

fix: add page history (using git log and git show)

Tienson Qin 4 年之前
父節點
當前提交
9c3b11c216

+ 19 - 25
src/electron/electron/git.cljs

@@ -30,7 +30,8 @@
           (let [result (gobj/get result "stdout")]
           (let [result (gobj/get result "stdout")]
             (p/resolved result))
             (p/resolved result))
           (let [error (gobj/get result "stderr")]
           (let [error (gobj/get result "stderr")]
-            (js/console.error error)
+            (when-not (string/blank? error)
+              (js/console.error error))
             (p/rejected error)))))))
             (p/rejected error)))))))
 
 
 (defn git-dir-exists?
 (defn git-dir-exists?
@@ -57,6 +58,8 @@
   []
   []
   (run-git! #js ["add" "./*"]))
   (run-git! #js ["add" "./*"]))
 
 
+;; git log -100 --oneline -p ~/Desktop/org/pages/contents.org
+
 (defn commit!
 (defn commit!
   [message]
   [message]
   (run-git! #js ["commit" "-m" message]))
   (run-git! #js ["commit" "-m" message]))
@@ -100,33 +103,24 @@
          (remove string/blank?))))
          (remove string/blank?))))
 
 
 (defn raw!
 (defn raw!
-  [args & {:keys [ok-handler error-handler]}]
+  [args]
   (let [args (if (string? args)
   (let [args (if (string? args)
                (split-args args)
                (split-args args)
                args)
                args)
-        ok-handler (if ok-handler
-                     ok-handler
-                     (fn [result]
-                       (let [result (if (string/blank? result)
-                                      (str (first args) " successfully!")
-                                      result)]
-                         (utils/send-to-renderer "notification" {:type "success"
-                                                                 :payload result}))))
-        error-handler (if error-handler
-                        error-handler
-                        (fn [error]
-                          ;; TODO: why this happen?
-                          (when-not (string/blank? error)
-                            (let [error (str (first args) " error: " error)]
-                              (utils/send-to-renderer "notification" {:type "error"
-                                                                      :payload error})))))]
-    (p/let [_ (when (= (first args) "commit")
-                (add-all!))]
-      (->
-       (p/let [result (run-git! (clj->js args))]
-         (when ok-handler
-           (ok-handler result)))
-       (p/catch error-handler)))))
+        ok-handler (fn [result]
+                     (p/resolved result))
+        error-handler (fn [error]
+                        ;; TODO: why this happen?
+                        (when-not (string/blank? error)
+                          (let [error (str (first args) " error: " error)]
+                            (utils/send-to-renderer "notification" {:type "error"
+                                                                    :payload error}))))]
+    (->
+     (p/let [_ (when (= (first args) "commit")
+                 (add-all!))
+             result (run-git! (clj->js args))]
+       (p/resolved result))
+     (p/catch error-handler))))
 
 
 (defn auto-commit-current-graph!
 (defn auto-commit-current-graph!
   []
   []

+ 8 - 1
src/main/frontend/components/page.cljs

@@ -45,7 +45,8 @@
             [frontend.text :as text]
             [frontend.text :as text]
             [frontend.modules.shortcut.core :as shortcut]
             [frontend.modules.shortcut.core :as shortcut]
             [frontend.handler.block :as block-handler]
             [frontend.handler.block :as block-handler]
-            [cljs-bean.core :as bean]))
+            [cljs-bean.core :as bean]
+            [frontend.handler.shell :as shell]))
 
 
 (defn- get-page-name
 (defn- get-page-name
   [state]
   [state]
@@ -320,6 +321,12 @@
                                       (if public? false true))
                                       (if public? false true))
                                      (state/close-modal!))}})
                                      (state/close-modal!))}})
 
 
+                      (when (util/electron?)
+                        {:title   (t :page/version-history)
+                         :options {:on-click
+                                   (fn []
+                                     (shell/get-file-latest-git-log page 100))}})
+
                       (when plugin-handler/lsp-enabled?
                       (when plugin-handler/lsp-enabled?
                         (for [[_ {:keys [key label] :as cmd} action pid] (state/get-plugins-commands-with-type :page-menu-item)]
                         (for [[_ {:keys [key label] :as cmd} action pid] (state/get-plugins-commands-with-type :page-menu-item)]
                           {:title label
                           {:title label

+ 2 - 0
src/main/frontend/dicts.cljs

@@ -148,6 +148,7 @@
         :page/open-with-default-app "Open with default app"
         :page/open-with-default-app "Open with default app"
         :page/action-publish "Publish"
         :page/action-publish "Publish"
         :page/make-public "Make it public for publishing"
         :page/make-public "Make it public for publishing"
+        :page/version-history "Check page history"
         :page/make-private "Make it private"
         :page/make-private "Make it private"
         :page/delete "Delete page"
         :page/delete "Delete page"
         :page/publish "Publish this page on Logseq"
         :page/publish "Publish this page on Logseq"
@@ -841,6 +842,7 @@
            :page/open-with-default-app "用默认应用打开文件"
            :page/open-with-default-app "用默认应用打开文件"
            :page/action-publish "发布"
            :page/action-publish "发布"
            :page/make-public "导出 HTML 时发布本页面"
            :page/make-public "导出 HTML 时发布本页面"
+           :page/version-history "查看页面历史记录"
            :page/make-private "导出 HTML 时取消发布本页面"
            :page/make-private "导出 HTML 时取消发布本页面"
            :page/delete "删除本页"
            :page/delete "删除本页"
            :page/publish "将本页发布至 Logseq"
            :page/publish "将本页发布至 Logseq"

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

@@ -135,6 +135,13 @@
 (defmethod handle :modal/show-cards [_]
 (defmethod handle :modal/show-cards [_]
   (state/set-modal! srs/global-cards))
   (state/set-modal! srs/global-cards))
 
 
+(rum/defc modal-output
+  [content]
+  content)
+
+(defmethod handle :modal/show [[_ content]]
+  (state/set-modal! #(modal-output content)))
+
 (defmethod handle :page/title-property-changed [[_ old-title new-title]]
 (defmethod handle :page/title-property-changed [[_ old-title new-title]]
   (page-handler/rename! old-title new-title))
   (page-handler/rename! old-title new-title))
 
 

+ 54 - 3
src/main/frontend/handler/shell.cljs

@@ -2,16 +2,32 @@
   (:require [electron.ipc :as ipc]
   (:require [electron.ipc :as ipc]
             [clojure.string :as string]
             [clojure.string :as string]
             [frontend.util :as util]
             [frontend.util :as util]
-            [frontend.handler.notification :as notification]))
+            [frontend.handler.notification :as notification]
+            [promesa.core :as p]
+            [frontend.db :as db]
+            [frontend.state :as state]
+            [frontend.config :as config]))
 
 
 (defn run-git-command!
 (defn run-git-command!
   [command]
   [command]
   (ipc/ipc "runGit" command))
   (ipc/ipc "runGit" command))
 
 
+;; TODO: export to pdf/html/word
 (defn run-pandoc-command!
 (defn run-pandoc-command!
   [command]
   [command]
   (ipc/ipc "runPandoc" command))
   (ipc/ipc "runPandoc" command))
 
 
+(defn wrap-notification!
+  [command f args]
+  (p/let [result (f args)]
+    (notification/show!
+     (if (string/blank? result)
+       [:p [:code.mr-1 (str command " " args) ]
+        "was executed successfully!"]
+       result)
+     :success
+     false)))
+
 (defn run-command!
 (defn run-command!
   [command]
   [command]
   (let [[command args] (util/split-first " " command)
   (let [[command args] (util/split-first " " command)
@@ -20,11 +36,46 @@
       (let [args (string/trim args)]
       (let [args (string/trim args)]
         (case (keyword command)
         (case (keyword command)
          :git
          :git
-         (run-git-command! args)
+         (wrap-notification! command run-git-command! args)
 
 
          ;; :pandoc
          ;; :pandoc
-         ;; (run-pandoc-command! args)
+         ;; (wrap-notification! command run-pandoc-command! args)
 
 
          (notification/show!
          (notification/show!
           [:div (str command " is not supported yet!")]
           [:div (str command " is not supported yet!")]
           :error))))))
           :error))))))
+
+;; git show $REV:$FILE
+(defn- get-versioned-file-content
+  [hash path]
+  (when (and hash path)
+    (let [repo (state/get-current-repo)
+          local-dir (config/get-local-dir repo)
+          path (string/replace path (str local-dir "/") "")]
+      (p/let [content (run-git-command! ["show" (str hash ":" path)])]
+        (state/pub-event! [:modal/show
+                           [:div.w-full.sm:max-w-lg {:style {:width 700}}
+                            [:div.font-bold.mb-4 (str path (util/format " (%s)" hash)) ]
+                            [:pre content]]])))))
+
+(defn get-file-latest-git-log
+  [page n]
+  (when (integer? n)
+    (let [file-id (:db/id (:block/file page))]
+      (when-let [path (:file/path (db/entity file-id))]
+        (p/let [result (run-git-command! ["log" (str "-" n) "--pretty=format:Commit: %C(auto)%h$$$%s$$$%ad" "-p" path])
+                lines (->> (string/split-lines result)
+                           (filter #(string/starts-with? % "Commit: ")))]
+          (notification/show! [:div
+                               [:div.font-bold "File history - " path]
+                               (for [line lines]
+                                 (let [[hash title time] (string/split line "$$$")
+                                       hash (subs hash 8)]
+                                   [:div.my-4 {:key hash}
+                                    [:hr]
+                                    [:div.mb-2
+                                     [:a.font-medium.mr-1.inline
+                                      {:on-click (fn [] (get-versioned-file-content hash path))}
+                                      hash]
+                                     title]
+                                    [:div.opacity-50 time]]))] :success false))))))

+ 4 - 2
src/main/frontend/ui.cljs

@@ -177,7 +177,9 @@
                   "entered" "transition ease-out duration-300 transform translate-y-0 opacity-100 sm:translate-x-0"
                   "entered" "transition ease-out duration-300 transform translate-y-0 opacity-100 sm:translate-x-0"
                   "exiting" "transition ease-in duration-100 opacity-100"
                   "exiting" "transition ease-in duration-100 opacity-100"
                   "exited" "transition ease-in duration-100 opacity-0")}
                   "exited" "transition ease-in duration-100 opacity-0")}
-        [:div.rounded-lg.shadow-xs.overflow-hidden
+        [:div.rounded-lg.shadow-xs {:style {:max-height "calc(100vh - 200px)"
+                                            :overflow-y "scroll"
+                                            :overflow-x "hidden"}}
          [:div.p-4
          [:div.p-4
           [:div.flex.items-start
           [:div.flex.items-start
            [:div.flex-shrink-0
            [:div.flex-shrink-0
@@ -489,7 +491,7 @@
                    (state/close-settings!))
                    (state/close-settings!))
         modal-panel-content (or modal-panel-content (fn [close] [:div]))]
         modal-panel-content (or modal-panel-content (fn [close] [:div]))]
     [:div.ui__modal
     [:div.ui__modal
-     {:style {:z-index (if show? 10 -1)}}
+     {:style {:z-index (if show? 100 -1)}}
      (css-transition
      (css-transition
       {:in show? :timeout 0}
       {:in show? :timeout 0}
       (fn [state]
       (fn [state]