state.cljs 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721
  1. (ns frontend.state
  2. (:require [cljs-bean.core :as bean]
  3. [cljs.core.async :as async]
  4. [clojure.string :as string]
  5. [cljs.spec.alpha :as s]
  6. [dommy.core :as dom]
  7. [medley.core :as medley]
  8. [electron.ipc :as ipc]
  9. [frontend.storage :as storage]
  10. [frontend.util :as util]
  11. [frontend.util.cursor :as cursor]
  12. [goog.dom :as gdom]
  13. [goog.object :as gobj]
  14. [promesa.core :as p]
  15. [rum.core :as rum]
  16. [logseq.graph-parser.config :as gp-config]
  17. [frontend.mobile.util :as mobile-util]))
  18. (defonce ^:large-vars/data-var state
  19. (let [document-mode? (or (storage/get :document/mode?) false)
  20. current-graph (let [graph (storage/get :git/current-repo)]
  21. (when graph (ipc/ipc "setCurrentGraph" graph))
  22. graph)]
  23. (atom
  24. {:route-match nil
  25. :today nil
  26. :system/events (async/chan 100)
  27. :db/batch-txs (async/chan 100)
  28. :file/writes (async/chan 100)
  29. :file/unlinked-dirs #{}
  30. :reactive/custom-queries (async/chan 100)
  31. :notification/show? false
  32. :notification/content nil
  33. :repo/loading-files? {}
  34. :nfs/user-granted? {}
  35. :nfs/refreshing? nil
  36. :instrument/disabled? (storage/get "instrument-disabled")
  37. ;; TODO: how to detect the network reliably?
  38. :network/online? true
  39. :indexeddb/support? true
  40. :me nil
  41. :git/current-repo current-graph
  42. :format/loading {}
  43. :draw? false
  44. :db/restoring? nil
  45. :journals-length 3
  46. :search/q ""
  47. :search/mode :global
  48. :search/result nil
  49. :search/graph-filters []
  50. ;; modals
  51. :modal/id nil
  52. :modal/label ""
  53. :modal/show? false
  54. :modal/panel-content nil
  55. :modal/fullscreen? false
  56. :modal/close-btn? nil
  57. :modal/subsets []
  58. ;; right sidebar
  59. :ui/fullscreen? false
  60. :ui/settings-open? false
  61. :ui/sidebar-open? false
  62. :ui/left-sidebar-open? (boolean (storage/get "ls-left-sidebar-open?"))
  63. :ui/theme (or (storage/get :ui/theme) "light")
  64. :ui/system-theme? ((fnil identity (or util/mac? util/win32? false)) (storage/get :ui/system-theme?))
  65. :ui/custom-theme (or (storage/get :ui/custom-theme) {:light {:mode "light"} :dark {:mode "dark"}})
  66. :ui/wide-mode? (storage/get :ui/wide-mode)
  67. ;; ui/collapsed-blocks is to separate the collapse/expand state from db for:
  68. ;; 1. right sidebar
  69. ;; 2. zoom-in view
  70. ;; 3. queries
  71. ;; 4. references
  72. ;; graph => {:block-id bool}
  73. :ui/collapsed-blocks {}
  74. :ui/sidebar-collapsed-blocks {}
  75. :ui/root-component nil
  76. :ui/file-component nil
  77. :ui/custom-query-components {}
  78. :ui/show-recent? false
  79. :ui/command-palette-open? false
  80. :ui/developer-mode? (or (= (storage/get "developer-mode") "true")
  81. false)
  82. ;; remember scroll positions of visited paths
  83. :ui/paths-scroll-positions {}
  84. :ui/shortcut-tooltip? (if (false? (storage/get :ui/shortcut-tooltip?))
  85. false
  86. true)
  87. :ui/scrolling? false
  88. :document/mode? document-mode?
  89. :config {}
  90. :block/component-editing-mode? false
  91. :editor/draw-mode? false
  92. :editor/action nil
  93. :editor/action-data nil
  94. ;; With label or other data
  95. :editor/last-saved-cursor nil
  96. :editor/editing? nil
  97. :editor/in-composition? false
  98. :editor/content {}
  99. :editor/block nil
  100. :editor/block-dom-id nil
  101. :editor/set-timestamp-block nil
  102. :editor/last-input-time nil
  103. :editor/document-mode? document-mode?
  104. :editor/args nil
  105. :editor/on-paste? false
  106. :editor/last-key-code nil
  107. ;; for audio record
  108. :editor/record-status "NONE"
  109. :db/last-transact-time {}
  110. ;; whether database is persisted
  111. :db/persisted? {}
  112. :cursor-range nil
  113. :selection/mode false
  114. ;; Warning: blocks order is determined when setting this attribute
  115. :selection/blocks []
  116. :selection/start-block nil
  117. ;; either :up or :down, defaults to down
  118. ;; used to determine selection direction when two or more blocks are selected
  119. :selection/direction :down
  120. :custom-context-menu/show? false
  121. :custom-context-menu/links nil
  122. ;; pages or blocks in the right sidebar
  123. ;; It is a list of `[repo db-id block-type block-data]` 4-tuple
  124. :sidebar/blocks '()
  125. :preferred-language (storage/get :preferred-language)
  126. ;; electron
  127. :electron/auto-updater-downloaded false
  128. :electron/updater-pending? false
  129. :electron/updater {}
  130. :electron/user-cfgs nil
  131. ;; mobile
  132. :mobile/show-action-bar? false
  133. :mobile/actioned-block nil
  134. :mobile/show-toolbar? false
  135. :mobile/show-recording-bar? false
  136. ;;; toolbar icon doesn't update correctly when clicking after separate it from box,
  137. ;;; add a random in (<= 1000000) to observer its update
  138. :mobile/toolbar-update-observer 0
  139. :mobile/show-tabbar? false
  140. ;; plugin
  141. :plugin/enabled (and (util/electron?)
  142. ;; true false :theme-only
  143. ((fnil identity true) (storage/get :lsp-core-enabled)))
  144. :plugin/preferences nil
  145. :plugin/indicator-text nil
  146. :plugin/installed-plugins {}
  147. :plugin/installed-themes []
  148. :plugin/installed-slash-commands {}
  149. :plugin/installed-ui-items {}
  150. :plugin/installed-resources {}
  151. :plugin/installed-hooks {}
  152. :plugin/simple-commands {}
  153. :plugin/selected-theme nil
  154. :plugin/selected-unpacked-pkg nil
  155. :plugin/marketplace-pkgs nil
  156. :plugin/marketplace-stats nil
  157. :plugin/installing nil
  158. :plugin/active-readme nil
  159. :plugin/updates-pending {}
  160. :plugin/updates-coming {}
  161. :plugin/updates-downloading? false
  162. :plugin/updates-unchecked #{}
  163. :plugin/navs-settings? true
  164. :plugin/focused-settings nil ;; plugin id
  165. ;; pdf
  166. :pdf/current nil
  167. :pdf/ref-highlight nil
  168. ;; all notification contents as k-v pairs
  169. :notification/contents {}
  170. :graph/syncing? false
  171. ;; graph -> state
  172. :graph/parsing-state {}
  173. ;; copied blocks
  174. :copy/blocks {:copy/content nil
  175. :copy/graph nil
  176. :copy/blocks nil}
  177. :copy/export-block-text-indent-style (or (storage/get :copy/export-block-text-indent-style)
  178. "dashes")
  179. :copy/export-block-text-remove-options (or (storage/get :copy/export-block-text-remove-options)
  180. #{})
  181. :date-picker/date nil
  182. :youtube/players {}
  183. ;; command palette
  184. :command-palette/commands []
  185. :view/components {}
  186. :favorites/dragging nil
  187. :srs/mode? false
  188. :srs/cards-due-count nil
  189. :reactive/query-dbs {}
  190. ;; login, userinfo, token, ...
  191. :auth/refresh-token nil
  192. :auth/access-token nil
  193. :auth/id-token nil
  194. ;; file-sync
  195. :file-sync/sync-manager nil
  196. :file-sync/sync-state-manager nil
  197. :file-sync/sync-state nil
  198. :file-sync/sync-uploading-files nil
  199. :file-sync/sync-downloading-files nil
  200. :file-sync/download-init-progress nil
  201. :encryption/graph-parsing? false
  202. })))
  203. ;; block uuid -> {content(String) -> ast}
  204. (def blocks-ast-cache (atom {}))
  205. (defn add-block-ast-cache!
  206. [block-uuid content ast]
  207. (when (and block-uuid content ast)
  208. (let [new-value (assoc-in @blocks-ast-cache [block-uuid content] ast)
  209. new-value (if (> (count new-value) 10000)
  210. (into {} (take 5000 new-value))
  211. new-value)]
  212. (reset! blocks-ast-cache new-value))))
  213. (defn get-block-ast
  214. [block-uuid content]
  215. (when (and block-uuid content)
  216. (get-in @blocks-ast-cache [block-uuid content])))
  217. (defn sub
  218. [ks]
  219. (if (coll? ks)
  220. (util/react (rum/cursor-in state ks))
  221. (util/react (rum/cursor state ks))))
  222. (defn get-route-match
  223. []
  224. (:route-match @state))
  225. (defn get-current-route
  226. []
  227. (get-in (get-route-match) [:data :name]))
  228. (defn home?
  229. []
  230. (= :home (get-current-route)))
  231. (defn setups-picker?
  232. []
  233. (= :repo-add (get-current-route)))
  234. (defn get-current-page
  235. []
  236. (when (= :page (get-current-route))
  237. (get-in (get-route-match)
  238. [:path-params :name])))
  239. (defn route-has-p?
  240. []
  241. (get-in (get-route-match) [:query-params :p]))
  242. (defn set-state!
  243. [path value]
  244. (if (vector? path)
  245. (swap! state assoc-in path value)
  246. (swap! state assoc path value)))
  247. (defn update-state!
  248. [path f]
  249. (if (vector? path)
  250. (swap! state update-in path f)
  251. (swap! state update path f)))
  252. (defn get-current-repo
  253. []
  254. (or (:git/current-repo @state)
  255. (when-not (mobile-util/native-platform?)
  256. "local")))
  257. (defn get-config
  258. ([]
  259. (get-config (get-current-repo)))
  260. ([repo-url]
  261. (get-in @state [:config repo-url])))
  262. (def default-arweave-gateway "https://arweave.net")
  263. (defn get-arweave-gateway
  264. []
  265. (:arweave/gateway (get-config) default-arweave-gateway))
  266. (defonce built-in-macros
  267. {"img" "[:img.$4 {:src \"$1\" :style {:width $2 :height $3}}]"})
  268. (defn get-macros
  269. []
  270. (merge
  271. built-in-macros
  272. (:macros (get-config))))
  273. (defn sub-config
  274. []
  275. (sub :config))
  276. (defn get-custom-css-link
  277. []
  278. (:custom-css-url (get-config)))
  279. (defn get-custom-js-link
  280. []
  281. (:custom-js-url (get-config)))
  282. (defn get-default-journal-template
  283. []
  284. (when-let [template (get-in (get-config) [:default-templates :journals])]
  285. (when-not (string/blank? template)
  286. (string/trim template))))
  287. (defn all-pages-public?
  288. []
  289. (let [value (:publishing/all-pages-public? (get-config))
  290. value (if (some? value) value (:all-pages-public? (get-config)))]
  291. (true? value)))
  292. (defn enable-grammarly?
  293. []
  294. (true? (:feature/enable-grammarly?
  295. (get (sub-config) (get-current-repo)))))
  296. ;; (defn store-block-id-in-file?
  297. ;; []
  298. ;; (true? (:block/store-id-in-file? (get-config))))
  299. (defn scheduled-deadlines-disabled?
  300. []
  301. (true? (:feature/disable-scheduled-and-deadline-query?
  302. (get (sub-config) (get-current-repo)))))
  303. (defn enable-timetracking?
  304. []
  305. (not (false? (:feature/enable-timetracking?
  306. (get (sub-config) (get-current-repo))))))
  307. (defn enable-journals?
  308. [repo]
  309. (not (false? (:feature/enable-journals?
  310. (get (sub-config) repo)))))
  311. (defn enable-flashcards?
  312. [repo]
  313. (not (false? (:feature/enable-flashcards?
  314. (get (sub-config) repo)))))
  315. (defn export-heading-to-list?
  316. []
  317. (not (false? (:export/heading-to-list?
  318. (get (sub-config) (get-current-repo))))))
  319. (defn enable-git-auto-push?
  320. [repo]
  321. (not (false? (:git-auto-push
  322. (get (sub-config) repo)))))
  323. (defn enable-block-timestamps?
  324. []
  325. (true? (:feature/enable-block-timestamps?
  326. (get (sub-config) (get-current-repo)))))
  327. (defn sub-graph-config
  328. []
  329. (get (sub-config) (get-current-repo)))
  330. (defn sub-graph-config-settings
  331. []
  332. (:graph/settings (sub-graph-config)))
  333. ;; Enable by default
  334. (defn show-brackets?
  335. []
  336. (not (false? (:ui/show-brackets?
  337. (get (sub-config) (get-current-repo))))))
  338. (defn get-default-home
  339. []
  340. (:default-home (get-config)))
  341. (defn sub-default-home-page
  342. []
  343. (get-in (sub-config) [(get-current-repo) :default-home :page] ""))
  344. (defn custom-home-page?
  345. []
  346. (some? (:page (get-default-home))))
  347. (defn get-preferred-format
  348. ([]
  349. (get-preferred-format (get-current-repo)))
  350. ([repo-url]
  351. (keyword
  352. (or
  353. (when-let [fmt (:preferred-format (get-config repo-url))]
  354. (string/lower-case (name fmt)))
  355. (get-in @state [:me :preferred_format] "markdown")))))
  356. ;; TODO: consider adding a pane in Settings to set this through the GUI (rather
  357. ;; than having to go through the config.edn file)
  358. (defn get-editor-command-trigger
  359. ([] (get-editor-command-trigger (get-current-repo)))
  360. ([repo-url]
  361. (or
  362. (:editor/command-trigger (get-config repo-url)) ;; Get from user config
  363. "/"))) ;; Set the default
  364. (defn markdown?
  365. []
  366. (= (keyword (get-preferred-format))
  367. :markdown))
  368. (defn get-pages-directory
  369. []
  370. (or
  371. (when-let [repo (get-current-repo)]
  372. (:pages-directory (get-config repo)))
  373. "pages"))
  374. (defn get-journals-directory
  375. []
  376. (or
  377. (when-let [repo (get-current-repo)]
  378. (:journals-directory (get-config repo)))
  379. "journals"))
  380. (defn org-mode-file-link?
  381. [repo]
  382. (:org-mode/insert-file-link? (get-config repo)))
  383. (defn get-journal-file-name-format
  384. []
  385. (when-let [repo (get-current-repo)]
  386. (:journal/file-name-format (get-config repo))))
  387. (defn get-preferred-workflow
  388. []
  389. (keyword
  390. (or
  391. (when-let [workflow (:preferred-workflow (get-config))]
  392. (let [workflow (name workflow)]
  393. (if (util/safe-re-find #"now|NOW" workflow)
  394. :now
  395. :todo)))
  396. (get-in @state [:me :preferred_workflow] :now))))
  397. (defn get-preferred-todo
  398. []
  399. (if (= (get-preferred-workflow) :now)
  400. "LATER"
  401. "TODO"))
  402. (defn page-name-order
  403. "Decide whether to use file name or :title as page name. If it returns \"file\", use the file
  404. name unless it is missing."
  405. []
  406. (:page-name-order (get-config)))
  407. (defn get-repos
  408. []
  409. (get-in @state [:me :repos]))
  410. (defn set-repos!
  411. [repos]
  412. (set-state! [:me :repos] repos))
  413. (defn add-repo!
  414. [repo]
  415. (when (not (string/blank? repo))
  416. (update-state! [:me :repos]
  417. (fn [repos]
  418. (->> (conj repos repo)
  419. (distinct))))))
  420. (defn set-current-repo!
  421. [repo]
  422. (swap! state assoc :git/current-repo repo)
  423. (if repo
  424. (storage/set :git/current-repo repo)
  425. (storage/remove :git/current-repo))
  426. (ipc/ipc "setCurrentGraph" repo))
  427. (defn set-preferred-format!
  428. [format]
  429. (swap! state assoc-in [:me :preferred_format] (name format)))
  430. (defn set-preferred-workflow!
  431. [workflow]
  432. (swap! state assoc-in [:me :preferred_workflow] (name workflow)))
  433. (defn set-preferred-language!
  434. [language]
  435. (set-state! :preferred-language (name language))
  436. (storage/set :preferred-language (name language)))
  437. (defn delete-repo!
  438. [repo]
  439. (swap! state update-in [:me :repos]
  440. (fn [repos]
  441. (->> (remove #(= (:url repo)
  442. (:url %))
  443. repos)
  444. (util/distinct-by :url)))))
  445. (defn set-timestamp-block!
  446. [value]
  447. (set-state! :editor/set-timestamp-block value))
  448. (defn get-timestamp-block
  449. []
  450. (:editor/set-timestamp-block @state))
  451. (defn set-edit-content!
  452. ([input-id value] (set-edit-content! input-id value true))
  453. ([input-id value set-input-value?]
  454. (when input-id
  455. (when set-input-value?
  456. (when-let [input (gdom/getElement input-id)]
  457. (util/set-change-value input value)))
  458. (update-state! :editor/content (fn [m]
  459. (assoc m input-id value))))))
  460. (defn get-edit-input-id
  461. []
  462. (ffirst (:editor/editing? @state)))
  463. (defn get-input
  464. []
  465. (when-let [id (get-edit-input-id)]
  466. (gdom/getElement id)))
  467. (defn editing?
  468. []
  469. (let [input (get-input)]
  470. (and input (= input (.-activeElement js/document)))))
  471. (defn get-edit-content
  472. []
  473. (get (:editor/content @state) (get-edit-input-id)))
  474. (defn sub-edit-content
  475. []
  476. (sub [:editor/content (get-edit-input-id)]))
  477. (defn get-cursor-range
  478. []
  479. (:cursor-range @state))
  480. (defn set-cursor-range!
  481. [range]
  482. (set-state! :cursor-range range))
  483. (defn set-q!
  484. [value]
  485. (set-state! :search/q value))
  486. (defn set-search-mode!
  487. [value]
  488. (set-state! :search/mode value))
  489. (defn set-editor-action!
  490. [value]
  491. (set-state! :editor/action value))
  492. (defn set-editor-action-data!
  493. [value]
  494. (set-state! :editor/action-data value))
  495. (defn get-editor-action
  496. []
  497. (:editor/action @state))
  498. (defn get-editor-action-data
  499. []
  500. (:editor/action-data @state))
  501. (defn set-editor-show-page-search!
  502. [value]
  503. (set-editor-action! (when value :page-search)))
  504. (defn get-editor-show-page-search?
  505. []
  506. (= (get-editor-action) :page-search))
  507. (defn set-editor-show-page-search-hashtag!
  508. [value]
  509. (set-editor-action! (when value :page-search-hashtag)))
  510. (defn get-editor-show-page-search-hashtag?
  511. []
  512. (= (get-editor-action) :page-search-hashtag))
  513. (defn set-editor-show-block-search!
  514. [value]
  515. (set-editor-action! (when value :block-search)))
  516. (defn get-editor-show-block-search?
  517. []
  518. (= (get-editor-action) :block-search))
  519. (defn set-editor-show-template-search!
  520. [value]
  521. (set-editor-action! (when value :template-search)))
  522. (defn get-editor-show-template-search?
  523. []
  524. (= (get-editor-action) :template-search))
  525. (defn set-editor-show-date-picker!
  526. [value]
  527. (set-editor-action! (when value :datepicker)))
  528. (defn get-editor-show-date-picker?
  529. []
  530. (= (get-editor-action) :datepicker))
  531. (defn set-editor-show-input!
  532. [value]
  533. (if value
  534. (do
  535. (set-editor-action-data! (assoc (get-editor-action-data) :options value))
  536. (set-editor-action! :input))
  537. (do
  538. (set-editor-action! nil)
  539. (set-editor-action-data! nil))))
  540. (defn get-editor-show-input
  541. []
  542. (when (= (get-editor-action) :input)
  543. (get @state :editor/action-data)))
  544. (defn set-editor-show-commands!
  545. []
  546. (when-not (get-editor-action) (set-editor-action! :commands)))
  547. (defn set-editor-show-block-commands!
  548. []
  549. (when-not (get-editor-action) (set-editor-action! :block-commands)))
  550. (defn set-editor-show-zotero!
  551. [value]
  552. (set-state! :editor/show-zotero value))
  553. (defn clear-editor-action!
  554. []
  555. (swap! state (fn [state]
  556. (assoc state :editor/action nil))))
  557. (defn set-edit-input-id!
  558. [input-id]
  559. (swap! state update :editor/editing?
  560. (fn [_m]
  561. (and input-id {input-id true}))))
  562. (defn get-edit-pos
  563. []
  564. (when-let [input (get-input)]
  565. (util/get-selection-start input)))
  566. (defn set-selection-start-block!
  567. [start-block]
  568. (swap! state assoc :selection/start-block start-block))
  569. (defn get-selection-start-block
  570. []
  571. (get @state :selection/start-block))
  572. (defn set-selection-blocks!
  573. ([blocks]
  574. (set-selection-blocks! blocks :down))
  575. ([blocks direction]
  576. (when (seq blocks)
  577. (let [blocks (util/sort-by-height blocks)]
  578. (swap! state assoc
  579. :selection/mode true
  580. :selection/blocks blocks
  581. :selection/direction direction)))))
  582. (defn into-selection-mode!
  583. []
  584. (swap! state assoc :selection/mode true))
  585. (defn clear-selection!
  586. []
  587. (swap! state assoc
  588. :selection/mode false
  589. :selection/blocks nil
  590. :selection/direction :down))
  591. (defn get-selection-blocks
  592. []
  593. (:selection/blocks @state))
  594. (defn get-selection-block-ids
  595. []
  596. (->> (sub :selection/blocks)
  597. (keep #(when-let [id (dom/attr % "blockid")]
  598. (uuid id)))
  599. (distinct)))
  600. (defn get-selection-start-block-or-first
  601. []
  602. (or (get-selection-start-block)
  603. (some-> (first (get-selection-blocks))
  604. (gobj/get "id"))))
  605. (defn in-selection-mode?
  606. []
  607. (:selection/mode @state))
  608. (defn selection?
  609. "True sense of selection mode with valid selected block"
  610. []
  611. (and (in-selection-mode?) (seq (get-selection-blocks))))
  612. (defn conj-selection-block!
  613. [block direction]
  614. (dom/add-class! block "selected noselect")
  615. (swap! state assoc
  616. :selection/mode true
  617. :selection/blocks (-> (conj (vec (:selection/blocks @state)) block)
  618. (util/sort-by-height))
  619. :selection/direction direction))
  620. (defn drop-last-selection-block!
  621. []
  622. (let [last-block (peek (vec (:selection/blocks @state)))]
  623. (swap! state assoc
  624. :selection/mode true
  625. :selection/blocks (pop (vec (:selection/blocks @state))))
  626. last-block))
  627. (defn get-selection-direction
  628. []
  629. (:selection/direction @state))
  630. (defn show-custom-context-menu!
  631. [links]
  632. (swap! state assoc
  633. :custom-context-menu/show? true
  634. :custom-context-menu/links links))
  635. (defn hide-custom-context-menu!
  636. []
  637. (swap! state assoc
  638. :custom-context-menu/show? false
  639. :custom-context-menu/links nil))
  640. (defn toggle-sidebar-open?!
  641. []
  642. (swap! state update :ui/sidebar-open? not))
  643. (defn open-right-sidebar!
  644. []
  645. (swap! state assoc :ui/sidebar-open? true))
  646. (defn hide-right-sidebar!
  647. []
  648. (swap! state assoc :ui/sidebar-open? false))
  649. (defn sidebar-add-block!
  650. [repo db-id block-type]
  651. (when (not (util/sm-breakpoint?))
  652. (when db-id
  653. (update-state! :sidebar/blocks (fn [blocks]
  654. (->> (remove #(= (second %) db-id) blocks)
  655. (cons [repo db-id block-type])
  656. (distinct))))
  657. (open-right-sidebar!)
  658. (when-let [elem (gdom/getElementByClass "cp__right-sidebar-scrollable")]
  659. (util/scroll-to elem 0)))))
  660. (defn sidebar-remove-block!
  661. [idx]
  662. (update-state! :sidebar/blocks (fn [blocks]
  663. (if (string? idx)
  664. (remove #(= (second %) idx) blocks)
  665. (util/drop-nth idx blocks))))
  666. (when (empty? (:sidebar/blocks @state))
  667. (hide-right-sidebar!)))
  668. (defn sidebar-replace-block!
  669. [old-sidebar-key new-sidebar-key]
  670. (update-state! :sidebar/blocks (fn [blocks]
  671. (map #(if (= % old-sidebar-key)
  672. new-sidebar-key
  673. %) blocks))))
  674. (defn sidebar-block-exists?
  675. [idx]
  676. (some #(= (second %) idx) (:sidebar/blocks @state)))
  677. (defn clear-sidebar-blocks!
  678. []
  679. (set-state! :sidebar/blocks '()))
  680. (defn sidebar-block-toggle-collapse!
  681. [db-id]
  682. (when db-id
  683. (update-state! [:ui/sidebar-collapsed-blocks db-id] not)))
  684. (defn get-edit-block
  685. []
  686. (get @state :editor/block))
  687. (defn get-current-edit-block-and-position
  688. []
  689. (let [edit-input-id (get-edit-input-id)
  690. edit-block (get-edit-block)
  691. block-element (when edit-input-id (gdom/getElement (string/replace edit-input-id "edit-block" "ls-block")))
  692. container (when block-element
  693. (util/get-block-container block-element))]
  694. (when container
  695. {:last-edit-block edit-block
  696. :container (gobj/get container "id")
  697. :pos (cursor/pos (gdom/getElement edit-input-id))})))
  698. (defonce publishing? (atom nil))
  699. (defn publishing-enable-editing?
  700. []
  701. (and @publishing? (:publishing/enable-editing? (get-config))))
  702. (defn enable-editing?
  703. []
  704. (or (not @publishing?) (:publishing/enable-editing? (get-config))))
  705. (defn set-editing!
  706. ([edit-input-id content block cursor-range]
  707. (set-editing! edit-input-id content block cursor-range true))
  708. ([edit-input-id content block cursor-range move-cursor?]
  709. (when (and edit-input-id block
  710. (or
  711. (publishing-enable-editing?)
  712. (not @publishing?)))
  713. (let [block-element (gdom/getElement (string/replace edit-input-id "edit-block" "ls-block"))
  714. container (util/get-block-container block-element)
  715. block (if container
  716. (assoc block
  717. :block/container (gobj/get container "id"))
  718. block)
  719. content (string/trim (or content ""))]
  720. (swap! state
  721. (fn [state]
  722. (-> state
  723. (assoc-in [:editor/content edit-input-id] content)
  724. (assoc
  725. :editor/block block
  726. :editor/editing? {edit-input-id true}
  727. :editor/last-key-code nil
  728. :cursor-range cursor-range))))
  729. (when-let [input (gdom/getElement edit-input-id)]
  730. (let [pos (count cursor-range)]
  731. (when content
  732. (util/set-change-value input content))
  733. (when move-cursor?
  734. (cursor/move-cursor-to input pos))
  735. (when (or (util/mobile?) (mobile-util/native-platform?))
  736. (set-state! :mobile/show-action-bar? false))))))))
  737. (defn clear-edit!
  738. []
  739. (swap! state merge {:editor/editing? nil
  740. :editor/block nil
  741. :cursor-range nil
  742. :editor/last-saved-cursor nil}))
  743. (defn into-code-editor-mode!
  744. []
  745. (swap! state merge {:editor/editing? nil
  746. :cursor-range nil
  747. :editor/code-mode? true}))
  748. (defn set-editor-last-pos!
  749. [new-pos]
  750. (set-state! [:editor/last-saved-cursor (:block/uuid (get-edit-block))] new-pos))
  751. (defn clear-editor-last-pos!
  752. []
  753. (set-state! :editor/last-saved-cursor nil))
  754. (defn get-editor-last-pos
  755. []
  756. (get-in @state [:editor/last-saved-cursor (:block/uuid (get-edit-block))]))
  757. (defn set-block-content-and-last-pos!
  758. [edit-input-id content new-pos]
  759. (when edit-input-id
  760. (set-edit-content! edit-input-id content)
  761. (set-state! [:editor/last-saved-cursor (:block/uuid (get-edit-block))] new-pos)))
  762. (defn set-theme-mode!
  763. [mode]
  764. (when (mobile-util/native-ios?)
  765. (if (= mode "light")
  766. (util/set-theme-light)
  767. (util/set-theme-dark)))
  768. (set-state! :ui/theme mode)
  769. (storage/set :ui/theme mode))
  770. (defn sync-system-theme!
  771. []
  772. (let [system-dark? (.-matches (js/window.matchMedia "(prefers-color-scheme: dark)"))]
  773. (set-theme-mode! (if system-dark? "dark" "light"))
  774. (set-state! :ui/system-theme? true)
  775. (storage/set :ui/system-theme? true)))
  776. (defn use-theme-mode!
  777. [theme-mode]
  778. (if (= theme-mode "system")
  779. (sync-system-theme!)
  780. (do
  781. (set-theme-mode! theme-mode)
  782. (set-state! :ui/system-theme? false)
  783. (storage/set :ui/system-theme? false))))
  784. (defn toggle-theme
  785. [theme]
  786. (if (= theme "dark") "light" "dark"))
  787. (defn toggle-theme!
  788. []
  789. (use-theme-mode! (toggle-theme (:ui/theme @state))))
  790. (defn set-custom-theme!
  791. ([custom-theme]
  792. (set-custom-theme! nil custom-theme))
  793. ([mode theme]
  794. (set-state! (if mode [:ui/custom-theme (keyword mode)] :ui/custom-theme) theme)
  795. (storage/set :ui/custom-theme (:ui/custom-theme @state))))
  796. (defn set-editing-block-dom-id!
  797. [block-dom-id]
  798. (set-state! :editor/block-dom-id block-dom-id))
  799. (defn get-editing-block-dom-id
  800. []
  801. (:editor/block-dom-id @state))
  802. (defn set-root-component!
  803. [component]
  804. (set-state! :ui/root-component component))
  805. (defn get-root-component
  806. []
  807. (get @state :ui/root-component))
  808. (defn load-app-user-cfgs
  809. ([] (load-app-user-cfgs false))
  810. ([refresh?]
  811. (p/let [cfgs (if (or refresh? (nil? (:electron/user-cfgs @state)))
  812. (ipc/ipc "userAppCfgs")
  813. (:electron/user-cfgs @state))
  814. cfgs (if (object? cfgs) (bean/->clj cfgs) cfgs)]
  815. (set-state! :electron/user-cfgs cfgs))))
  816. (defn setup-electron-updater!
  817. []
  818. (when (util/electron?)
  819. (js/window.apis.setUpdatesCallback
  820. (fn [_ args]
  821. (let [data (bean/->clj args)
  822. pending? (not= (:type data) "completed")]
  823. (set-state! :electron/updater-pending? pending?)
  824. (when pending? (set-state! :electron/updater data))
  825. nil)))))
  826. (defn set-file-component!
  827. [component]
  828. (set-state! :ui/file-component component))
  829. (defn clear-file-component!
  830. []
  831. (set-state! :ui/file-component nil))
  832. (defn get-file-component
  833. []
  834. (get @state :ui/file-component))
  835. (defn set-journals-length!
  836. [value]
  837. (when value
  838. (set-state! :journals-length value)))
  839. (defn add-custom-query-component!
  840. [query-string component]
  841. (update-state! :ui/custom-query-components
  842. (fn [m]
  843. (assoc m query-string component))))
  844. (defn remove-custom-query-component!
  845. [query-string]
  846. (update-state! :ui/custom-query-components
  847. (fn [m]
  848. (dissoc m query-string))))
  849. (defn get-custom-query-components
  850. []
  851. (vals (get @state :ui/custom-query-components)))
  852. (defn save-scroll-position!
  853. ([value]
  854. (save-scroll-position! value js/window.location.hash))
  855. ([value path]
  856. (set-state! [:ui/paths-scroll-positions path] value)))
  857. (defn get-saved-scroll-position
  858. ([]
  859. (get-saved-scroll-position js/window.location.hash))
  860. ([path]
  861. (get-in @state [:ui/paths-scroll-positions path] 0)))
  862. (defn set-today!
  863. [value]
  864. (set-state! :today value))
  865. (defn get-date-formatter
  866. []
  867. (gp-config/get-date-formatter (get-config)))
  868. (defn shortcuts []
  869. (get-in @state [:config (get-current-repo) :shortcuts]))
  870. (defn get-me
  871. []
  872. (:me @state))
  873. (defn deprecated-logged?
  874. "Whether the user has logged in."
  875. []
  876. false)
  877. (defn set-db-restoring!
  878. [value]
  879. (set-state! :db/restoring? value))
  880. (defn set-indexedb-support!
  881. [value]
  882. (set-state! :indexeddb/support? value))
  883. (defn modal-opened?
  884. []
  885. (:modal/show? @state))
  886. (declare set-modal!)
  887. (declare close-modal!)
  888. (defn get-sub-modals
  889. []
  890. (:modal/subsets @state))
  891. (defn set-sub-modal!
  892. ([panel-content]
  893. (set-sub-modal! panel-content
  894. {:close-btn? true}))
  895. ([panel-content {:keys [id label close-btn? show? center?] :as opts}]
  896. (if (not (modal-opened?))
  897. (set-modal! panel-content opts)
  898. (let [modals (:modal/subsets @state)
  899. idx (and id (first (keep-indexed #(when (= (:modal/id %2) id) %1)
  900. modals)))
  901. input (medley/filter-vals
  902. #(not (nil? %1))
  903. {:modal/id id
  904. :modal/label (or label (if center? "ls-modal-align-center" ""))
  905. :modal/show? (if (boolean? show?) show? true)
  906. :modal/panel-content panel-content
  907. :modal/close-btn? close-btn?})]
  908. (swap! state update-in
  909. [:modal/subsets (or idx (count modals))]
  910. merge input)
  911. (:modal/subsets @state)))))
  912. (defn close-sub-modal!
  913. ([] (close-sub-modal! nil))
  914. ([all?-a-id]
  915. (if (true? all?-a-id)
  916. (swap! state assoc :modal/subsets [])
  917. (let [id all?-a-id
  918. mid (:modal/id @state)
  919. modals (:modal/subsets @state)]
  920. (if (and id (not (string/blank? mid)) (= id mid))
  921. (close-modal!)
  922. (when-let [idx (if id (first (keep-indexed #(when (= (:modal/id %2) id) %1) modals))
  923. (dec (count modals)))]
  924. (swap! state assoc :modal/subsets (into [] (medley/remove-nth idx modals)))))))
  925. (:modal/subsets @state)))
  926. (defn set-modal!
  927. ([modal-panel-content]
  928. (set-modal! modal-panel-content
  929. {:fullscreen? false
  930. :close-btn? true}))
  931. ([modal-panel-content {:keys [id label fullscreen? close-btn? center?]}]
  932. (when (seq (get-sub-modals))
  933. (close-sub-modal! true))
  934. (swap! state assoc
  935. :modal/id id
  936. :modal/label (or label (if center? "ls-modal-align-center" ""))
  937. :modal/show? (boolean modal-panel-content)
  938. :modal/panel-content modal-panel-content
  939. :modal/fullscreen? fullscreen?
  940. :modal/close-btn? close-btn?)))
  941. (defn close-modal!
  942. []
  943. (if (seq (get-sub-modals))
  944. (close-sub-modal!)
  945. (swap! state assoc
  946. :modal/id nil
  947. :modal/label ""
  948. :modal/show? false
  949. :modal/fullscreen? false
  950. :modal/panel-content nil
  951. :ui/open-select nil)))
  952. (defn get-db-batch-txs-chan
  953. []
  954. (:db/batch-txs @state))
  955. (defn get-file-write-chan
  956. []
  957. (:file/writes @state))
  958. (defn get-reactive-custom-queries-chan
  959. []
  960. (:reactive/custom-queries @state))
  961. (defn get-write-chan-length
  962. []
  963. (let [c (get-file-write-chan)]
  964. (count (gobj/get c "buf"))))
  965. (defn get-left-sidebar-open?
  966. []
  967. (get-in @state [:ui/left-sidebar-open?]))
  968. (defn set-left-sidebar-open!
  969. [value]
  970. (storage/set "ls-left-sidebar-open?" (boolean value))
  971. (set-state! :ui/left-sidebar-open? value))
  972. (defn toggle-left-sidebar!
  973. []
  974. (set-left-sidebar-open!
  975. (not (get-left-sidebar-open?))))
  976. (defn set-developer-mode!
  977. [value]
  978. (set-state! :ui/developer-mode? value)
  979. (storage/set "developer-mode" (str value)))
  980. (defn developer-mode?
  981. []
  982. (:ui/developer-mode? @state))
  983. (defn get-notification-contents
  984. []
  985. (get @state :notification/contents))
  986. (defn document-mode?
  987. []
  988. (get @state :document/mode?))
  989. (defn doc-mode-enter-for-new-line?
  990. []
  991. (and (document-mode?)
  992. (not (:shortcut/doc-mode-enter-for-new-block? (sub-graph-config)))))
  993. (defn toggle-document-mode!
  994. []
  995. (let [mode (document-mode?)]
  996. (set-state! :document/mode? (not mode))
  997. (storage/set :document/mode? (not mode))))
  998. (defn shortcut-tooltip-enabled?
  999. []
  1000. (get @state :ui/shortcut-tooltip?))
  1001. (defn toggle-shortcut-tooltip!
  1002. []
  1003. (let [mode (shortcut-tooltip-enabled?)]
  1004. (set-state! :ui/shortcut-tooltip? (not mode))
  1005. (storage/set :ui/shortcut-tooltip? (not mode))))
  1006. (defn mobile?
  1007. []
  1008. (or (util/mobile?) (mobile-util/native-platform?)))
  1009. (defn enable-tooltip?
  1010. []
  1011. (if (mobile?)
  1012. false
  1013. (get (get (sub-config) (get-current-repo))
  1014. :ui/enable-tooltip?
  1015. true)))
  1016. (defn show-command-doc?
  1017. []
  1018. (get (get (sub-config) (get-current-repo))
  1019. :ui/show-command-doc?
  1020. true))
  1021. (defn set-config!
  1022. [repo-url value]
  1023. (set-state! [:config repo-url] value))
  1024. (defn get-wide-mode?
  1025. []
  1026. (:ui/wide-mode? @state))
  1027. (defn toggle-wide-mode!
  1028. []
  1029. (update-state! :ui/wide-mode? not))
  1030. (defn set-online!
  1031. [value]
  1032. (set-state! :network/online? value))
  1033. (defn get-commands
  1034. []
  1035. (:commands (get-config)))
  1036. (defn get-plugins-commands
  1037. []
  1038. (mapcat seq (flatten (vals (:plugin/installed-slash-commands @state)))))
  1039. (defn get-plugins-commands-with-type
  1040. [type]
  1041. (filterv #(= (keyword (first %)) (keyword type))
  1042. (apply concat (vals (:plugin/simple-commands @state)))))
  1043. (defn get-plugins-ui-items-with-type
  1044. [type]
  1045. (filterv #(= (keyword (first %)) (keyword type))
  1046. (apply concat (vals (:plugin/installed-ui-items @state)))))
  1047. (defn get-plugin-resources-with-type
  1048. [pid type]
  1049. (when-let [pid (and type (keyword pid))]
  1050. (get-in @state [:plugin/installed-resources pid (keyword type)])))
  1051. (defn get-plugin-resource
  1052. [pid type key]
  1053. (when-let [resources (get-plugin-resources-with-type pid type)]
  1054. (get resources key)))
  1055. (defn upt-plugin-resource
  1056. [pid type key attr val]
  1057. (when-let [resource (get-plugin-resource pid type key)]
  1058. (let [resource (assoc resource (keyword attr) val)]
  1059. (set-state!
  1060. [:plugin/installed-resources (keyword pid) (keyword type) key] resource)
  1061. resource)))
  1062. (defn install-plugin-hook
  1063. [pid hook]
  1064. (when-let [pid (keyword pid)]
  1065. (set-state!
  1066. [:plugin/installed-hooks hook]
  1067. (conj
  1068. ((fnil identity #{}) (get-in @state [:plugin/installed-hooks hook]))
  1069. pid)) true))
  1070. (defn uninstall-plugin-hook
  1071. [pid hook-or-all]
  1072. (when-let [pid (keyword pid)]
  1073. (if (nil? hook-or-all)
  1074. (swap! state update :plugin/installed-hooks #(update-vals % (fn [ids] (disj ids pid))))
  1075. (when-let [coll (get-in @state [:plugin/installed-hooks hook-or-all])]
  1076. (set-state! [:plugin/installed-hooks hook-or-all] (disj coll pid))))
  1077. true))
  1078. (defn get-scheduled-future-days
  1079. []
  1080. (let [days (:scheduled/future-days (get-config))]
  1081. (or (when (int? days) days) 0)))
  1082. (defn set-graph-syncing?
  1083. [value]
  1084. (set-state! :graph/syncing? value))
  1085. (defn set-editor-in-composition!
  1086. [value]
  1087. (set-state! :editor/in-composition? value))
  1088. (defn editor-in-composition?
  1089. []
  1090. (:editor/in-composition? @state))
  1091. (defn set-loading-files!
  1092. [repo value]
  1093. (when repo
  1094. (set-state! [:repo/loading-files? repo] value)))
  1095. (defn loading-files?
  1096. [repo]
  1097. (get-in @state [:repo/loading-files? repo]))
  1098. (defn set-editor-last-input-time!
  1099. [repo time]
  1100. (swap! state assoc-in [:editor/last-input-time repo] time))
  1101. (defn set-last-transact-time!
  1102. [repo time]
  1103. (swap! state assoc-in [:db/last-transact-time repo] time)
  1104. ;; THINK: new block, indent/outdent, drag && drop, etc.
  1105. (set-editor-last-input-time! repo time))
  1106. (defn set-db-persisted!
  1107. [repo value]
  1108. (swap! state assoc-in [:db/persisted? repo] value))
  1109. (defn db-idle?
  1110. [repo]
  1111. (when repo
  1112. (when-let [last-time (get-in @state [:db/last-transact-time repo])]
  1113. (let [now (util/time-ms)]
  1114. (>= (- now last-time) 3000)))))
  1115. (defn input-idle?
  1116. [repo]
  1117. (when repo
  1118. (or
  1119. (when-let [last-time (get-in @state [:editor/last-input-time repo])]
  1120. (let [now (util/time-ms)]
  1121. (>= (- now last-time) 500)))
  1122. ;; not in editing mode
  1123. (not (get-edit-input-id)))))
  1124. (defn set-nfs-refreshing!
  1125. [value]
  1126. (set-state! :nfs/refreshing? value))
  1127. (defn nfs-refreshing?
  1128. []
  1129. (:nfs/refreshing? @state))
  1130. (defn set-search-result!
  1131. [value]
  1132. (set-state! :search/result value))
  1133. (defn clear-search-result!
  1134. []
  1135. (set-search-result! nil))
  1136. (defn add-graph-search-filter!
  1137. [q]
  1138. (when-not (string/blank? q)
  1139. (update-state! :search/graph-filters
  1140. (fn [value]
  1141. (vec (distinct (conj value q)))))))
  1142. (defn remove-search-filter!
  1143. [q]
  1144. (when-not (string/blank? q)
  1145. (update-state! :search/graph-filters
  1146. (fn [value]
  1147. (remove #{q} value)))))
  1148. (defn clear-search-filters!
  1149. []
  1150. (set-state! :search/graph-filters []))
  1151. (defn get-search-mode
  1152. []
  1153. (:search/mode @state))
  1154. (defn toggle!
  1155. [path]
  1156. (update-state! path not))
  1157. (defn toggle-settings!
  1158. []
  1159. (toggle! :ui/settings-open?))
  1160. (defn settings-open?
  1161. []
  1162. (:ui/settings-open? @state))
  1163. (defn close-settings!
  1164. []
  1165. (set-state! :ui/settings-open? false))
  1166. (defn open-settings!
  1167. []
  1168. (set-state! :ui/settings-open? true))
  1169. ;; TODO: Move those to the uni `state`
  1170. (defonce editor-op (atom nil))
  1171. (defn set-editor-op!
  1172. [value]
  1173. (reset! editor-op value))
  1174. (defn get-editor-op
  1175. []
  1176. @editor-op)
  1177. (defn get-start-of-week
  1178. []
  1179. (or
  1180. (when-let [repo (get-current-repo)]
  1181. (get-in @state [:config repo :start-of-week]))
  1182. (get-in @state [:me :settings :start-of-week])
  1183. 6))
  1184. (defn get-ref-open-blocks-level
  1185. []
  1186. (or
  1187. (when-let [value (:ref/default-open-blocks-level (get-config))]
  1188. (when (integer? value)
  1189. value))
  1190. 2))
  1191. (defn get-linked-references-collapsed-threshold
  1192. []
  1193. (or
  1194. (when-let [value (:ref/linked-references-collapsed-threshold (get-config))]
  1195. (when (integer? value)
  1196. value))
  1197. 100))
  1198. (defn get-events-chan
  1199. []
  1200. (:system/events @state))
  1201. (defn pub-event!
  1202. [payload]
  1203. (let [chan (get-events-chan)]
  1204. (async/put! chan payload)))
  1205. (defn get-copied-blocks
  1206. []
  1207. (:copy/blocks @state))
  1208. (defn set-copied-blocks!
  1209. [content blocks]
  1210. (set-state! :copy/blocks {:copy/graph (get-current-repo)
  1211. :copy/content (or content (get-in @state [:copy/blocks :copy/content]))
  1212. :copy/blocks blocks}))
  1213. (defn get-export-block-text-indent-style []
  1214. (:copy/export-block-text-indent-style @state))
  1215. (defn set-export-block-text-indent-style!
  1216. [v]
  1217. (set-state! :copy/export-block-text-indent-style v)
  1218. (storage/set :copy/export-block-text-indent-style v))
  1219. (defn get-export-block-text-remove-options []
  1220. (:copy/export-block-text-remove-options @state))
  1221. (defn update-export-block-text-remove-options!
  1222. [e k]
  1223. (let [f (if (util/echecked? e) conj disj)]
  1224. (update-state! :copy/export-block-text-remove-options
  1225. #(f % k))
  1226. (storage/set :copy/export-block-text-remove-options
  1227. (get-export-block-text-remove-options))))
  1228. (defn set-editor-args!
  1229. [args]
  1230. (set-state! :editor/args args))
  1231. (defn block-component-editing?
  1232. []
  1233. (:block/component-editing-mode? @state))
  1234. (defn set-block-component-editing-mode!
  1235. [value]
  1236. (set-state! :block/component-editing-mode? value))
  1237. (defn logical-outdenting?
  1238. []
  1239. (:editor/logical-outdenting?
  1240. (get (sub-config) (get-current-repo))))
  1241. (defn get-editor-args
  1242. []
  1243. (:editor/args @state))
  1244. (defn get-export-bullet-indentation
  1245. []
  1246. (case (get (get-config) :export/bullet-indentation :tab)
  1247. :eight-spaces
  1248. " "
  1249. :four-spaces
  1250. " "
  1251. :two-spaces
  1252. " "
  1253. :tab
  1254. "\t"))
  1255. (defn set-page-blocks-cp!
  1256. [value]
  1257. (set-state! [:view/components :page-blocks] value))
  1258. (defn get-page-blocks-cp
  1259. []
  1260. (get-in @state [:view/components :page-blocks]))
  1261. ;; To avoid circular dependencies
  1262. (defn set-component!
  1263. [k value]
  1264. (set-state! [:view/components k] value))
  1265. (defn get-component
  1266. [k]
  1267. (get-in @state [:view/components k]))
  1268. (defn exit-editing-and-set-selected-blocks!
  1269. ([blocks]
  1270. (exit-editing-and-set-selected-blocks! blocks :down))
  1271. ([blocks direction]
  1272. (clear-edit!)
  1273. (set-selection-blocks! blocks direction)))
  1274. (defn remove-watch-state [key]
  1275. (remove-watch state key))
  1276. (defn get-git-auto-commit-enabled?
  1277. []
  1278. (false? (sub [:electron/user-cfgs :git/disable-auto-commit?])))
  1279. (defn set-last-key-code!
  1280. [key-code]
  1281. (set-state! :editor/last-key-code key-code))
  1282. (defn get-last-key-code
  1283. []
  1284. (:editor/last-key-code @state))
  1285. (defn get-plugin-by-id
  1286. [id]
  1287. (when-let [id (and id (keyword id))]
  1288. (get-in @state [:plugin/installed-plugins id])))
  1289. (defn get-enabled?-installed-plugins
  1290. ([theme?] (get-enabled?-installed-plugins theme? true false))
  1291. ([theme? enabled? include-unpacked?]
  1292. (filterv
  1293. #(and (if include-unpacked? true (:iir %))
  1294. (if-not (boolean? enabled?) true (= (not enabled?) (boolean (get-in % [:settings :disabled]))))
  1295. (= (boolean theme?) (:theme %)))
  1296. (vals (:plugin/installed-plugins @state)))))
  1297. (defn lsp-enabled?-or-theme
  1298. []
  1299. (:plugin/enabled @state))
  1300. (def lsp-enabled?
  1301. (lsp-enabled?-or-theme))
  1302. (defn consume-updates-coming-plugin
  1303. [payload updated?]
  1304. (when-let [id (keyword (:id payload))]
  1305. (let [pending? (boolean (seq (:plugin/updates-pending @state)))]
  1306. (swap! state update :plugin/updates-pending dissoc id)
  1307. (if updated?
  1308. (if-let [error (:error-code payload)]
  1309. (swap! state update-in [:plugin/updates-coming id] assoc :error-code error)
  1310. (swap! state update :plugin/updates-coming dissoc id))
  1311. (swap! state update :plugin/updates-coming assoc id payload))
  1312. (pub-event! [:plugin/consume-updates id pending? updated?]))))
  1313. (defn coming-update-new-version?
  1314. [pkg]
  1315. (and pkg (:latest-version pkg)))
  1316. (defn plugin-update-available?
  1317. [id]
  1318. (when-let [pkg (and id (get (:plugin/updates-coming @state) (keyword id)))]
  1319. (coming-update-new-version? pkg)))
  1320. (defn all-available-coming-updates
  1321. []
  1322. (when-let [updates (vals (:plugin/updates-coming @state))]
  1323. (filterv #(coming-update-new-version? %) updates)))
  1324. (defn get-next-selected-coming-update
  1325. []
  1326. (when-let [updates (all-available-coming-updates)]
  1327. (let [unchecked (:plugin/updates-unchecked @state)]
  1328. (first (filter #(and (not (and (seq unchecked) (contains? unchecked (:id %))))
  1329. (not (:error-code %))) updates)))))
  1330. (defn set-unchecked-update
  1331. [id unchecked?]
  1332. (swap! state update :plugin/updates-unchecked (if unchecked? conj disj) id))
  1333. (defn reset-unchecked-update
  1334. []
  1335. (swap! state assoc :plugin/updates-unchecked #{}))
  1336. (defn reset-all-updates-state
  1337. []
  1338. (swap! state assoc
  1339. :plugin/updates-pending {}
  1340. :plugin/updates-coming {}
  1341. :plugin/updates-downloading? false))
  1342. (defn sub-right-sidebar-blocks
  1343. []
  1344. (when-let [current-repo (get-current-repo)]
  1345. (->> (sub :sidebar/blocks)
  1346. (filter #(= (first %) current-repo)))))
  1347. (defn toggle-collapsed-block!
  1348. [block-id]
  1349. (let [current-repo (get-current-repo)]
  1350. (update-state! [:ui/collapsed-blocks current-repo block-id] not)))
  1351. (defn set-collapsed-block!
  1352. [block-id value]
  1353. (let [current-repo (get-current-repo)]
  1354. (set-state! [:ui/collapsed-blocks current-repo block-id] value)))
  1355. (defn sub-collapsed
  1356. [block-id]
  1357. (sub [:ui/collapsed-blocks (get-current-repo) block-id]))
  1358. (defn get-modal-id
  1359. []
  1360. (:modal/id @state))
  1361. (defn edit-in-query-component
  1362. []
  1363. (and (editing?)
  1364. ;; config
  1365. (:custom-query? (last (get-editor-args)))))
  1366. (defn set-auth-id-token
  1367. [id-token]
  1368. (set-state! :auth/id-token id-token))
  1369. (defn set-auth-refresh-token
  1370. [refresh-token]
  1371. (set-state! :auth/refresh-token refresh-token))
  1372. (defn set-auth-access-token
  1373. [access-token]
  1374. (set-state! :auth/access-token access-token))
  1375. (defn get-auth-id-token []
  1376. (:auth/id-token @state))
  1377. (defn get-auth-refresh-token []
  1378. (:auth/refresh-token @state))
  1379. (defn set-file-sync-manager [v]
  1380. (set-state! :file-sync/sync-manager v))
  1381. (defn set-file-sync-state [v]
  1382. (when v (s/assert :frontend.fs.sync/sync-state v))
  1383. (set-state! :file-sync/sync-state v))
  1384. (defn get-file-sync-manager []
  1385. (:file-sync/sync-manager @state))
  1386. (defn get-file-sync-state []
  1387. (:file-sync/sync-state @state))
  1388. (defn reset-file-sync-download-init-state!
  1389. []
  1390. (set-state! [:file-sync/download-init-progress (get-current-repo)] {}))
  1391. (defn set-file-sync-download-init-state!
  1392. [m]
  1393. (update-state! [:file-sync/download-init-progress (get-current-repo)]
  1394. (if (fn? m) m
  1395. (fn [old-value] (merge old-value m)))))
  1396. (defn get-file-sync-download-init-state
  1397. []
  1398. (get-in @state [:file-sync/download-init-progress (get-current-repo)]))
  1399. (defn reset-parsing-state!
  1400. []
  1401. (set-state! [:graph/parsing-state (get-current-repo)] {}))
  1402. (defn set-parsing-state!
  1403. [m]
  1404. (update-state! [:graph/parsing-state (get-current-repo)]
  1405. (if (fn? m) m
  1406. (fn [old-value] (merge old-value m)))))
  1407. (defn http-proxy-enabled-or-val? []
  1408. (when-let [agent-opts (sub [:electron/user-cfgs :settings/agent])]
  1409. (when (every? not-empty (vals agent-opts))
  1410. (str (:protocol agent-opts) "://" (:host agent-opts) ":" (:port agent-opts)))))
  1411. (defn enable-encryption?
  1412. [repo]
  1413. (:feature/enable-encryption?
  1414. (get (sub-config) repo)))
  1415. (defn unlinked-dir?
  1416. [dir]
  1417. (contains? (:file/unlinked-dirs @state) dir))