state.cljs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823
  1. (ns frontend.state
  2. (:require [frontend.storage :as storage]
  3. [rum.core :as rum]
  4. [frontend.util :as util :refer-macros [profile]]
  5. [clojure.string :as string]
  6. [medley.core :as medley]
  7. [goog.object :as gobj]
  8. [goog.dom :as gdom]
  9. [dommy.core :as dom]
  10. [cljs.core.async :as async]))
  11. (defonce state
  12. (atom
  13. {:route-match nil
  14. :today nil
  15. :daily/migrating? nil
  16. :db/batch-txs (async/chan 100)
  17. :notification/show? false
  18. :notification/content nil
  19. :repo/cloning? false
  20. :repo/loading-files? nil
  21. :repo/importing-to-db? nil
  22. :repo/sync-status {}
  23. :repo/changed-files nil
  24. :indexeddb/support? true
  25. ;; TODO: save in local storage so that if :changed? is true when user
  26. ;; reloads the browser, the app should re-index the repo (another way
  27. ;; is to save all the tx data since :last-stored-at)
  28. ;; repo -> {:last-stored-at :last-modified-at}
  29. :repo/persist-status {}
  30. :me nil
  31. :git/clone-repo (or (storage/get :git/clone-repo) "")
  32. :git/current-repo (storage/get :git/current-repo)
  33. :git/status {}
  34. :format/loading {}
  35. :draw? false
  36. :db/restoring? nil
  37. :journals-length 1
  38. :search/q ""
  39. :search/result nil
  40. ;; custom shortcuts
  41. :shortcuts {:editor/new-block "enter"}
  42. ;; right sidebar
  43. :ui/sidebar-open? false
  44. :ui/left-sidebar-open? false
  45. :ui/theme (or (storage/get :ui/theme) "dark")
  46. ;; :show-all, :hide-block-body, :hide-block-children
  47. :ui/cycle-collapse :show-all
  48. :ui/collapsed-blocks {}
  49. :ui/sidebar-collapsed-blocks {}
  50. :ui/root-component nil
  51. :ui/file-component nil
  52. :ui/custom-query-components {}
  53. :ui/show-recent? false
  54. :ui/developer-mode? (or (= (storage/get "developer-mode") "true")
  55. false)
  56. :document/mode? (or (storage/get :document/mode?) false)
  57. :github/contents {}
  58. :config {}
  59. :editor/show-page-search? false
  60. :editor/show-page-search-hashtag? false
  61. :editor/show-date-picker? false
  62. ;; With label or other data
  63. :editor/show-input nil
  64. :editor/last-saved-cursor nil
  65. :editor/editing? nil
  66. :editor/pos 0
  67. :editor/content {}
  68. :editor/block nil
  69. :editor/set-timestamp-block nil
  70. :cursor-range nil
  71. :selection/mode false
  72. :selection/blocks []
  73. :selection/start-block nil
  74. :custom-context-menu/show? false
  75. :custom-context-menu/links nil
  76. ;; pages or blocks in the right sidebar
  77. :sidebar/blocks '()
  78. :preferred-language (storage/get :preferred-language)
  79. ;; all notification contents as k-v pairs
  80. :notification/contents {}}))
  81. (defn get-route-match
  82. []
  83. (:route-match @state))
  84. (defn get-current-route
  85. []
  86. (get-in (get-route-match) [:data :name]))
  87. (defn get-current-page
  88. []
  89. (and
  90. (= :page (get-current-route))
  91. (get-in (get-route-match)
  92. [:path-params :name])))
  93. (defn route-has-p?
  94. []
  95. (get-in (get-route-match) [:query-params :p]))
  96. (defn sub
  97. [ks]
  98. (if (coll? ks)
  99. (util/react (rum/cursor-in state ks))
  100. (util/react (rum/cursor state ks))))
  101. (defn set-state!
  102. [path value]
  103. (if (vector? path)
  104. (swap! state assoc-in path value)
  105. (swap! state assoc path value)))
  106. (defn update-state!
  107. [path f]
  108. (if (vector? path)
  109. (swap! state update-in path f)
  110. (swap! state update path f)))
  111. (defn get-current-repo
  112. []
  113. (:git/current-repo @state))
  114. (defn get-config
  115. ([]
  116. (get-config (get-current-repo)))
  117. ([repo-url]
  118. (get-in @state [:config repo-url])))
  119. (defn sub-config
  120. []
  121. (sub :config))
  122. (defn get-custom-css-link
  123. []
  124. (:custom-css-url (get-config)))
  125. (defn all-pages-public?
  126. []
  127. (true? (:all-pages-public? (get-config))))
  128. (defn enable-grammarly?
  129. []
  130. (true? (:feature/enable-grammarly?
  131. (get (sub-config) (get-current-repo)))))
  132. (defn enable-timetracking?
  133. []
  134. (not (false? (:feature/enable-timetracking?
  135. (get (sub-config) (get-current-repo))))))
  136. (defn get-default-home
  137. []
  138. (:default-home (get-config)))
  139. (defn custom-home-page?
  140. []
  141. (some? (:page (get-default-home))))
  142. (defn get-preferred-format
  143. []
  144. (keyword
  145. (or
  146. (when-let [fmt (:preferred-format (get-config))]
  147. (string/lower-case (name fmt)))
  148. (get-in @state [:me :preferred_format] "markdown"))))
  149. (defn get-preferred-workflow
  150. []
  151. (keyword
  152. (or
  153. (when-let [workflow (:preferred-workflow (get-config))]
  154. (let [workflow (name workflow)]
  155. (if (or (re-find #"now" workflow)
  156. (re-find #"NOW" workflow))
  157. :now
  158. :todo)))
  159. (get-in @state [:me :preferred_workflow] :now))))
  160. (defn get-preferred-todo
  161. []
  162. (if (= (get-preferred-workflow) :now)
  163. "LATER"
  164. "TODO"))
  165. (defn hide-file?
  166. []
  167. (:hide-file-in-page? (get-config)))
  168. (defn page-name-order
  169. []
  170. (:page-name-order (get-config)))
  171. (defn get-repos
  172. []
  173. (get-in @state [:me :repos]))
  174. (defn set-current-repo!
  175. [repo]
  176. (swap! state assoc :git/current-repo repo)
  177. (if repo
  178. (storage/set :git/current-repo repo)
  179. (storage/remove :git/current-repo)))
  180. (defn set-preferred-format!
  181. [format]
  182. (swap! state assoc-in [:me :preferred_format] (name format)))
  183. (defn set-preferred-workflow!
  184. [workflow]
  185. (swap! state assoc-in [:me :preferred_workflow] (name workflow)))
  186. (defn set-preferred-language!
  187. [language]
  188. (set-state! :preferred-language (name language))
  189. (storage/set :preferred-language (name language)))
  190. (defn delete-repo!
  191. [repo]
  192. (swap! state update-in [:me :repos]
  193. (fn [repos]
  194. (->> (remove #(= (:url repo)
  195. (:url %))
  196. repos)
  197. (util/distinct-by :url))))
  198. (when (= (get-current-repo) (:url repo))
  199. (set-current-repo! (:url (first (get-repos))))))
  200. (defn next-collapse-mode
  201. []
  202. (case (:ui/cycle-collapse @state)
  203. :show-all
  204. :hide-block-body
  205. :hide-block-body
  206. :hide-block-children
  207. :hide-block-children
  208. :show-all))
  209. (defn cycle-collapse!
  210. []
  211. (set-state! :ui/cycle-collapse (next-collapse-mode)))
  212. (defn set-timestamp-block!
  213. [value]
  214. (set-state! :editor/set-timestamp-block value))
  215. (defn get-timestamp-block
  216. []
  217. (:editor/set-timestamp-block @state))
  218. (defn set-edit-content!
  219. [input-id value]
  220. (when input-id
  221. (when-let [input (gdom/getElement input-id)]
  222. (gobj/set input "value" value))
  223. (update-state! :editor/content (fn [m]
  224. (assoc m input-id value)))
  225. ;; followers
  226. ;; (when-let [s (util/extract-uuid input-id)]
  227. ;; (let [input (gdom/getElement input-id)
  228. ;; leader-parent (util/rec-get-block-node input)
  229. ;; followers (->> (array-seq (js/document.getElementsByClassName s))
  230. ;; (remove #(= leader-parent %)))]
  231. ;; (prn "followers: " (count followers))
  232. ;; ))
  233. ))
  234. (defn get-edit-input-id
  235. []
  236. (ffirst (:editor/editing? @state)))
  237. (defn get-edit-content
  238. []
  239. (get (:editor/content @state) (get-edit-input-id)))
  240. (defn append-current-edit-content!
  241. [append-text]
  242. (when-not (string/blank? append-text)
  243. (when-let [input-id (get-edit-input-id)]
  244. (when-let [input (gdom/getElement input-id)]
  245. (let [value (gobj/get input "value")
  246. new-value (str value append-text)
  247. new-value (if (or (= (last value) " ")
  248. (= (last value) "\n"))
  249. new-value
  250. (str "\n" new-value))]
  251. (js/document.execCommand "insertText" false append-text)
  252. (update-state! :editor/content (fn [m]
  253. (assoc m input-id new-value))))))))
  254. (defn get-cursor-range
  255. []
  256. (:cursor-range @state))
  257. (defn set-cursor-range!
  258. [range]
  259. (set-state! :cursor-range range))
  260. (defn cloning?
  261. []
  262. (:repo/cloning? @state))
  263. (defn set-cloning?
  264. [value]
  265. (set-state! :repo/cloning? value))
  266. (defn get-block-collapsed-state
  267. [block-id]
  268. (get-in @state [:ui/collapsed-blocks block-id]))
  269. (defn set-collapsed-state!
  270. [block-id value]
  271. (set-state! [:ui/collapsed-blocks block-id] value))
  272. (defn collapse-block!
  273. [block-id]
  274. (set-collapsed-state! block-id true))
  275. (defn expand-block!
  276. [block-id]
  277. (set-collapsed-state! block-id false))
  278. (defn collapsed?
  279. [block-id]
  280. (get-in @state [:ui/collapsed-blocks block-id]))
  281. (defn clear-collapsed-blocks!
  282. []
  283. (set-state! :ui/collapsed-blocks {}))
  284. (defn set-q!
  285. [value]
  286. (set-state! :search/q value))
  287. (defn set-editor-show-page-search
  288. [value]
  289. (set-state! :editor/show-page-search? value)
  290. (set-state! :editor/show-page-search-hashtag? false))
  291. (defn set-editor-show-page-search-hashtag
  292. [value]
  293. (set-state! :editor/show-page-search? value)
  294. (set-state! :editor/show-page-search-hashtag? value))
  295. (defn get-editor-show-page-search
  296. []
  297. (get @state :editor/show-page-search?))
  298. (defn get-editor-show-page-search-hashtag
  299. []
  300. (get @state :editor/show-page-search-hashtag?))
  301. (defn set-editor-show-block-search
  302. [value]
  303. (set-state! :editor/show-block-search? value))
  304. (defn get-editor-show-block-search
  305. []
  306. (get @state :editor/show-block-search?))
  307. (defn set-editor-show-template-search
  308. [value]
  309. (set-state! :editor/show-template-search? value))
  310. (defn get-editor-show-template-search
  311. []
  312. (get @state :editor/show-template-search?))
  313. (defn set-editor-show-date-picker
  314. [value]
  315. (set-state! :editor/show-date-picker? value))
  316. (defn get-editor-show-date-picker
  317. []
  318. (get @state :editor/show-date-picker?))
  319. (defn set-editor-show-input
  320. [value]
  321. (set-state! :editor/show-input value))
  322. (defn get-editor-show-input
  323. []
  324. (get @state :editor/show-input))
  325. (defn set-edit-input-id!
  326. [input-id]
  327. (swap! state update :editor/editing?
  328. (fn [m]
  329. (and input-id {input-id true}))))
  330. (defn set-edit-pos!
  331. [pos]
  332. (set-state! :editor/pos pos))
  333. (defn get-edit-pos
  334. []
  335. (:editor/pos @state))
  336. (defn set-selection-start-block!
  337. [start-block]
  338. (swap! state assoc :selection/start-block start-block))
  339. (defn get-selection-start-block
  340. []
  341. (get @state :selection/start-block))
  342. (defn set-selection-blocks!
  343. [blocks]
  344. (when (seq blocks)
  345. (swap! state assoc
  346. :selection/mode true
  347. :selection/blocks blocks)))
  348. (defn into-selection-mode!
  349. []
  350. (swap! state assoc :selection/mode true))
  351. (defn clear-selection!
  352. []
  353. (swap! state assoc
  354. :selection/mode false
  355. :selection/blocks nil
  356. :selection/up? nil))
  357. (defn clear-selection-blocks!
  358. []
  359. (swap! state assoc :selection/blocks nil))
  360. (defn get-selection-blocks
  361. []
  362. (:selection/blocks @state))
  363. (defn in-selection-mode?
  364. []
  365. (:selection/mode @state))
  366. (defn conj-selection-block!
  367. [block up?]
  368. (dom/add-class! block "selected noselect")
  369. (swap! state assoc
  370. :selection/mode true
  371. :selection/blocks (conj (:selection/blocks @state) block)
  372. :selection/up? up?))
  373. (defn pop-selection-block!
  374. []
  375. (let [[first-block & others] (:selection/blocks @state)]
  376. (swap! state assoc
  377. :selection/mode true
  378. :selection/blocks others)
  379. first-block))
  380. (defn selection-up?
  381. []
  382. (:selection/up? @state))
  383. (defn set-selection-up?
  384. [value]
  385. (swap! state assoc :selection/up? value))
  386. (defn show-custom-context-menu!
  387. [links]
  388. (swap! state assoc
  389. :custom-context-menu/show? true
  390. :custom-context-menu/links links))
  391. (defn hide-custom-context-menu!
  392. []
  393. (swap! state assoc
  394. :custom-context-menu/show? false
  395. :custom-context-menu/links nil))
  396. (defn set-git-clone-repo!
  397. [repo]
  398. (set-state! :git/clone-repo repo)
  399. (storage/set :git/clone-repo repo))
  400. (defn set-github-token!
  401. [repo token]
  402. (when token
  403. (swap! state update-in [:me :repos]
  404. (fn [repos]
  405. (map (fn [r]
  406. (if (= repo (:url r))
  407. (assoc r :token token)
  408. repo)) repos)))))
  409. (defn set-github-installation-tokens!
  410. [tokens]
  411. (when (seq tokens)
  412. (let [tokens (medley/map-keys name tokens)
  413. repos (get-in @state [:me :repos])]
  414. (when (seq repos)
  415. (let [repos (mapv (fn [{:keys [installation_id] :as r}]
  416. (if-let [token (get tokens installation_id)]
  417. (assoc r :token token)
  418. r)) repos)]
  419. (swap! state assoc-in [:me :repos] repos))))))
  420. (defn get-github-token
  421. ([]
  422. (get-github-token (get-current-repo)))
  423. ([repo]
  424. (when repo
  425. (let [repos (get-in @state [:me :repos])]
  426. (-> (filter #(= repo (:url %)) repos)
  427. first
  428. :token)))))
  429. (defn toggle-sidebar-open?!
  430. []
  431. (swap! state update :ui/sidebar-open? not))
  432. (defn open-right-sidebar!
  433. []
  434. (swap! state assoc :ui/sidebar-open? true))
  435. (defn hide-right-sidebar!
  436. []
  437. (swap! state assoc :ui/sidebar-open? false))
  438. (defn sidebar-add-block!
  439. [repo db-id block-type block-data]
  440. (when db-id
  441. (update-state! :sidebar/blocks (fn [blocks]
  442. (->> (remove #(= (second %) db-id) blocks)
  443. (cons [repo db-id block-type block-data])
  444. (distinct))))
  445. (open-right-sidebar!)))
  446. (defn sidebar-remove-block!
  447. [idx]
  448. (update-state! :sidebar/blocks #(util/drop-nth idx %))
  449. (when (empty? (:sidebar/blocks @state))
  450. (hide-right-sidebar!)))
  451. (defn get-sidebar-blocks
  452. []
  453. (:sidebar/blocks @state))
  454. (defn sidebar-block-toggle-collapse!
  455. [db-id]
  456. (when db-id
  457. (update-state! [:ui/sidebar-collapsed-blocks db-id] not)))
  458. (defn set-editing!
  459. [edit-input-id content block cursor-range]
  460. (when edit-input-id
  461. (let [content (or content "")]
  462. (swap! state
  463. (fn [state]
  464. (-> state
  465. (assoc-in [:editor/content edit-input-id] (string/trim content))
  466. (assoc
  467. :editor/block block
  468. :editor/editing? {edit-input-id true}
  469. :cursor-range cursor-range)))))))
  470. (defn clear-edit!
  471. []
  472. (swap! state merge {:editor/editing? nil
  473. :editor/block nil
  474. :cursor-range nil}))
  475. (defn get-edit-block
  476. []
  477. (get @state :editor/block))
  478. (defn set-last-pos!
  479. [new-pos]
  480. (reset! state (assoc @state :editor/last-saved-cursor new-pos)))
  481. (defn set-block-content-and-last-pos!
  482. [edit-input-id content new-pos]
  483. (when edit-input-id
  484. (set-edit-content! edit-input-id content)
  485. (reset! state (assoc @state :editor/last-saved-cursor new-pos))))
  486. (defn set-theme!
  487. [theme]
  488. (set-state! :ui/theme theme)
  489. (storage/set :ui/theme theme))
  490. (defn toggle-theme!
  491. []
  492. (let [theme (:ui/theme @state)
  493. theme' (if (= theme "dark") "white" "dark")]
  494. (set-theme! theme')))
  495. (defn- file-content-key
  496. [repo path]
  497. (str "ls_file_content_" repo path))
  498. (defn update-sync-status!
  499. [status]
  500. (when (seq status)
  501. (when-let [current-repo (get-current-repo)]
  502. (set-state! [:repo/sync-status current-repo] status))))
  503. (defn set-root-component!
  504. [component]
  505. (set-state! :ui/root-component component))
  506. (defn get-root-component
  507. []
  508. (get @state :ui/root-component))
  509. (defn set-file-component!
  510. [component]
  511. (set-state! :ui/file-component component))
  512. (defn clear-file-component!
  513. []
  514. (set-state! :ui/file-component nil))
  515. (defn get-file-component
  516. []
  517. (get @state :ui/file-component))
  518. (defn set-journals-length!
  519. [value]
  520. (when value
  521. (set-state! :journals-length value)))
  522. (defn add-custom-query-component!
  523. [query-string component]
  524. (update-state! :ui/custom-query-components
  525. (fn [m]
  526. (assoc m query-string component))))
  527. (defn remove-custom-query-component!
  528. [query-string]
  529. (update-state! :ui/custom-query-components
  530. (fn [m]
  531. (dissoc m query-string))))
  532. (defn get-custom-query-components
  533. []
  534. (vals (get @state :ui/custom-query-components)))
  535. (defn get-journal-template
  536. []
  537. (when-let [repo (get-current-repo)]
  538. (get-in @state [:config repo :default-templates :journals])))
  539. (defn set-today!
  540. [value]
  541. (set-state! :today value))
  542. (defn toggle-document-mode!
  543. []
  544. (let [mode (get @state :document/mode?)]
  545. (set-state! :document/mode? (not mode))
  546. (storage/set :document/mode? (not mode))))
  547. (defn get-date-formatter
  548. []
  549. (or
  550. (when-let [repo (get-current-repo)]
  551. (get-in @state [:config repo :date-formatter]))
  552. ;; TODO:
  553. (get-in @state [:me :settings :date-formatter])
  554. "MMM do, yyyy"))
  555. (defn set-git-status!
  556. [repo-url value]
  557. (swap! state assoc-in [:git/status repo-url] value))
  558. (defn get-shortcut
  559. [repo key]
  560. (get-in @state [:config repo :shortcuts key]))
  561. (defn get-me
  562. []
  563. (:me @state))
  564. (defn logged?
  565. []
  566. (some? (:name (get-me))))
  567. (defn set-draw!
  568. [value]
  569. (set-state! :draw? value))
  570. (defn in-draw-mode?
  571. []
  572. (:draw? @state))
  573. (defn set-db-restoring!
  574. [value]
  575. (set-state! :db/restoring? value))
  576. (defn get-default-branch
  577. [repo-url]
  578. (or
  579. (some->> (:repos (get-me))
  580. (filter (fn [m]
  581. (= (:url m) repo-url)))
  582. (first)
  583. :branch)
  584. "master"))
  585. (defn get-current-project
  586. []
  587. (when-let [repo (get-current-repo)]
  588. (let [projects (:projects (get-me))
  589. project (:name (first (filter (fn [p] (= (:repo p) repo)) projects)))]
  590. (when-not (string/blank? project)
  591. project))))
  592. (defn set-indexedb-support?
  593. [value]
  594. (set-state! :indexeddb/support? value))
  595. (defn set-modal!
  596. [modal-panel-content]
  597. (swap! state assoc
  598. :modal/show? true
  599. :modal/panel-content modal-panel-content))
  600. (defn close-modal!
  601. []
  602. (swap! state assoc
  603. :modal/show? false
  604. :modal/panel-content nil))
  605. (defn get-journal-basis
  606. []
  607. (or
  608. (when-let [repo (get-current-repo)]
  609. (when-let [basis (get-in @state [:config repo :journal-basis])]
  610. (keyword (string/lower-case (str basis)))))
  611. :monthly))
  612. (defn update-repo-last-stored-at!
  613. [repo]
  614. (swap! state assoc-in [:repo/persist-status repo :last-stored-at] (util/time-ms)))
  615. (defn get-repo-persist-status
  616. []
  617. (:repo/persist-status @state))
  618. (defn mark-repo-as-changed!
  619. [repo _tx-id]
  620. (swap! state assoc-in [:repo/persist-status repo :last-modified-at] (util/time-ms)))
  621. (defn add-tx!
  622. ;; TODO: replace f with data for batch transactions
  623. [f]
  624. (when f
  625. (swap! state update :db/batch-txs (fn [chan]
  626. (async/put! chan f)
  627. chan))))
  628. (defn get-db-batch-txs-chan
  629. []
  630. (:db/batch-txs @state))
  631. (defn repos-need-to-be-stored?
  632. []
  633. (let [status (vals (get-repo-persist-status))]
  634. (some (fn [{:keys [last-stored-at last-modified-at]}]
  635. (> last-modified-at last-stored-at))
  636. status)))
  637. (defn get-left-sidebar-open
  638. []
  639. (get-in @state [:ui/left-sidebar-open?]))
  640. (defn set-left-sidebar-open!
  641. [value]
  642. (set-state! :ui/left-sidebar-open? value))
  643. (defn set-daily-migrating!
  644. [value]
  645. (set-state! :daily/migrating? value))
  646. (defn set-developer-mode!
  647. [value]
  648. (set-state! :ui/developer-mode? value)
  649. (storage/set "developer-mode" (str value)))
  650. (defn get-notification-contents
  651. []
  652. (get-in @state [:notification/contents]))
  653. (defn get-new-block-shortcut
  654. []
  655. (let [shortcut (get-in @state [:shortcuts :editor/new-block])]
  656. (if (and shortcut (contains? #{"enter" "alt+enter"} (string/lower-case shortcut)))
  657. shortcut
  658. "enter")))
  659. (defn set-new-block-shortcut!
  660. [value]
  661. (set-state! [:shortcuts :editor/new-block] value))
  662. (defn toggle-new-block-shortcut!
  663. []
  664. (if-let [enter? (= "enter" (get-new-block-shortcut))]
  665. (set-new-block-shortcut! "alt+enter")
  666. (set-new-block-shortcut! "enter")))
  667. (defn set-config!
  668. [repo-url value]
  669. (set-state! [:config repo-url] value)
  670. (set-new-block-shortcut!
  671. (or (get-shortcut repo-url :editor/new-block)
  672. "enter")))
  673. (defn git-auto-push?
  674. []
  675. (true? (:git-auto-push (get-config (get-current-repo)))))
  676. (defn set-changed-files!
  677. [repo changed-files]
  678. (set-state! [:repo/changed-files repo] changed-files))
  679. (defn get-changed-files
  680. []
  681. (get-in @state [:repo/changed-files (get-current-repo)]))