| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- (ns frontend.components.repo
- (:require [clojure.string :as string]
- [frontend.components.commit :as commit]
- [frontend.components.encryption :as encryption]
- [frontend.components.svg :as svg]
- [frontend.components.widgets :as widgets]
- [frontend.config :as config]
- [frontend.context.i18n :as i18n]
- [frontend.db :as db]
- [frontend.encrypt :as e]
- [frontend.handler.common :as common-handler]
- [frontend.handler.export :as export-handler]
- [frontend.handler.page :as page-handler]
- [frontend.handler.repo :as repo-handler]
- [frontend.handler.route :as route-handler]
- [frontend.handler.web.nfs :as nfs-handler]
- [frontend.modules.shortcut.core :as shortcut]
- [frontend.state :as state]
- [frontend.ui :as ui]
- [frontend.util :as util]
- [frontend.version :as version]
- [reitit.frontend.easy :as rfe]
- [rum.core :as rum]
- [frontend.mobile.util :as mobile-util]))
- (rum/defc add-repo
- [args]
- (if-let [graph-types (get-in args [:query-params :graph-types])]
- (let [graph-types-s (->> (string/split graph-types #",")
- (mapv keyword))]
- (when (seq graph-types-s)
- (widgets/add-graph :graph-types graph-types-s)))
- (widgets/add-graph)))
- (rum/defc repos < rum/reactive
- []
- (let [repos (->> (state/sub [:me :repos])
- (remove #(= (:url %) config/local-repo)))
- repos (util/distinct-by :url repos)]
- (rum/with-context [[t] i18n/*tongue-context*]
- (if (seq repos)
- [:div#graphs
- [:h1.title "All Graphs"]
- [:p.ml-2.opacity-70
- (if (state/github-authed?)
- "A \"graph\" in Logseq could be either a local directory or a git repo."
- "A \"graph\" in Logseq means a local directory.")]
- [:div.pl-1.content.mt-3
- [:div.flex.flex-row.my-4
- (when (nfs-handler/supported?)
- [:div.mr-8
- (ui/button
- (t :open-a-directory)
- :on-click #(page-handler/ls-dir-files! shortcut/refresh!))])
- (when (and (state/logged?) (not (util/electron?)))
- (ui/button
- "Add another git repo"
- :href (rfe/href :repo-add nil {:graph-types "github"})
- :intent "logseq"))]
- (for [{:keys [id url] :as repo} repos]
- (let [local? (config/local-db? url)]
- [:div.flex.justify-between.mb-1 {:key id}
- (if local?
- [:a
- (config/get-local-dir url)]
- [:a {:target "_blank"
- :href url}
- (db/get-repo-path url)])
- [:div.controls
- (when (e/encrypted-db? url)
- [:a.control {:title "Show encryption information about this graph"
- :on-click (fn []
- (state/set-modal! (encryption/encryption-dialog url)))}
- "🔐"])
- [:a.text-gray-400.ml-4 {:title "No worries, unlink this graph will clear its cache only, it does not remove your files on the disk."
- :on-click (fn []
- (repo-handler/remove-repo! repo))}
- "Unlink"]]]))]]
- (widgets/add-graph)))))
- (defn refresh-cb []
- (page-handler/create-today-journal!)
- (shortcut/refresh!))
- (rum/defc sync-status < rum/reactive
- {:did-mount (fn [state]
- (js/setTimeout common-handler/check-changed-files-status 1000)
- state)}
- [repo]
- (when (and repo
- (string/starts-with? repo "https://"))
- (let [changed-files (state/sub [:repo/changed-files repo])
- should-push? (seq changed-files)
- git-status (state/sub [:git/status repo])
- pushing? (= :pushing git-status)
- pulling? (= :pulling git-status)
- git-failed? (contains?
- #{:push-failed
- :clone-failed
- :checkout-failed
- :fetch-failed
- :merge-failed}
- git-status)
- push-failed? (= :push-failed git-status)
- last-pulled-at (db/sub-key-value repo :git/last-pulled-at)
- ;; db-persisted? (state/sub [:db/persisted? repo])
- editing? (seq (state/sub :editor/editing?))]
- [:div.flex-row.flex.items-center.cp__repo-indicator
- (when pushing? svg/loading)
- (ui/dropdown
- (fn [{:keys [toggle-fn]}]
- [:div.cursor.w-2.h-2.sync-status.mr-2
- {:class (cond
- git-failed?
- "bg-red-500"
- (or
- ;; (not db-persisted?)
- editing?
- should-push? pushing?)
- "bg-orange-400"
- :else
- "bg-green-600")
- :style {:border-radius "50%"
- :margin-top 2}
- :on-mouse-over
- (fn [e]
- (toggle-fn)
- (js/setTimeout common-handler/check-changed-files-status 0))}])
- (fn [{:keys [toggle-fn]}]
- (rum/with-context [[t] i18n/*tongue-context*]
- [:div.p-2.rounded-md.shadow-xs.bg-base-3.flex.flex-col.sync-content
- {:on-mouse-leave toggle-fn}
- [:div
- [:div
- (cond
- push-failed?
- [:p (t :git/push-failed)]
- (and should-push? (seq changed-files))
- [:div.changes
- [:ul.overflow-y-auto {:style {:max-height 250}}
- (for [file changed-files]
- [:li {:key (str "sync-" file)}
- [:div.flex.flex-row.justify-between.align-items
- [:a {:href (rfe/href :file {:path file})}
- file]
- [:a.ml-4.text-sm.mt-1
- {:on-click (fn [e]
- (export-handler/download-file! file))}
- [:span (t :download)]]]])]]
- :else
- [:p (t :git/local-changes-synced)])]
- ;; [:a.text-sm.font-bold {:href "/diff"} "Check diff"]
- [:div.flex.flex-row.justify-between.align-items.mt-2
- (ui/button (t :git/push)
- :on-click (fn [] (state/set-modal! commit/add-commit-message)))
- (when pushing? svg/loading)]]
- [:hr]
- [:div
- (when-not (string/blank? last-pulled-at)
- [:p {:style {:font-size 12}} (t :git/last-pull)
- (str ": " last-pulled-at)])
- [:div.flex.flex-row.justify-between.align-items
- (ui/button (t :git/pull)
- :on-click (fn [] (repo-handler/pull-current-repo)))
- (when pulling? svg/loading)]
- [:a.mt-5.text-sm.opacity-50.block
- {:on-click (fn []
- (export-handler/export-repo-as-zip! repo))}
- (t :repo/download-zip)]
- [:p.pt-2.text-sm.opacity-50
- (t :git/version) (str " " version/version)]]])))])))
- (rum/defc repos-dropdown < rum/reactive
- [on-click]
- (when-let [current-repo (state/sub :git/current-repo)]
- (rum/with-context [[t] i18n/*tongue-context*]
- (let [get-repo-name (fn [repo]
- (if (config/local-db? repo)
- (config/get-local-dir repo)
- (db/get-repo-path repo)))
- repos (state/sub [:me :repos])
- repos (remove (fn [r] (= config/local-repo (:url r))) repos)
- switch-repos (remove (fn [repo]
- (= current-repo (:url repo)))
- repos)]
- (when (seq repos)
- (ui/dropdown-with-links
- (fn [{:keys [toggle-fn]}]
- [:a#repo-switch.block.pr-2.whitespace-nowrap {:on-click toggle-fn
- :class (when-not (util/mobile?)
- "fade-link")}
- [:span
- (let [repo-name (get-repo-name current-repo)
- repo-name (if (or (util/electron?)
- (mobile-util/is-native-platform?))
- (last
- (string/split repo-name #"/"))
- repo-name)]
- [:span#repo-name {:title repo-name} repo-name])
- [:span.dropdown-caret.ml-1 {:style {:border-top-color "#6b7280"}}]]])
- (mapv
- (fn [{:keys [id url]}]
- {:title (get-repo-name url)
- :options {:class "ml-1"
- :on-click (fn []
- (repo-handler/push-if-auto-enabled! (state/get-current-repo))
- (state/set-current-repo! url)
- ;; load config
- (common-handler/reset-config! url nil)
- (shortcut/refresh!)
- (when-not (= :draw (state/get-current-route))
- (route-handler/redirect-to-home!))
- (when on-click
- (on-click url)))}})
- switch-repos)
- (cond->
- {:modal-class (util/hiccup->class
- "origin-top-right.absolute.left-0.mt-2.w-48.rounded-md.shadow-lg")
- :links-footer [:div
- (when (seq switch-repos) [:hr.my-4])
- [:a {:class "block px-4 py-2 text-sm transition ease-in-out duration-150 cursor menu-link"
- :href (rfe/href :repo-add)}
- (t :new-graph)]
- [:a {:class "block px-4 py-2 text-sm transition ease-in-out duration-150 cursor menu-link"
- :href (rfe/href :repos)}
- (t :all-graphs)]
- (let [nfs-repo? (config/local-db? current-repo)]
- (when (and nfs-repo?
- (not= current-repo config/local-repo)
- (nfs-handler/supported?))
- [:a {:class "block px-4 py-2 text-sm transition ease-in-out duration-150 cursor menu-link"
- :on-click (fn []
- (state/pub-event!
- [:modal/show
- [:div {:style {:max-width 700}}
- [:p "Refresh detects and processes files modified on your disk and diverged from the actual Logseq page content. Continue?"]
- (ui/button
- "Yes"
- :on-click (fn []
- (state/close-modal!)
- (nfs-handler/refresh! (state/get-current-repo) refresh-cb)))]]))}
- (t :sync-from-local-files)]))
- [:a {:class "block px-4 py-2 text-sm transition ease-in-out duration-150 cursor menu-link"
- :on-click (fn []
- (state/pub-event!
- [:modal/show
- [:div {:style {:max-width 700}}
- [:p "Re-index will discard the current graph, and then processes all the files again as they are currently stored on disk. You will lose unsaved changes and it might take a while. Continue?"]
- (ui/button
- "Yes"
- :on-click (fn []
- (state/close-modal!)
- (repo-handler/re-index!
- nfs-handler/rebuild-index!
- page-handler/create-today-journal!)))]]))}
- (t :re-index)]]}
- (seq switch-repos)
- (assoc :links-header [:div.font-medium.text-sm.opacity-70.px-4.py-2
- "Switch to:"]))))))))
|