| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- (ns frontend.handler.repo
- "System-component-like ns that manages user's repos/graphs"
- (:refer-clojure :exclude [clone])
- (:require [cljs-bean.core :as bean]
- [clojure.string :as string]
- [electron.ipc :as ipc]
- [frontend.config :as config]
- [frontend.date :as date]
- [frontend.db :as db]
- [frontend.db.persist :as db-persist]
- [frontend.db.react :as react]
- [frontend.db.restore :as db-restore]
- [frontend.handler.global-config :as global-config-handler]
- [frontend.handler.graph :as graph-handler]
- [frontend.handler.notification :as notification]
- [frontend.handler.repo-config :as repo-config-handler]
- [frontend.handler.route :as route-handler]
- [frontend.handler.ui :as ui-handler]
- [frontend.idb :as idb]
- [frontend.persist-db :as persist-db]
- [frontend.search :as search]
- [frontend.state :as state]
- [frontend.undo-redo :as undo-redo]
- [frontend.util :as util]
- [frontend.util.text :as text-util]
- [logseq.common.config :as common-config]
- [logseq.db :as ldb]
- [logseq.db.frontend.schema :as db-schema]
- [promesa.core :as p]))
- ;; Project settings should be checked in two situations:
- ;; 1. User changes the config.edn directly in logseq.com (fn: alter-file)
- ;; 2. Git pulls the new change (fn: load-files)
- (defn remove-repo!
- [{:keys [url] :as repo} & {:keys [switch-graph?]
- :or {switch-graph? true}}]
- (let [current-repo (state/get-current-repo)
- db-based? (config/db-based-graph? url)]
- (when (or (config/local-file-based-graph? url) db-based?)
- (p/do!
- (idb/clear-local-db! url) ; clear file handles
- (db/remove-conn! url)
- (db-persist/delete-graph! url)
- (search/remove-db! url)
- (state/delete-repo! repo)
- (when switch-graph?
- (if (= current-repo url)
- (do
- (state/set-current-repo! nil)
- (when-let [graph (:url (first (state/get-repos)))]
- (notification/show! (str "Removed graph "
- (pr-str (text-util/get-graph-name-from-path url))
- ". Redirecting to graph "
- (pr-str (text-util/get-graph-name-from-path graph)))
- :success)
- (state/pub-event! [:graph/switch graph {:persist? false}])))
- (notification/show! (str "Removed graph " (pr-str (text-util/get-graph-name-from-path url))) :success)))))))
- (defn start-repo-db-if-not-exists!
- [repo & {:as opts}]
- (state/set-current-repo! repo)
- (db/start-db-conn! repo (assoc opts
- :db-graph? (config/db-based-graph? repo)
- :listen-handler (fn [conn]
- (undo-redo/listen-db-changes! repo conn)))))
- (defn restore-and-setup-repo!
- "Restore the db of a graph from the persisted data, and setup. Create a new
- conn, or replace the conn in state with a new one."
- [repo & {:as opts}]
- (p/do!
- (state/set-db-restoring! true)
- (db-restore/restore-graph! repo opts)
- (repo-config-handler/restore-repo-config! repo)
- (when (config/global-config-enabled?)
- (global-config-handler/restore-global-config!))
- ;; Don't have to unlisten the old listener, as it will be destroyed with the conn
- (when-not (true? (:ignore-style? opts))
- (ui-handler/add-style-if-exists!))
- (when-not config/publishing?
- (state/set-db-restoring! false))))
- (defn rebuild-index!
- [url]
- (when-not (state/unlinked-dir? (config/get-repo-dir url))
- (when url
- (search/reset-indice! url)
- (db/remove-conn! url)
- (react/clear-query-state!)
- (-> (p/do! (db-persist/delete-graph! url))
- (p/catch (fn [error]
- (prn "Delete repo failed, error: " error)))))))
- (defn re-index!
- [nfs-rebuild-index! ok-handler]
- (when-let [repo (state/get-current-repo)]
- (state/reset-parsing-state!)
- (let [dir (config/get-repo-dir repo)]
- (when-not (state/unlinked-dir? dir)
- (route-handler/redirect-to-home!)
- (let [local? (config/local-file-based-graph? repo)]
- (if local?
- (nfs-rebuild-index! repo ok-handler)
- (rebuild-index! repo))
- (js/setTimeout
- (route-handler/redirect-to-home!)
- 500))))))
- (defn get-repos
- []
- (p/let [nfs-dbs (db-persist/get-all-graphs)
- nfs-dbs (map (fn [db]
- (let [graph-name (:name db)]
- {:url graph-name
- :metadata (:metadata db)
- :root (config/get-local-dir graph-name)
- :nfs? true}))
- nfs-dbs)
- nfs-dbs (and (seq nfs-dbs)
- (cond (util/electron?)
- (p/chain
- (ipc/ipc :inflateGraphsInfo (ldb/write-transit-str nfs-dbs))
- ldb/read-transit-str)
- ;(mobile-util/native-platform?)
- ;(util-fs/inflate-graphs-info nfs-dbs)
- :else
- nfs-dbs))]
- (seq (bean/->clj nfs-dbs))))
- (defn combine-local-&-remote-graphs
- [local-repos remote-repos]
- (when-let [repos' (seq (concat (map (fn [{:keys [sync-meta metadata] :as repo}]
- (let [graph-id (some-> (or (:kv/value metadata)
- (second sync-meta)) str)]
- (if graph-id (assoc repo :GraphUUID graph-id) repo)))
- local-repos)
- (some->> remote-repos
- (map #(assoc % :remote? true)))))]
- (let [app-major-schema-version (str (:major (db-schema/parse-schema-version db-schema/version)))
- repos' (group-by :url repos')
- repos'' (mapcat (fn [[k vs]]
- (if (some? k)
- (let [remote-repos (filter :remote? vs)
- version-matched-remote-repo
- (first
- (filter
- #(= app-major-schema-version (:GraphSchemaVersion %))
- remote-repos))]
- [(merge (first vs) (second vs) version-matched-remote-repo)])
- vs))
- repos')]
- (sort-by (fn [repo]
- (let [graph-name (or (:GraphName repo)
- (last (string/split (:root repo) #"/")))]
- [(:remote? repo) (string/lower-case graph-name)])) repos''))))
- (defn get-detail-graph-info
- [url]
- (when-let [graphs (seq (and url (combine-local-&-remote-graphs
- (state/get-repos)
- (state/get-remote-file-graphs))))]
- (first (filter #(when-let [url' (:url %)]
- (= url url')) graphs))))
- (defn refresh-repos!
- []
- (p/let [repos (get-repos)
- repos' (combine-local-&-remote-graphs
- repos
- (concat
- (state/get-rtc-graphs)
- (when-not (or (util/mobile?) util/web-platform?)
- (state/get-remote-file-graphs))))]
- (state/set-repos! repos')
- repos'))
- (defn graph-ready!
- ;; FIXME: Call electron that the graph is loaded, an ugly implementation for redirect to page when graph is restored
- [graph]
- (when (util/electron?)
- (ipc/ipc "graphReady" graph)))
- (defn graph-already-exists?
- "Checks to see if given db graph name already exists"
- [graph-name]
- (let [full-graph-name (string/lower-case (str config/db-version-prefix graph-name))]
- (some #(= (some-> (:url %) string/lower-case) full-graph-name) (state/get-repos))))
- (defn- create-db [full-graph-name {:keys [file-graph-import?]}]
- (->
- (p/let [config (common-config/create-config-for-db-graph config/config-default-content)
- _ (persist-db/<new full-graph-name
- (cond-> {:config config
- :graph-git-sha config/revision}
- file-graph-import? (assoc :import-type :file-graph)))
- _ (start-repo-db-if-not-exists! full-graph-name)
- _ (state/add-repo! {:url full-graph-name :root (config/get-local-dir full-graph-name)})
- _ (restore-and-setup-repo! full-graph-name {:file-graph-import? file-graph-import?})
- _ (when-not file-graph-import? (route-handler/redirect-to-home!))
- _ (repo-config-handler/set-repo-config-state! full-graph-name config/config-default-content)
- ;; TODO: handle global graph
- _ (state/pub-event! [:init/commands])
- _ (when-not file-graph-import? (state/pub-event! [:page/create (date/today) {:redirect? false}]))]
- (state/pub-event! [:shortcut/refresh])
- (route-handler/redirect-to-home!)
- (ui-handler/re-render-root!)
- (graph-handler/settle-metadata-to-local! {:created-at (js/Date.now)})
- (prn "New db created: " full-graph-name)
- full-graph-name)
- (p/catch (fn [error]
- (notification/show! "Create graph failed." :error)
- (js/console.error error)))))
- (defn new-db!
- "Handler for creating a new database graph"
- ([graph] (new-db! graph {}))
- ([graph opts]
- (let [full-graph-name (str config/db-version-prefix graph)]
- (if (graph-already-exists? graph)
- (state/pub-event! [:notification/show
- {:content (str "The graph '" graph "' already exists. Please try again with another name.")
- :status :error}])
- (create-db full-graph-name opts)))))
- (defn fix-broken-graph!
- [graph]
- (state/<invoke-db-worker :thread-api/fix-broken-graph graph))
- (defn gc-graph!
- [graph]
- (p/do!
- (state/<invoke-db-worker :thread-api/gc-graph graph)
- (state/pub-event! [:notification/show
- {:content "Graph gc successfully!"
- :status :success}])))
|