repo.cljs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. (ns frontend.handler.repo
  2. "System-component-like ns that manages user's repos/graphs"
  3. (:refer-clojure :exclude [clone])
  4. (:require [clojure.string :as string]
  5. [frontend.config :as config]
  6. [frontend.date :as date]
  7. [frontend.db :as db]
  8. [frontend.db.restore :as db-restore]
  9. [frontend.handler.repo-config :as repo-config-handler]
  10. [frontend.handler.common.config-edn :as config-edn-common-handler]
  11. [frontend.handler.route :as route-handler]
  12. [frontend.handler.ui :as ui-handler]
  13. [frontend.handler.notification :as notification]
  14. [frontend.handler.global-config :as global-config-handler]
  15. [frontend.handler.graph :as graph-handler]
  16. [frontend.idb :as idb]
  17. [frontend.search :as search]
  18. [frontend.state :as state]
  19. [frontend.util :as util]
  20. [frontend.util.fs :as util-fs]
  21. [frontend.util.text :as text-util]
  22. [frontend.persist-db :as persist-db]
  23. [promesa.core :as p]
  24. [frontend.db.persist :as db-persist]
  25. [electron.ipc :as ipc]
  26. [cljs-bean.core :as bean]
  27. [frontend.mobile.util :as mobile-util]
  28. [borkdude.rewrite-edn :as rewrite]))
  29. ;; Project settings should be checked in two situations:
  30. ;; 1. User changes the config.edn directly in logseq.com (fn: alter-file)
  31. ;; 2. Git pulls the new change (fn: load-files)
  32. (defn remove-repo!
  33. [{:keys [url] :as repo} & {:keys [switch-graph?]
  34. :or {switch-graph? true}}]
  35. (let [current-repo (state/get-current-repo)
  36. db-based? (config/db-based-graph? url)]
  37. (when (or (config/local-file-based-graph? url) db-based?)
  38. (p/do!
  39. (idb/clear-local-db! url) ; clear file handles
  40. (db/remove-conn! url)
  41. (db-persist/delete-graph! url)
  42. (search/remove-db! url)
  43. (state/delete-repo! repo)
  44. (when switch-graph?
  45. (if (= current-repo url)
  46. (do
  47. (state/set-current-repo! nil)
  48. (when-let [graph (:url (first (state/get-repos)))]
  49. (notification/show! (str "Removed graph "
  50. (pr-str (text-util/get-graph-name-from-path url))
  51. ". Redirecting to graph "
  52. (pr-str (text-util/get-graph-name-from-path graph)))
  53. :success)
  54. (state/pub-event! [:graph/switch graph {:persist? false}])))
  55. (notification/show! (str "Removed graph " (pr-str (text-util/get-graph-name-from-path url))) :success)))))))
  56. (defn start-repo-db-if-not-exists!
  57. [repo & {:as opts}]
  58. (state/set-current-repo! repo)
  59. (db/start-db-conn! repo (merge
  60. opts
  61. {:db-graph? (config/db-based-graph? repo)})))
  62. (defn restore-and-setup-repo!
  63. "Restore the db of a graph from the persisted data, and setup. Create a new
  64. conn, or replace the conn in state with a new one."
  65. [repo & {:as opts}]
  66. (p/do!
  67. (state/set-db-restoring! true)
  68. (db-restore/restore-graph! repo opts)
  69. (repo-config-handler/restore-repo-config! repo)
  70. (when (config/global-config-enabled?)
  71. (global-config-handler/restore-global-config!))
  72. ;; Don't have to unlisten the old listener, as it will be destroyed with the conn
  73. (ui-handler/add-style-if-exists!)
  74. (when-not config/publishing?
  75. (state/set-db-restoring! false))))
  76. (defn rebuild-index!
  77. [url]
  78. (when-not (state/unlinked-dir? (config/get-repo-dir url))
  79. (when url
  80. (search/reset-indice! url)
  81. (db/remove-conn! url)
  82. (db/clear-query-state!)
  83. (-> (p/do! (db-persist/delete-graph! url))
  84. (p/catch (fn [error]
  85. (prn "Delete repo failed, error: " error)))))))
  86. (defn re-index!
  87. [nfs-rebuild-index! ok-handler]
  88. (when-let [repo (state/get-current-repo)]
  89. (state/reset-parsing-state!)
  90. (let [dir (config/get-repo-dir repo)]
  91. (when-not (state/unlinked-dir? dir)
  92. (route-handler/redirect-to-home!)
  93. (let [local? (config/local-file-based-graph? repo)]
  94. (if local?
  95. (nfs-rebuild-index! repo ok-handler)
  96. (rebuild-index! repo))
  97. (js/setTimeout
  98. (route-handler/redirect-to-home!)
  99. 500))))))
  100. (defn get-repos
  101. []
  102. (p/let [nfs-dbs (db-persist/get-all-graphs)
  103. nfs-dbs (map (fn [db]
  104. (let [graph-name (:name db)]
  105. {:url graph-name
  106. :metadata (:metadata db)
  107. :root (config/get-local-dir graph-name)
  108. :nfs? true}))
  109. nfs-dbs)
  110. nfs-dbs (and (seq nfs-dbs)
  111. (cond (util/electron?)
  112. (ipc/ipc :inflateGraphsInfo nfs-dbs)
  113. (mobile-util/native-platform?)
  114. (util-fs/inflate-graphs-info nfs-dbs)
  115. :else
  116. nfs-dbs))]
  117. (seq (bean/->clj nfs-dbs))))
  118. (defn combine-local-&-remote-graphs
  119. [local-repos remote-repos]
  120. (when-let [repos' (seq (concat (map (fn [{:keys [sync-meta metadata] :as repo}]
  121. (let [graph-id (or (:kv/value metadata) (second sync-meta))]
  122. (if graph-id (assoc repo :GraphUUID graph-id) repo)))
  123. local-repos)
  124. (some->> remote-repos
  125. (map #(assoc % :remote? true)))))]
  126. (let [repos' (group-by :GraphUUID repos')
  127. repos'' (mapcat (fn [[k vs]]
  128. (if-not (nil? k)
  129. [(merge (first vs) (second vs))] vs))
  130. repos')]
  131. (sort-by (fn [repo]
  132. (let [graph-name (or (:GraphName repo)
  133. (last (string/split (:root repo) #"/")))]
  134. [(:remote? repo) (string/lower-case graph-name)])) repos''))))
  135. (defn get-detail-graph-info
  136. [url]
  137. (when-let [graphs (seq (and url (combine-local-&-remote-graphs
  138. (state/get-repos)
  139. (state/get-remote-file-graphs))))]
  140. (first (filter #(when-let [url' (:url %)]
  141. (= url url')) graphs))))
  142. (defn refresh-repos!
  143. []
  144. (p/let [repos (get-repos)
  145. repos' (combine-local-&-remote-graphs
  146. repos
  147. (concat
  148. (state/get-rtc-graphs)
  149. (state/get-remote-file-graphs)))]
  150. (state/set-repos! repos')
  151. repos'))
  152. (defn graph-ready!
  153. ;; FIXME: Call electron that the graph is loaded, an ugly implementation for redirect to page when graph is restored
  154. [graph]
  155. (when (util/electron?)
  156. (ipc/ipc "graphReady" graph)))
  157. (defn graph-already-exists?
  158. "Checks to see if given db graph name already exists"
  159. [graph-name]
  160. (let [full-graph-name (string/lower-case (str config/db-version-prefix graph-name))]
  161. (some #(= (some-> (:url %) string/lower-case) full-graph-name) (state/get-repos))))
  162. (defn migrate-db-config
  163. [content]
  164. (-> (reduce rewrite/dissoc
  165. (rewrite/parse-string (str content))
  166. (keys config-edn-common-handler/file-only-config))
  167. str))
  168. (defn- create-db [full-graph-name {:keys [file-graph-import?]}]
  169. (->
  170. (p/let [config (migrate-db-config config/config-default-content)
  171. _ (persist-db/<new full-graph-name
  172. (cond-> {:config config}
  173. file-graph-import? (assoc :import-type :file-graph)))
  174. _ (start-repo-db-if-not-exists! full-graph-name)
  175. _ (state/add-repo! {:url full-graph-name :root (config/get-local-dir full-graph-name)})
  176. _ (restore-and-setup-repo! full-graph-name)
  177. _ (when-not file-graph-import? (route-handler/redirect-to-home!))
  178. _ (repo-config-handler/set-repo-config-state! full-graph-name config/config-default-content)
  179. ;; TODO: handle global graph
  180. _ (state/pub-event! [:init/commands])
  181. _ (when-not file-graph-import? (state/pub-event! [:page/create (date/today) {:redirect? false}]))]
  182. (state/pub-event! [:shortcut/refresh])
  183. (route-handler/redirect-to-home!)
  184. (ui-handler/re-render-root!)
  185. (graph-handler/settle-metadata-to-local! {:created-at (js/Date.now)})
  186. (prn "New db created: " full-graph-name)
  187. full-graph-name)
  188. (p/catch (fn [error]
  189. (notification/show! "Create graph failed." :error)
  190. (js/console.error error)))))
  191. (defn new-db!
  192. "Handler for creating a new database graph"
  193. ([graph] (new-db! graph {}))
  194. ([graph opts]
  195. (let [full-graph-name (str config/db-version-prefix graph)]
  196. (if (graph-already-exists? graph)
  197. (state/pub-event! [:notification/show
  198. {:content (str "The graph '" graph "' already exists. Please try again with another name.")
  199. :status :error}])
  200. (create-db full-graph-name opts)))))