state.cljs 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185
  1. (ns frontend.state
  2. "Provides main application state, fns associated to set and state based rum
  3. cursors"
  4. (:require [cljs-bean.core :as bean]
  5. [cljs.core.async :as async :refer [<!]]
  6. [cljs.spec.alpha :as s]
  7. [clojure.string :as string]
  8. [dommy.core :as dom]
  9. [electron.ipc :as ipc]
  10. [frontend.mobile.util :as mobile-util]
  11. [frontend.storage :as storage]
  12. [frontend.spec.storage :as storage-spec]
  13. [frontend.util :as util]
  14. [frontend.util.cursor :as cursor]
  15. [goog.dom :as gdom]
  16. [goog.object :as gobj]
  17. [logseq.graph-parser.config :as gp-config]
  18. [medley.core :as medley]
  19. [promesa.core :as p]
  20. [rum.core :as rum]))
  21. ;; Stores main application state
  22. (defonce ^:large-vars/data-var state
  23. (let [document-mode? (or (storage/get :document/mode?) false)
  24. current-graph (let [graph (storage/get :git/current-repo)]
  25. (when graph (ipc/ipc "setCurrentGraph" graph))
  26. graph)]
  27. (atom
  28. {:route-match nil
  29. :today nil
  30. :system/events (async/chan 1000)
  31. :db/batch-txs (async/chan 1000)
  32. :file/writes (async/chan 10000)
  33. :file/unlinked-dirs #{}
  34. :reactive/custom-queries (async/chan 1000)
  35. :notification/show? false
  36. :notification/content nil
  37. :repo/loading-files? {}
  38. :nfs/user-granted? {}
  39. :nfs/refreshing? nil
  40. :instrument/disabled? (storage/get "instrument-disabled")
  41. ;; TODO: how to detect the network reliably?
  42. :network/online? true
  43. :indexeddb/support? true
  44. :me nil
  45. :git/current-repo current-graph
  46. :draw? false
  47. :db/restoring? nil
  48. :journals-length 3
  49. :search/q ""
  50. :search/mode :global ;; inner page or full graph? {:page :global}
  51. :search/result nil
  52. :search/graph-filters []
  53. :search/engines {}
  54. ;; modals
  55. :modal/dropdowns {}
  56. :modal/id nil
  57. :modal/label ""
  58. :modal/show? false
  59. :modal/panel-content nil
  60. :modal/payload nil
  61. :modal/fullscreen? false
  62. :modal/close-btn? nil
  63. :modal/close-backdrop? true
  64. :modal/subsets []
  65. ;; ui
  66. :ui/viewport {}
  67. ;; left sidebar
  68. :ui/navigation-item-collapsed? {}
  69. ;; right sidebar
  70. :ui/settings-open? false
  71. :ui/sidebar-open? false
  72. :ui/sidebar-width "40%"
  73. :ui/left-sidebar-open? (boolean (storage/get "ls-left-sidebar-open?"))
  74. :ui/theme (or (storage/get :ui/theme) "light")
  75. :ui/system-theme? ((fnil identity (or util/mac? util/win32? false)) (storage/get :ui/system-theme?))
  76. :ui/custom-theme (or (storage/get :ui/custom-theme) {:light {:mode "light"} :dark {:mode "dark"}})
  77. :ui/wide-mode? (storage/get :ui/wide-mode)
  78. ;; ui/collapsed-blocks is to separate the collapse/expand state from db for:
  79. ;; 1. right sidebar
  80. ;; 2. zoom-in view
  81. ;; 3. queries
  82. ;; 4. references
  83. ;; graph => {:block-id bool}
  84. :ui/collapsed-blocks {}
  85. :ui/sidebar-collapsed-blocks {}
  86. :ui/root-component nil
  87. :ui/file-component nil
  88. :ui/developer-mode? (or (= (storage/get "developer-mode") "true")
  89. false)
  90. ;; remember scroll positions of visited paths
  91. :ui/paths-scroll-positions {}
  92. :ui/shortcut-tooltip? (if (false? (storage/get :ui/shortcut-tooltip?))
  93. false
  94. true)
  95. :ui/scrolling? false
  96. :document/mode? document-mode?
  97. :config {}
  98. :block/component-editing-mode? false
  99. :editor/op nil
  100. :editor/latest-op nil
  101. :editor/hidden-editors #{} ;; page names
  102. :editor/draw-mode? false
  103. :editor/action nil
  104. :editor/action-data nil
  105. ;; With label or other data
  106. :editor/last-saved-cursor nil
  107. :editor/editing? nil
  108. :editor/in-composition? false
  109. :editor/content {}
  110. :editor/block nil
  111. :editor/block-dom-id nil
  112. :editor/set-timestamp-block nil ;; click rendered block timestamp-cp to set timestamp
  113. :editor/last-input-time nil
  114. :editor/document-mode? document-mode?
  115. :editor/args nil
  116. :editor/on-paste? false
  117. :editor/last-key-code nil
  118. :editor/block-op-type nil ;; :cut, :copy
  119. ;; Stores deleted refed blocks, indexed by repo
  120. :editor/last-replace-ref-content-tx nil
  121. ;; for audio record
  122. :editor/record-status "NONE"
  123. ;; Whether to skip saving the current block
  124. :editor/skip-saving-current-block? false
  125. :editor/code-block-context {}
  126. :db/last-transact-time {}
  127. ;; whether database is persisted
  128. :db/persisted? {}
  129. :cursor-range nil
  130. :selection/mode false
  131. ;; Warning: blocks order is determined when setting this attribute
  132. :selection/blocks []
  133. :selection/start-block nil
  134. ;; either :up or :down, defaults to down
  135. ;; used to determine selection direction when two or more blocks are selected
  136. :selection/direction :down
  137. :selection/selected-all? false
  138. :custom-context-menu/show? false
  139. :custom-context-menu/links nil
  140. :custom-context-menu/position nil
  141. ;; pages or blocks in the right sidebar
  142. ;; It is a list of `[repo db-id block-type block-data]` 4-tuple
  143. :sidebar/blocks '()
  144. :preferred-language (storage/get :preferred-language)
  145. ;; electron
  146. :electron/auto-updater-downloaded false
  147. :electron/updater-pending? false
  148. :electron/updater {}
  149. :electron/user-cfgs nil
  150. :electron/server nil
  151. :electron/window-maximized? false
  152. :electron/window-fullscreen? false
  153. ;; assets
  154. :assets/alias-enabled? (or (storage/get :assets/alias-enabled?) false)
  155. :assets/alias-dirs (or (storage/get :assets/alias-dirs) [])
  156. ;; mobile
  157. :mobile/container-urls nil
  158. :mobile/show-action-bar? false
  159. :mobile/actioned-block nil
  160. :mobile/show-toolbar? false
  161. :mobile/show-recording-bar? false
  162. :mobile/show-tabbar? false
  163. ;;; Used to monitor mobile app status,
  164. ;;; value spec:
  165. ;;; {:is-active? bool, :timestamp int}
  166. :mobile/app-state-change (atom nil)
  167. ;; plugin
  168. :plugin/enabled (and (util/electron?)
  169. ;; true false :theme-only
  170. ((fnil identity true) (storage/get ::storage-spec/lsp-core-enabled)))
  171. :plugin/preferences nil
  172. :plugin/indicator-text nil
  173. :plugin/installed-plugins {}
  174. :plugin/installed-themes []
  175. :plugin/installed-slash-commands {}
  176. :plugin/installed-ui-items {}
  177. :plugin/installed-resources {}
  178. :plugin/installed-hooks {}
  179. :plugin/installed-services {}
  180. :plugin/simple-commands {}
  181. :plugin/selected-theme nil
  182. :plugin/selected-unpacked-pkg nil
  183. :plugin/marketplace-pkgs nil
  184. :plugin/marketplace-stats nil
  185. :plugin/installing nil
  186. :plugin/active-readme nil
  187. :plugin/updates-auto-checking? false
  188. :plugin/updates-pending {}
  189. :plugin/updates-coming {}
  190. :plugin/updates-downloading? false
  191. :plugin/updates-unchecked #{}
  192. :plugin/navs-settings? true
  193. :plugin/focused-settings nil ;; plugin id
  194. ;; pdf
  195. :pdf/system-win? false
  196. :pdf/current nil
  197. :pdf/ref-highlight nil
  198. :pdf/block-highlight-colored? (or (storage/get "ls-pdf-hl-block-is-colored") true)
  199. ;; all notification contents as k-v pairs
  200. :notification/contents {}
  201. :graph/syncing? false
  202. ;; graph -> state
  203. :graph/parsing-state {}
  204. :copy/export-block-text-indent-style (or (storage/get :copy/export-block-text-indent-style)
  205. "dashes")
  206. :copy/export-block-text-remove-options (or (storage/get :copy/export-block-text-remove-options)
  207. #{})
  208. :copy/export-block-text-other-options (or (storage/get :copy/export-block-text-other-options)
  209. {})
  210. :date-picker/date nil
  211. :youtube/players {}
  212. ;; command palette
  213. :command-palette/commands []
  214. :view/components {}
  215. :favorites/dragging nil
  216. :srs/mode? false
  217. :srs/cards-due-count nil
  218. :reactive/query-dbs {}
  219. ;; login, userinfo, token, ...
  220. :auth/refresh-token (storage/get "refresh-token")
  221. :auth/access-token nil
  222. :auth/id-token nil
  223. ;; file-sync
  224. :file-sync/jstour-inst nil
  225. :file-sync/onboarding-state (or (storage/get :file-sync/onboarding-state)
  226. {:welcome false})
  227. :file-sync/remote-graphs {:loading false :graphs nil}
  228. :file-sync/set-remote-graph-password-result {}
  229. ;; graph-uuid -> {:graphs-txid {}
  230. ;; :file-sync/sync-manager {}
  231. ;; :file-sync/sync-state {}
  232. ;; ;; {file-path -> payload}
  233. ;; :file-sync/progress {}
  234. ;; :file-sync/start-time {}
  235. ;; :file-sync/last-synced-at {}}
  236. :file-sync/graph-state {:current-graph-uuid nil}
  237. ;; graph-uuid -> ...
  238. :user/info {:UserGroups (storage/get :user-groups)}
  239. :encryption/graph-parsing? false
  240. :ui/loading? {}
  241. :feature/enable-sync? (storage/get :logseq-sync-enabled)
  242. :feature/enable-sync-diff-merge? (storage/get :logseq-sync-diff-merge-enabled)
  243. :file/rename-event-chan (async/chan 100)
  244. :ui/find-in-page nil
  245. :graph/importing nil
  246. :graph/importing-state {}
  247. :whiteboard/onboarding-whiteboard? (or (storage/get :ls-onboarding-whiteboard?) false)
  248. :whiteboard/onboarding-tour? (or (storage/get :whiteboard-onboarding-tour?) false)
  249. :whiteboard/last-persisted-at {}
  250. :whiteboard/pending-tx-data {}
  251. :history/page-only-mode? false
  252. ;; db tx-id -> editor cursor
  253. :history/tx->editor-cursor {}})))
  254. ;; Block ast state
  255. ;; ===============
  256. ;; block uuid -> {content(String) -> ast}
  257. (def blocks-ast-cache (atom {}))
  258. (defn add-block-ast-cache!
  259. [block-uuid content ast]
  260. (when (and block-uuid content ast)
  261. (let [new-value (assoc-in @blocks-ast-cache [block-uuid content] ast)
  262. new-value (if (> (count new-value) 10000)
  263. (into {} (take 5000 new-value))
  264. new-value)]
  265. (reset! blocks-ast-cache new-value))))
  266. (defn get-block-ast
  267. [block-uuid content]
  268. (when (and block-uuid content)
  269. (get-in @blocks-ast-cache [block-uuid content])))
  270. ;; User configuration getters under :config (and sometimes :me)
  271. ;; ========================================
  272. ;; TODO: Refactor default config values to be data driven. Currently they are all
  273. ;; buried in getters
  274. ;; TODO: Refactor our access to be more data driven. Currently each getter
  275. ;; (re-)fetches get-current-repo needlessly
  276. ;; TODO: Add consistent validation. Only a few config options validate at get time
  277. (def default-config
  278. "Default config for a repo-specific, user config"
  279. {:feature/enable-search-remove-accents? true
  280. :default-arweave-gateway "https://arweave.net"
  281. :ui/auto-expand-block-refs? true
  282. ;; For flushing the settings of old versions. Don't bump this value.
  283. ;; There are only two kinds of graph, one is not upgraded (:legacy) and one is upgraded (:triple-lowbar)
  284. ;; For not upgraded graphs, the config will have no key `:file/name-format`
  285. ;; Then the default value is applied
  286. :file/name-format :legacy})
  287. ;; State that most user config is dependent on
  288. (declare get-current-repo sub set-state!)
  289. (defn merge-configs
  290. "Merges user configs in given orders. All values are overridden except for maps
  291. which are merged."
  292. [& configs]
  293. (->> configs
  294. (filter map?)
  295. (apply merge-with
  296. (fn merge-config [current new]
  297. (if (and (map? current) (map? new))
  298. (merge current new)
  299. new)))))
  300. (defn get-global-config
  301. []
  302. (get-in @state [:config ::global-config]))
  303. (defn get-global-config-str-content
  304. []
  305. (get-in @state [:config ::global-config-str-content]))
  306. (defn get-graph-config
  307. ([] (get-graph-config (get-current-repo)))
  308. ([repo-url] (get-in @state [:config repo-url])))
  309. (defn get-config
  310. "User config for the given repo or current repo if none given. All config fetching
  311. should be done through this fn in order to get global config and config defaults"
  312. ([]
  313. (get-config (get-current-repo)))
  314. ([repo-url]
  315. (merge-configs
  316. default-config
  317. (get-global-config)
  318. (get-graph-config repo-url))))
  319. (defonce publishing? (atom nil))
  320. (defn publishing-enable-editing?
  321. []
  322. (and @publishing? (:publishing/enable-editing? (get-config))))
  323. (defn enable-editing?
  324. []
  325. (or (not @publishing?) (:publishing/enable-editing? (get-config))))
  326. (defn get-arweave-gateway
  327. []
  328. (:arweave/gateway (get-config)))
  329. (defonce built-in-macros
  330. {"img" "[:img.$4 {:src \"$1\" :style {:width $2 :height $3}}]"})
  331. (defn get-macros
  332. []
  333. (merge
  334. built-in-macros
  335. (:macros (get-config))))
  336. (defn set-assets-alias-enabled!
  337. [v]
  338. (set-state! :assets/alias-enabled? (boolean v))
  339. (storage/set :assets/alias-enabled? (boolean v)))
  340. (defn set-assets-alias-dirs!
  341. [dirs]
  342. (when dirs
  343. (set-state! :assets/alias-dirs dirs)
  344. (storage/set :assets/alias-dirs dirs)))
  345. (defn get-custom-css-link
  346. []
  347. (:custom-css-url (get-config)))
  348. (defn get-custom-js-link
  349. []
  350. (:custom-js-url (get-config)))
  351. (defn get-default-journal-template
  352. []
  353. (when-let [template (get-in (get-config) [:default-templates :journals])]
  354. (when-not (string/blank? template)
  355. (string/trim template))))
  356. (defn all-pages-public?
  357. []
  358. (let [value (:publishing/all-pages-public? (get-config))
  359. value (if (some? value) value (:all-pages-public? (get-config)))]
  360. (true? value)))
  361. (defn get-default-home
  362. []
  363. (:default-home (get-config)))
  364. (defn custom-home-page?
  365. []
  366. (some? (:page (get-default-home))))
  367. (defn get-preferred-format
  368. ([]
  369. (get-preferred-format (get-current-repo)))
  370. ([repo-url]
  371. (keyword
  372. (or
  373. (when-let [fmt (:preferred-format (get-config repo-url))]
  374. (string/lower-case (name fmt)))
  375. (get-in @state [:me :preferred_format] "markdown")))))
  376. (defn markdown?
  377. []
  378. (= (keyword (get-preferred-format))
  379. :markdown))
  380. (defn get-pages-directory
  381. []
  382. (or
  383. (when-let [repo (get-current-repo)]
  384. (:pages-directory (get-config repo)))
  385. "pages"))
  386. (defn get-journals-directory
  387. []
  388. (or
  389. (when-let [repo (get-current-repo)]
  390. (:journals-directory (get-config repo)))
  391. "journals"))
  392. (defn get-whiteboards-directory
  393. []
  394. (or
  395. (when-let [repo (get-current-repo)]
  396. (:whiteboards-directory (get-config repo)))
  397. "whiteboards"))
  398. (defn org-mode-file-link?
  399. [repo]
  400. (:org-mode/insert-file-link? (get-config repo)))
  401. (defn get-journal-file-name-format
  402. []
  403. (when-let [repo (get-current-repo)]
  404. (:journal/file-name-format (get-config repo))))
  405. (defn get-preferred-workflow
  406. []
  407. (keyword
  408. (or
  409. (when-let [workflow (:preferred-workflow (get-config))]
  410. (let [workflow (name workflow)]
  411. (if (util/safe-re-find #"now|NOW" workflow)
  412. :now
  413. :todo)))
  414. (get-in @state [:me :preferred_workflow] :now))))
  415. (defn get-preferred-todo
  416. []
  417. (if (= (get-preferred-workflow) :now)
  418. "LATER"
  419. "TODO"))
  420. (defn get-filename-format
  421. ([] (get-filename-format (get-current-repo)))
  422. ([repo]
  423. (:file/name-format (get-config repo))))
  424. (defn get-date-formatter
  425. []
  426. (gp-config/get-date-formatter (get-config)))
  427. (defn shortcuts []
  428. (:shortcuts (get-config)))
  429. (defn get-commands
  430. []
  431. (:commands (get-config)))
  432. (defn get-scheduled-future-days
  433. []
  434. (let [days (:scheduled/future-days (get-config))]
  435. (or (when (int? days) days) 7)))
  436. (defn get-start-of-week
  437. []
  438. (or (:start-of-week (get-config))
  439. (get-in @state [:me :settings :start-of-week])
  440. 6))
  441. (defn get-ref-open-blocks-level
  442. []
  443. (or
  444. (when-let [value (:ref/default-open-blocks-level (get-config))]
  445. (when (integer? value)
  446. value))
  447. 2))
  448. (defn get-linked-references-collapsed-threshold
  449. []
  450. (or
  451. (when-let [value (:ref/linked-references-collapsed-threshold (get-config))]
  452. (when (integer? value)
  453. value))
  454. 100))
  455. (defn get-export-bullet-indentation
  456. []
  457. (case (get (get-config) :export/bullet-indentation :tab)
  458. :eight-spaces
  459. " "
  460. :four-spaces
  461. " "
  462. :two-spaces
  463. " "
  464. :tab
  465. "\t"))
  466. (defn enable-search-remove-accents?
  467. []
  468. (:feature/enable-search-remove-accents? (get-config)))
  469. ;; State cursor fns for use with rum components
  470. ;; ============================================
  471. (declare document-mode?)
  472. (defn sub
  473. "Creates a rum cursor, https://github.com/tonsky/rum#cursors, for use in rum components.
  474. Similar to re-frame subscriptions"
  475. [ks]
  476. (if (coll? ks)
  477. (util/react (rum/cursor-in state ks))
  478. (util/react (rum/cursor state ks))))
  479. (defn sub-config
  480. "Sub equivalent to get-config which should handle all sub user-config access"
  481. ([] (sub-config (get-current-repo)))
  482. ([repo]
  483. (let [config (sub :config)]
  484. (merge-configs default-config
  485. (get config ::global-config)
  486. (get config repo)))))
  487. (defn enable-grammarly?
  488. []
  489. (true? (:feature/enable-grammarly? (sub-config))))
  490. (defn scheduled-deadlines-disabled?
  491. []
  492. (true? (:feature/disable-scheduled-and-deadline-query? (sub-config))))
  493. (defn enable-timetracking?
  494. []
  495. (not (false? (:feature/enable-timetracking? (sub-config)))))
  496. (defn enable-fold-button-right?
  497. []
  498. (let [_ (sub :ui/viewport)]
  499. (and (util/mobile?)
  500. (util/sm-breakpoint?))))
  501. (defn enable-journals?
  502. ([]
  503. (enable-journals? (get-current-repo)))
  504. ([repo]
  505. (not (false? (:feature/enable-journals? (sub-config repo))))))
  506. (defn enable-flashcards?
  507. ([]
  508. (enable-flashcards? (get-current-repo)))
  509. ([repo]
  510. (not (false? (:feature/enable-flashcards? (sub-config repo))))))
  511. (defn enable-sync?
  512. []
  513. (sub :feature/enable-sync?))
  514. (defn enable-sync-diff-merge?
  515. []
  516. (sub :feature/enable-sync-diff-merge?))
  517. (defn enable-whiteboards?
  518. ([]
  519. (enable-whiteboards? (get-current-repo)))
  520. ([repo]
  521. (not (false? (:feature/enable-whiteboards? (sub-config repo))))))
  522. (defn enable-git-auto-push?
  523. [repo]
  524. (not (false? (:git-auto-push (sub-config repo)))))
  525. (defn enable-block-timestamps?
  526. []
  527. (true? (:feature/enable-block-timestamps? (sub-config))))
  528. (defn graph-settings
  529. []
  530. (:graph/settings (sub-config)))
  531. ;; Enable by default
  532. (defn show-brackets?
  533. []
  534. (not (false? (:ui/show-brackets? (sub-config)))))
  535. (defn sub-default-home-page
  536. []
  537. (get-in (sub-config) [:default-home :page] ""))
  538. (defn sub-edit-content
  539. [id]
  540. (sub [:editor/content id]))
  541. (defn- get-selected-block-ids
  542. [blocks]
  543. (->> blocks
  544. (remove nil?)
  545. (keep #(when-let [id (dom/attr % "blockid")]
  546. (uuid id)))
  547. (distinct)))
  548. (defn sub-block-selected?
  549. [container-id block-uuid]
  550. (rum/react
  551. (rum/derived-atom [state] [::select-block container-id block-uuid]
  552. (fn [state]
  553. (contains? (set (get-selected-block-ids (:selection/blocks state)))
  554. block-uuid)))))
  555. (defn block-content-max-length
  556. [repo]
  557. (or (:block/content-max-length (sub-config repo)) 10000))
  558. (defn mobile?
  559. []
  560. (or (util/mobile?) (mobile-util/native-platform?)))
  561. (defn enable-tooltip?
  562. []
  563. (if (mobile?)
  564. false
  565. (get (sub-config) :ui/enable-tooltip? true)))
  566. (defn show-command-doc?
  567. []
  568. (get (sub-config) :ui/show-command-doc? true))
  569. (defn logical-outdenting?
  570. []
  571. (:editor/logical-outdenting? (sub-config)))
  572. (defn show-full-blocks?
  573. []
  574. (:ui/show-full-blocks? (sub-config)))
  575. (defn preferred-pasting-file?
  576. []
  577. (:editor/preferred-pasting-file? (sub-config)))
  578. (defn auto-expand-block-refs?
  579. []
  580. (:ui/auto-expand-block-refs? (sub-config)))
  581. (defn doc-mode-enter-for-new-line?
  582. []
  583. (and (document-mode?)
  584. (not (:shortcut/doc-mode-enter-for-new-block? (get-config)))))
  585. (defn user-groups
  586. []
  587. (set (sub [:user/info :UserGroups])))
  588. ;; State mutation helpers
  589. ;; ======================
  590. (defn set-state!
  591. [path value]
  592. (if (vector? path)
  593. (swap! state assoc-in path value)
  594. (swap! state assoc path value))
  595. nil)
  596. (defn update-state!
  597. [path f]
  598. (if (vector? path)
  599. (swap! state update-in path f)
  600. (swap! state update path f))
  601. nil)
  602. ;; State getters and setters
  603. ;; =========================
  604. ;; These fns handle any key except :config.
  605. ;; Some state is also stored in local storage and/or sent to electron's main process
  606. (defn get-route-match
  607. []
  608. (:route-match @state))
  609. (defn get-current-route
  610. []
  611. (get-in (get-route-match) [:data :name]))
  612. (defn home?
  613. []
  614. (= :home (get-current-route)))
  615. (defn whiteboard-dashboard?
  616. []
  617. (= :whiteboards (get-current-route)))
  618. (defn setups-picker?
  619. []
  620. (= :repo-add (get-current-route)))
  621. (defn get-current-page
  622. []
  623. (when (= :page (get-current-route))
  624. (get-in (get-route-match)
  625. [:path-params :name])))
  626. (defn whiteboard-route?
  627. []
  628. (= :whiteboard (get-current-route)))
  629. (defn get-current-whiteboard
  630. []
  631. (when (whiteboard-route?)
  632. (get-in (get-route-match)
  633. [:path-params :name])))
  634. (defn route-has-p?
  635. []
  636. (get-in (get-route-match) [:query-params :p]))
  637. (defn get-current-repo
  638. "Returns the current repo URL, or else open demo graph"
  639. []
  640. (or (:git/current-repo @state)
  641. "local"))
  642. (defn get-remote-graphs
  643. []
  644. (get-in @state [:file-sync/remote-graphs :graphs]))
  645. (defn get-remote-graph-info-by-uuid
  646. [uuid]
  647. (when-let [graphs (seq (get-in @state [:file-sync/remote-graphs :graphs]))]
  648. (some #(when (= (:GraphUUID %) (str uuid)) %) graphs)))
  649. (defn get-remote-graph-usage
  650. []
  651. (when-let [graphs (seq (get-in @state [:file-sync/remote-graphs :graphs]))]
  652. (->> graphs
  653. (map #(hash-map :uuid (:GraphUUID %)
  654. :name (:GraphName %)
  655. :used-gbs (/ (:GraphStorageUsage %) 1024 1024 1024)
  656. :limit-gbs (/ (:GraphStorageLimit %) 1024 1024 1024)
  657. :used-percent (/ (:GraphStorageUsage %) (:GraphStorageLimit %) 0.01)))
  658. (map #(assoc % :free-gbs (- (:limit-gbs %) (:used-gbs %))))
  659. (vec))))
  660. (defn delete-remote-graph!
  661. [repo]
  662. (swap! state update-in [:file-sync/remote-graphs :graphs]
  663. (fn [repos]
  664. (remove #(and
  665. (:GraphUUID repo)
  666. (:GraphUUID %)
  667. (= (:GraphUUID repo) (:GraphUUID %))) repos))))
  668. (defn add-remote-graph!
  669. [repo]
  670. (swap! state update-in [:file-sync/remote-graphs :graphs]
  671. (fn [repos]
  672. (->> (conj repos repo)
  673. (distinct)))))
  674. (defn get-repos
  675. []
  676. (get-in @state [:me :repos]))
  677. (defn set-repos!
  678. [repos]
  679. (set-state! [:me :repos] repos))
  680. (defn add-repo!
  681. [repo]
  682. (when (not (string/blank? repo))
  683. (update-state! [:me :repos]
  684. (fn [repos]
  685. (->> (conj repos repo)
  686. (distinct))))))
  687. (defn set-current-repo!
  688. [repo]
  689. (swap! state assoc :git/current-repo repo)
  690. (if repo
  691. (storage/set :git/current-repo repo)
  692. (storage/remove :git/current-repo))
  693. (ipc/ipc "setCurrentGraph" repo))
  694. (defn set-preferred-format!
  695. [format]
  696. (swap! state assoc-in [:me :preferred_format] (name format)))
  697. (defn set-preferred-workflow!
  698. [workflow]
  699. (swap! state assoc-in [:me :preferred_workflow] (name workflow)))
  700. (defn set-preferred-language!
  701. [language]
  702. (set-state! :preferred-language (name language))
  703. (storage/set :preferred-language (name language)))
  704. (defn delete-repo!
  705. [repo]
  706. (swap! state update-in [:me :repos]
  707. (fn [repos]
  708. (->> (remove #(or (= (:url repo) (:url %))
  709. (and
  710. (:GraphUUID repo)
  711. (:GraphUUID %)
  712. (= (:GraphUUID repo) (:GraphUUID %)))) repos)
  713. (util/distinct-by :url)))))
  714. (defn set-timestamp-block!
  715. [value]
  716. (set-state! :editor/set-timestamp-block value))
  717. (defn get-timestamp-block
  718. []
  719. (:editor/set-timestamp-block @state))
  720. (defn set-edit-content!
  721. ([input-id value] (set-edit-content! input-id value true))
  722. ([input-id value set-input-value?]
  723. (when input-id
  724. (when set-input-value?
  725. (when-let [input (gdom/getElement input-id)]
  726. (util/set-change-value input value)))
  727. (update-state! :editor/content (fn [m]
  728. (assoc m input-id value))))))
  729. (defn get-edit-input-id
  730. []
  731. (ffirst (:editor/editing? @state)))
  732. (defn get-input
  733. []
  734. (when-let [id (get-edit-input-id)]
  735. (gdom/getElement id)))
  736. (defn editing?
  737. []
  738. (let [input (get-input)]
  739. (and input (= input (.-activeElement js/document)))))
  740. (defn get-edit-content
  741. []
  742. (get (:editor/content @state) (get-edit-input-id)))
  743. (defn get-cursor-range
  744. []
  745. (:cursor-range @state))
  746. (defn set-cursor-range!
  747. [range]
  748. (set-state! :cursor-range range))
  749. (defn set-q!
  750. [value]
  751. (set-state! :search/q value))
  752. (defn set-search-mode!
  753. [value]
  754. (set-state! :search/mode value))
  755. (defn set-editor-action!
  756. [value]
  757. (set-state! :editor/action value))
  758. (defn set-editor-action-data!
  759. [value]
  760. (set-state! :editor/action-data value))
  761. (defn get-editor-action
  762. []
  763. (:editor/action @state))
  764. (defn get-editor-action-data
  765. []
  766. (:editor/action-data @state))
  767. (defn get-editor-show-page-search?
  768. []
  769. (= (get-editor-action) :page-search))
  770. (defn get-editor-show-page-search-hashtag?
  771. []
  772. (= (get-editor-action) :page-search-hashtag))
  773. (defn get-editor-show-block-search?
  774. []
  775. (= (get-editor-action) :block-search))
  776. (defn set-editor-show-input!
  777. [value]
  778. (if value
  779. (do
  780. (set-editor-action-data! (assoc (get-editor-action-data) :options value))
  781. (set-editor-action! :input))
  782. (do
  783. (set-editor-action! nil)
  784. (set-editor-action-data! nil))))
  785. (defn get-editor-show-input
  786. []
  787. (when (= (get-editor-action) :input)
  788. (get @state :editor/action-data)))
  789. (defn set-editor-show-commands!
  790. []
  791. (when-not (get-editor-action) (set-editor-action! :commands)))
  792. (defn set-editor-show-block-commands!
  793. []
  794. (when-not (get-editor-action) (set-editor-action! :block-commands)))
  795. (defn clear-editor-action!
  796. []
  797. (swap! state (fn [state]
  798. (assoc state :editor/action nil))))
  799. (defn set-edit-input-id!
  800. [input-id]
  801. (swap! state update :editor/editing?
  802. (fn [_m]
  803. (and input-id {input-id true}))))
  804. (defn get-edit-pos
  805. []
  806. (when-let [input (get-input)]
  807. (util/get-selection-start input)))
  808. (defn get-selection-start-block
  809. []
  810. (get @state :selection/start-block))
  811. (defn set-selection-start-block!
  812. [start-block]
  813. (when-not (get-selection-start-block)
  814. (swap! state assoc :selection/start-block start-block)))
  815. (defn set-selection-blocks!
  816. ([blocks]
  817. (set-selection-blocks! blocks :down))
  818. ([blocks direction]
  819. (when (seq blocks)
  820. (let [blocks (vec (util/sort-by-height (remove nil? blocks)))]
  821. (swap! state assoc
  822. :selection/mode true
  823. :selection/blocks blocks
  824. :selection/direction direction)))))
  825. (defn into-selection-mode!
  826. []
  827. (swap! state assoc :selection/mode true))
  828. (defn clear-selection!
  829. []
  830. (swap! state assoc
  831. :selection/mode false
  832. :selection/blocks nil
  833. :selection/direction :down
  834. :selection/start-block nil
  835. :selection/selected-all? false))
  836. (defn get-selection-blocks
  837. []
  838. (->> (:selection/blocks @state)
  839. (remove nil?)))
  840. (defn get-selection-block-ids
  841. []
  842. (get-selected-block-ids (get-selection-blocks)))
  843. (defn get-selection-start-block-or-first
  844. []
  845. (or (get-selection-start-block)
  846. (some-> (first (get-selection-blocks))
  847. (gobj/get "id"))))
  848. (defn in-selection-mode?
  849. []
  850. (:selection/mode @state))
  851. (defn selection?
  852. "True sense of selection mode with valid selected block"
  853. []
  854. (and (in-selection-mode?) (seq (get-selection-blocks))))
  855. (defn conj-selection-block!
  856. [block direction]
  857. (swap! state assoc
  858. :selection/mode true
  859. :selection/blocks (-> (conj (vec (:selection/blocks @state)) block)
  860. util/sort-by-height
  861. vec)
  862. :selection/direction direction))
  863. (defn drop-last-selection-block!
  864. []
  865. (let [direction (:selection/direction @state)
  866. up? (= direction :up)
  867. blocks (:selection/blocks @state)
  868. last-block (if up?
  869. (first blocks)
  870. (peek (vec blocks)))
  871. blocks' (-> (if up?
  872. (rest blocks)
  873. (pop (vec blocks)))
  874. util/sort-by-height
  875. vec)]
  876. (swap! state assoc
  877. :selection/mode true
  878. :selection/blocks blocks')
  879. last-block))
  880. (defn get-selection-direction
  881. []
  882. (:selection/direction @state))
  883. (defn show-custom-context-menu!
  884. [links position]
  885. (swap! state assoc
  886. :custom-context-menu/show? true
  887. :custom-context-menu/links links
  888. :custom-context-menu/position position))
  889. (defn hide-custom-context-menu!
  890. []
  891. (swap! state assoc
  892. :custom-context-menu/show? false
  893. :custom-context-menu/links nil
  894. :custom-context-menu/position nil))
  895. (defn toggle-navigation-item-collapsed!
  896. [item]
  897. (update-state! [:ui/navigation-item-collapsed? item] not))
  898. (defn toggle-sidebar-open?!
  899. []
  900. (swap! state update :ui/sidebar-open? not))
  901. (defn open-right-sidebar!
  902. []
  903. (swap! state assoc :ui/sidebar-open? true))
  904. (defn hide-right-sidebar!
  905. []
  906. (swap! state assoc :ui/sidebar-open? false))
  907. (defn sidebar-add-block!
  908. [repo db-id block-type]
  909. (when (not (util/sm-breakpoint?))
  910. (when db-id
  911. (update-state! :sidebar/blocks (fn [blocks]
  912. (->> (remove #(= (second %) db-id) blocks)
  913. (cons [repo db-id block-type])
  914. (distinct))))
  915. (set-state! [:ui/sidebar-collapsed-blocks db-id] false)
  916. (open-right-sidebar!)
  917. (when-let [elem (gdom/getElementByClass "sidebar-item-list")]
  918. (util/scroll-to elem 0)))))
  919. (defn sidebar-move-block!
  920. [from to]
  921. (update-state! :sidebar/blocks (fn [blocks]
  922. (let [to (if (> from to) (inc to) to)]
  923. (if (not= to from)
  924. (let [item (nth blocks from)
  925. blocks (keep-indexed #(when (not= %1 from) %2) blocks)
  926. [l r] (split-at to blocks)]
  927. (concat l [item] r))
  928. blocks)))))
  929. (defn sidebar-remove-block!
  930. [idx]
  931. (update-state! :sidebar/blocks (fn [blocks]
  932. (if (string? idx)
  933. (remove #(= (second %) idx) blocks)
  934. (util/drop-nth idx blocks))))
  935. (when (empty? (:sidebar/blocks @state))
  936. (hide-right-sidebar!)))
  937. (defn sidebar-remove-rest!
  938. [db-id]
  939. (update-state! :sidebar/blocks (fn [blocks]
  940. (remove #(not= (second %) db-id) blocks)))
  941. (set-state! [:ui/sidebar-collapsed-blocks db-id] false))
  942. (defn sidebar-replace-block!
  943. [old-sidebar-key new-sidebar-key]
  944. (update-state! :sidebar/blocks (fn [blocks]
  945. (map #(if (= % old-sidebar-key)
  946. new-sidebar-key
  947. %) blocks))))
  948. (defn sidebar-block-exists?
  949. [idx]
  950. (some #(= (second %) idx) (:sidebar/blocks @state)))
  951. (defn clear-sidebar-blocks!
  952. []
  953. (set-state! :sidebar/blocks '()))
  954. (defn sidebar-block-toggle-collapse!
  955. [db-id]
  956. (when db-id
  957. (update-state! [:ui/sidebar-collapsed-blocks db-id] not)))
  958. (defn sidebar-block-collapse-rest!
  959. [db-id]
  960. (let [items (disj (set (map second (:sidebar/blocks @state))) db-id)]
  961. (doseq [item items] (set-state! [:ui/sidebar-collapsed-blocks item] true))))
  962. (defn sidebar-block-set-collapsed-all!
  963. [collapsed?]
  964. (let [items (map second (:sidebar/blocks @state))]
  965. (doseq [item items]
  966. (set-state! [:ui/sidebar-collapsed-blocks item] collapsed?))))
  967. (defn get-edit-block
  968. []
  969. (get @state :editor/block))
  970. (defn get-current-edit-block-and-position
  971. []
  972. (let [edit-input-id (get-edit-input-id)
  973. edit-block (get-edit-block)
  974. block-element (when edit-input-id (gdom/getElement (string/replace edit-input-id "edit-block" "ls-block")))
  975. container (when block-element
  976. (util/get-block-container block-element))]
  977. (when container
  978. {:last-edit-block edit-block
  979. :container (gobj/get container "id")
  980. :pos (or (cursor/pos (gdom/getElement edit-input-id))
  981. (count (:block/content edit-block)))})))
  982. (defn clear-edit!
  983. []
  984. (swap! state merge {:editor/editing? nil
  985. :editor/block nil
  986. :cursor-range nil
  987. :editor/last-saved-cursor nil}))
  988. (defn into-code-editor-mode!
  989. []
  990. (swap! state merge {:editor/editing? nil
  991. :cursor-range nil
  992. :editor/code-mode? true}))
  993. (defn set-editor-last-pos!
  994. [new-pos]
  995. (set-state! [:editor/last-saved-cursor (:block/uuid (get-edit-block))] new-pos))
  996. (defn clear-editor-last-pos!
  997. []
  998. (set-state! :editor/last-saved-cursor nil))
  999. (defn get-editor-last-pos
  1000. []
  1001. (get-in @state [:editor/last-saved-cursor (:block/uuid (get-edit-block))]))
  1002. (defn set-block-content-and-last-pos!
  1003. [edit-input-id content new-pos]
  1004. (when edit-input-id
  1005. (set-edit-content! edit-input-id content)
  1006. (set-state! [:editor/last-saved-cursor (:block/uuid (get-edit-block))] new-pos)))
  1007. (defn set-theme-mode!
  1008. [mode]
  1009. (when (mobile-util/native-platform?)
  1010. (if (= mode "light")
  1011. (util/set-theme-light)
  1012. (util/set-theme-dark)))
  1013. (set-state! :ui/theme mode)
  1014. (storage/set :ui/theme mode))
  1015. (defn sync-system-theme!
  1016. []
  1017. (let [system-dark? (.-matches (js/window.matchMedia "(prefers-color-scheme: dark)"))]
  1018. (set-theme-mode! (if system-dark? "dark" "light"))
  1019. (set-state! :ui/system-theme? true)
  1020. (storage/set :ui/system-theme? true)))
  1021. (defn use-theme-mode!
  1022. [theme-mode]
  1023. (if (= theme-mode "system")
  1024. (sync-system-theme!)
  1025. (do
  1026. (set-theme-mode! theme-mode)
  1027. (set-state! :ui/system-theme? false)
  1028. (storage/set :ui/system-theme? false))))
  1029. (defn- toggle-theme
  1030. [theme]
  1031. (if (= theme "dark") "light" "dark"))
  1032. (defn toggle-theme!
  1033. []
  1034. (use-theme-mode! (toggle-theme (:ui/theme @state))))
  1035. (defn set-custom-theme!
  1036. ([custom-theme]
  1037. (set-custom-theme! nil custom-theme))
  1038. ([mode theme]
  1039. (set-state! (if mode [:ui/custom-theme (keyword mode)] :ui/custom-theme) theme)
  1040. (storage/set :ui/custom-theme (:ui/custom-theme @state))))
  1041. (defn restore-mobile-theme!
  1042. "Restore mobile theme setting from local storage"
  1043. []
  1044. (let [mode (or (storage/get :ui/theme) "light")
  1045. system-theme? (storage/get :ui/system-theme?)]
  1046. (when (and (not system-theme?)
  1047. (mobile-util/native-platform?))
  1048. (if (= mode "light")
  1049. (util/set-theme-light)
  1050. (util/set-theme-dark)))))
  1051. (defn set-editing-block-dom-id!
  1052. [block-dom-id]
  1053. (set-state! :editor/block-dom-id block-dom-id))
  1054. (defn get-editing-block-dom-id
  1055. []
  1056. (:editor/block-dom-id @state))
  1057. (defn set-root-component!
  1058. [component]
  1059. (set-state! :ui/root-component component))
  1060. (defn get-root-component
  1061. []
  1062. (get @state :ui/root-component))
  1063. (defn load-app-user-cfgs
  1064. ([] (load-app-user-cfgs false))
  1065. ([refresh?]
  1066. (when (util/electron?)
  1067. (p/let [cfgs (if (or refresh? (nil? (:electron/user-cfgs @state)))
  1068. (ipc/ipc :userAppCfgs)
  1069. (:electron/user-cfgs @state))
  1070. cfgs (if (object? cfgs) (bean/->clj cfgs) cfgs)]
  1071. (set-state! :electron/user-cfgs cfgs)))))
  1072. (defn setup-electron-updater!
  1073. []
  1074. (when (util/electron?)
  1075. (js/window.apis.setUpdatesCallback
  1076. (fn [_ args]
  1077. (let [data (bean/->clj args)
  1078. pending? (not= (:type data) "completed")]
  1079. (set-state! :electron/updater-pending? pending?)
  1080. (when pending? (set-state! :electron/updater data))
  1081. nil)))))
  1082. (defn set-file-component!
  1083. [component]
  1084. (set-state! :ui/file-component component))
  1085. (defn clear-file-component!
  1086. []
  1087. (set-state! :ui/file-component nil))
  1088. (defn set-journals-length!
  1089. [value]
  1090. (when value
  1091. (set-state! :journals-length value)))
  1092. (defn save-scroll-position!
  1093. ([value]
  1094. (save-scroll-position! value js/window.location.hash))
  1095. ([value path]
  1096. (set-state! [:ui/paths-scroll-positions path] value)))
  1097. (defn get-saved-scroll-position
  1098. ([]
  1099. (get-saved-scroll-position js/window.location.hash))
  1100. ([path]
  1101. (get-in @state [:ui/paths-scroll-positions path] 0)))
  1102. (defn set-today!
  1103. [value]
  1104. (set-state! :today value))
  1105. (defn get-me
  1106. []
  1107. (:me @state))
  1108. (defn set-db-restoring!
  1109. [value]
  1110. (set-state! :db/restoring? value))
  1111. (defn set-indexedb-support!
  1112. [value]
  1113. (set-state! :indexeddb/support? value))
  1114. (defn modal-opened?
  1115. []
  1116. (:modal/show? @state))
  1117. (declare set-modal!)
  1118. (declare close-modal!)
  1119. (defn get-sub-modals
  1120. []
  1121. (:modal/subsets @state))
  1122. (defn set-sub-modal!
  1123. ([panel-content]
  1124. (set-sub-modal! panel-content
  1125. {:close-btn? true}))
  1126. ([panel-content {:keys [id label payload close-btn? close-backdrop? show? center?] :as opts}]
  1127. (if (not (modal-opened?))
  1128. (set-modal! panel-content opts)
  1129. (let [modals (:modal/subsets @state)
  1130. idx (and id (first (keep-indexed #(when (= (:modal/id %2) id) %1)
  1131. modals)))
  1132. input (medley/filter-vals
  1133. #(not (nil? %1))
  1134. {:modal/id id
  1135. :modal/label (or label (if center? "ls-modal-align-center" ""))
  1136. :modal/payload payload
  1137. :modal/show? (if (boolean? show?) show? true)
  1138. :modal/panel-content panel-content
  1139. :modal/close-btn? close-btn?
  1140. :modal/close-backdrop? (if (boolean? close-backdrop?) close-backdrop? true)})]
  1141. (swap! state update-in
  1142. [:modal/subsets (or idx (count modals))]
  1143. merge input)
  1144. (:modal/subsets @state)))))
  1145. (defn close-sub-modal!
  1146. ([] (close-sub-modal! nil))
  1147. ([all?-a-id]
  1148. (if (true? all?-a-id)
  1149. (swap! state assoc :modal/subsets [])
  1150. (let [id all?-a-id
  1151. mid (:modal/id @state)
  1152. modals (:modal/subsets @state)]
  1153. (if (and id (not (string/blank? mid)) (= id mid))
  1154. (close-modal!)
  1155. (when-let [idx (if id (first (keep-indexed #(when (= (:modal/id %2) id) %1) modals))
  1156. (dec (count modals)))]
  1157. (swap! state assoc :modal/subsets (into [] (medley/remove-nth idx modals)))))))
  1158. (:modal/subsets @state)))
  1159. (defn set-modal!
  1160. ([modal-panel-content]
  1161. (set-modal! modal-panel-content
  1162. {:fullscreen? false
  1163. :close-btn? true}))
  1164. ([modal-panel-content {:keys [id label payload fullscreen? close-btn? close-backdrop? center?]}]
  1165. (let [opened? (modal-opened?)]
  1166. (when opened?
  1167. (close-modal!))
  1168. (when (seq (get-sub-modals))
  1169. (close-sub-modal! true))
  1170. (async/go
  1171. (when opened?
  1172. (<! (async/timeout 100)))
  1173. (swap! state assoc
  1174. :modal/id id
  1175. :modal/label (or label (if center? "ls-modal-align-center" ""))
  1176. :modal/show? (boolean modal-panel-content)
  1177. :modal/panel-content modal-panel-content
  1178. :modal/payload payload
  1179. :modal/fullscreen? fullscreen?
  1180. :modal/close-btn? close-btn?
  1181. :modal/close-backdrop? (if (boolean? close-backdrop?) close-backdrop? true))))
  1182. nil))
  1183. (defn close-modal!
  1184. []
  1185. (when-not (editing?)
  1186. (if (seq (get-sub-modals))
  1187. (close-sub-modal!)
  1188. (swap! state assoc
  1189. :modal/id nil
  1190. :modal/label ""
  1191. :modal/payload nil
  1192. :modal/show? false
  1193. :modal/fullscreen? false
  1194. :modal/panel-content nil
  1195. :ui/open-select nil))))
  1196. (defn get-db-batch-txs-chan
  1197. []
  1198. (:db/batch-txs @state))
  1199. (defn get-file-write-chan
  1200. []
  1201. (:file/writes @state))
  1202. (defn get-reactive-custom-queries-chan
  1203. []
  1204. (:reactive/custom-queries @state))
  1205. (defn get-left-sidebar-open?
  1206. []
  1207. (get-in @state [:ui/left-sidebar-open?]))
  1208. (defn set-left-sidebar-open!
  1209. [value]
  1210. (storage/set "ls-left-sidebar-open?" (boolean value))
  1211. (set-state! :ui/left-sidebar-open? value))
  1212. (defn toggle-left-sidebar!
  1213. []
  1214. (set-left-sidebar-open!
  1215. (not (get-left-sidebar-open?))))
  1216. (defn set-developer-mode!
  1217. [value]
  1218. (set-state! :ui/developer-mode? value)
  1219. (storage/set "developer-mode" (str value)))
  1220. (defn developer-mode?
  1221. []
  1222. (:ui/developer-mode? @state))
  1223. (defn get-notification-contents
  1224. []
  1225. (get @state :notification/contents))
  1226. (defn document-mode?
  1227. []
  1228. (get @state :document/mode?))
  1229. (defn toggle-document-mode!
  1230. []
  1231. (let [mode (document-mode?)]
  1232. (set-state! :document/mode? (not mode))
  1233. (storage/set :document/mode? (not mode))))
  1234. (defn shortcut-tooltip-enabled?
  1235. []
  1236. (get @state :ui/shortcut-tooltip?))
  1237. (defn toggle-shortcut-tooltip!
  1238. []
  1239. (let [mode (shortcut-tooltip-enabled?)]
  1240. (set-state! :ui/shortcut-tooltip? (not mode))
  1241. (storage/set :ui/shortcut-tooltip? (not mode))))
  1242. (defn set-config!
  1243. [repo-url value]
  1244. (when value (set-state! [:config repo-url] value)))
  1245. (defn set-global-config!
  1246. [value str-content]
  1247. ;; Placed under :config so cursors can work seamlessly
  1248. (when value
  1249. (set-config! ::global-config value)
  1250. (set-config! ::global-config-str-content str-content)))
  1251. (defn get-wide-mode?
  1252. []
  1253. (:ui/wide-mode? @state))
  1254. (defn toggle-wide-mode!
  1255. []
  1256. (update-state! :ui/wide-mode? not))
  1257. (defn set-online!
  1258. [value]
  1259. (set-state! :network/online? value))
  1260. (defn get-plugins-slash-commands
  1261. []
  1262. (mapcat seq (flatten (vals (:plugin/installed-slash-commands @state)))))
  1263. (defn get-plugins-commands-with-type
  1264. [type]
  1265. (->> (apply concat (vals (:plugin/simple-commands @state)))
  1266. (filterv #(= (keyword (first %)) (keyword type)))))
  1267. (defn get-plugins-ui-items-with-type
  1268. [type]
  1269. (->> (apply concat (vals (:plugin/installed-ui-items @state)))
  1270. (filterv #(= (keyword (first %)) (keyword type)))))
  1271. (defn get-plugin-resources-with-type
  1272. [pid type]
  1273. (when-let [pid (and type (keyword pid))]
  1274. (get-in @state [:plugin/installed-resources pid (keyword type)])))
  1275. (defn get-plugin-resource
  1276. [pid type key]
  1277. (when-let [resources (get-plugin-resources-with-type pid type)]
  1278. (get resources key)))
  1279. (defn upt-plugin-resource
  1280. [pid type key attr val]
  1281. (when-let [resource (get-plugin-resource pid type key)]
  1282. (let [resource (assoc resource (keyword attr) val)]
  1283. (set-state!
  1284. [:plugin/installed-resources (keyword pid) (keyword type) key] resource)
  1285. resource)))
  1286. (defn get-plugin-services
  1287. [pid type]
  1288. (when-let [installed (and pid (:plugin/installed-services @state))]
  1289. (some->> (seq (get installed (keyword pid)))
  1290. (filterv #(= type (:type %))))))
  1291. (defn install-plugin-service
  1292. ([pid type name] (install-plugin-service pid type name nil))
  1293. ([pid type name opts]
  1294. (when-let [pid (and pid type name (keyword pid))]
  1295. (let [exists (get-plugin-services pid type)]
  1296. (when-let [service (and (or (not exists) (not (some #(= name (:name %)) exists)))
  1297. {:pid pid :type type :name name :opts opts})]
  1298. (update-state! [:plugin/installed-services pid] #(conj (vec %) service))
  1299. ;; search engines state for results
  1300. (when (= type :search)
  1301. (set-state! [:search/engines (str pid name)] service)))))))
  1302. (defn uninstall-plugin-service
  1303. [pid type-or-all]
  1304. (when-let [pid (keyword pid)]
  1305. (when-let [installed (get (:plugin/installed-services @state) pid)]
  1306. (let [remove-all? (or (true? type-or-all) (nil? type-or-all))
  1307. remains (if remove-all? nil (filterv #(not= type-or-all (:type %)) installed))
  1308. removed (if remove-all? installed (filterv #(= type-or-all (:type %)) installed))]
  1309. (set-state! [:plugin/installed-services pid] remains)
  1310. ;; search engines state for results
  1311. (when-let [removed' (seq (filter #(= :search (:type %)) removed))]
  1312. (update-state! :search/engines #(apply dissoc % (mapv (fn [{:keys [pid name]}] (str pid name)) removed'))))))))
  1313. (defn get-all-plugin-services-with-type
  1314. [type]
  1315. (when-let [installed (vals (:plugin/installed-services @state))]
  1316. (mapcat (fn [s] (filter #(= (keyword type) (:type %)) s)) installed)))
  1317. (defn get-all-plugin-search-engines
  1318. []
  1319. (:search/engines @state))
  1320. (defn update-plugin-search-engine
  1321. [pid name f]
  1322. (when-let [pid (keyword pid)]
  1323. (set-state! :search/engines
  1324. (update-vals (get-all-plugin-search-engines)
  1325. #(if (and (= pid (:pid %)) (= name (:name %)))
  1326. (f %) %)))))
  1327. (defn reset-plugin-search-engines
  1328. []
  1329. (when-let [engines (get-all-plugin-search-engines)]
  1330. (set-state! :search/engines
  1331. (update-vals engines #(assoc % :result nil)))))
  1332. (defn install-plugin-hook
  1333. ([pid hook] (install-plugin-hook pid hook true))
  1334. ([pid hook opts]
  1335. (when-let [pid (keyword pid)]
  1336. (set-state!
  1337. [:plugin/installed-hooks hook]
  1338. (assoc
  1339. ((fnil identity {}) (get-in @state [:plugin/installed-hooks hook]))
  1340. pid opts)) true)))
  1341. (defn uninstall-plugin-hook
  1342. [pid hook-or-all]
  1343. (when-let [pid (keyword pid)]
  1344. (if (nil? hook-or-all)
  1345. (swap! state update :plugin/installed-hooks #(update-vals % (fn [ids] (dissoc ids pid))))
  1346. (when-let [coll (get-in @state [:plugin/installed-hooks hook-or-all])]
  1347. (set-state! [:plugin/installed-hooks hook-or-all] (dissoc coll pid))))
  1348. true))
  1349. (defn slot-hook-exist?
  1350. [uuid]
  1351. (when-let [type (and uuid (string/replace (str uuid) "-" "_"))]
  1352. (when-let [hooks (sub :plugin/installed-hooks)]
  1353. (contains? hooks (str "hook:editor:slot_" type)))))
  1354. (defn active-tldraw-app
  1355. []
  1356. (when-let [tldraw-el (.querySelector js/document.body ".logseq-tldraw[data-tlapp]")]
  1357. (gobj/get js/window.tlapps (.. tldraw-el -dataset -tlapp))))
  1358. (defn tldraw-editing-logseq-block?
  1359. []
  1360. (when-let [app (active-tldraw-app)]
  1361. (and (= 1 (.. app -selectedShapesArray -length))
  1362. (= (.. app -editingShape) (.. app -selectedShapesArray (at 0))))))
  1363. (defn set-graph-syncing?
  1364. [value]
  1365. (set-state! :graph/syncing? value))
  1366. (defn set-editor-in-composition!
  1367. [value]
  1368. (set-state! :editor/in-composition? value))
  1369. (defn editor-in-composition?
  1370. []
  1371. (:editor/in-composition? @state))
  1372. (defn set-loading-files!
  1373. [repo value]
  1374. (when repo
  1375. (set-state! [:repo/loading-files? repo] value)))
  1376. (defn loading-files?
  1377. [repo]
  1378. (get-in @state [:repo/loading-files? repo]))
  1379. (defn set-editor-last-input-time!
  1380. [repo time]
  1381. (swap! state assoc-in [:editor/last-input-time repo] time))
  1382. (defn set-last-transact-time!
  1383. [repo time]
  1384. (swap! state assoc-in [:db/last-transact-time repo] time)
  1385. ;; THINK: new block, indent/outdent, drag && drop, etc.
  1386. (set-editor-last-input-time! repo time))
  1387. (defn set-db-persisted!
  1388. [repo value]
  1389. (swap! state assoc-in [:db/persisted? repo] value))
  1390. (defn db-idle?
  1391. [repo]
  1392. (when repo
  1393. (when-let [last-time (get-in @state [:db/last-transact-time repo])]
  1394. (let [now (util/time-ms)]
  1395. (>= (- now last-time) 3000)))))
  1396. (defn input-idle?
  1397. [repo & {:keys [diff]
  1398. :or {diff 1000}}]
  1399. (when repo
  1400. (or
  1401. (when-let [last-time (get-in @state [:editor/last-input-time repo])]
  1402. (let [now (util/time-ms)]
  1403. (>= (- now last-time) diff)))
  1404. ;; not in editing mode
  1405. ;; Is this a good idea to put whiteboard check here?
  1406. (not (get-edit-input-id)))))
  1407. (defn whiteboard-idle?
  1408. "Check if whiteboard is idle."
  1409. [repo]
  1410. (when repo
  1411. (>= (- (util/time-ms) (or (get-in @state [:whiteboard/last-persisted-at repo])
  1412. (- (util/time-ms) 10000)))
  1413. 3000)))
  1414. (defn set-nfs-refreshing!
  1415. [value]
  1416. (set-state! :nfs/refreshing? value))
  1417. (defn nfs-refreshing?
  1418. []
  1419. (:nfs/refreshing? @state))
  1420. (defn set-search-result!
  1421. [value]
  1422. (set-state! :search/result value))
  1423. (defn clear-search-result!
  1424. []
  1425. (set-search-result! nil))
  1426. (defn add-graph-search-filter!
  1427. [q]
  1428. (when-not (string/blank? q)
  1429. (update-state! :search/graph-filters
  1430. (fn [value]
  1431. (vec (distinct (conj value q)))))))
  1432. (defn remove-search-filter!
  1433. [q]
  1434. (when-not (string/blank? q)
  1435. (update-state! :search/graph-filters
  1436. (fn [value]
  1437. (remove #{q} value)))))
  1438. (defn clear-search-filters!
  1439. []
  1440. (set-state! :search/graph-filters []))
  1441. (defn get-search-mode
  1442. []
  1443. (:search/mode @state))
  1444. (defn toggle!
  1445. [path]
  1446. (update-state! path not))
  1447. (defn toggle-settings!
  1448. []
  1449. (toggle! :ui/settings-open?))
  1450. (defn settings-open?
  1451. []
  1452. (:ui/settings-open? @state))
  1453. (defn close-settings!
  1454. []
  1455. (set-state! :ui/settings-open? false))
  1456. (defn open-settings!
  1457. ([] (open-settings! true))
  1458. ([active-tab] (set-state! :ui/settings-open? active-tab)))
  1459. ;; TODO: Move those to the uni `state`
  1460. (defn set-editor-op!
  1461. [value]
  1462. (set-state! :editor/op value)
  1463. (when value (set-state! :editor/latest-op value)))
  1464. (defn get-editor-op
  1465. []
  1466. (:editor/op @state))
  1467. (defn get-editor-latest-op
  1468. []
  1469. (:editor/latest-op @state))
  1470. (defn get-events-chan
  1471. []
  1472. (:system/events @state))
  1473. (defn pub-event!
  1474. {:malli/schema [:=> [:cat vector?] :any]}
  1475. [payload]
  1476. (let [d (p/deferred)
  1477. chan (get-events-chan)]
  1478. (async/put! chan [payload d])
  1479. d))
  1480. (defn get-export-block-text-indent-style []
  1481. (:copy/export-block-text-indent-style @state))
  1482. (defn set-export-block-text-indent-style!
  1483. [v]
  1484. (set-state! :copy/export-block-text-indent-style v)
  1485. (storage/set :copy/export-block-text-indent-style v))
  1486. (defn get-export-block-text-remove-options []
  1487. (:copy/export-block-text-remove-options @state))
  1488. (defn update-export-block-text-remove-options!
  1489. [e k]
  1490. (let [f (if (util/echecked? e) conj disj)]
  1491. (update-state! :copy/export-block-text-remove-options
  1492. #(f % k))
  1493. (storage/set :copy/export-block-text-remove-options
  1494. (get-export-block-text-remove-options))))
  1495. (defn get-export-block-text-other-options []
  1496. (:copy/export-block-text-other-options @state))
  1497. (defn update-export-block-text-other-options!
  1498. [k v]
  1499. (update-state! :copy/export-block-text-other-options #(assoc % k v)))
  1500. (defn set-editor-args!
  1501. [args]
  1502. (set-state! :editor/args args))
  1503. (defn editing-whiteboard-portal?
  1504. []
  1505. (and (active-tldraw-app) (tldraw-editing-logseq-block?)))
  1506. (defn block-component-editing?
  1507. []
  1508. (and (:block/component-editing-mode? @state)
  1509. (not (editing-whiteboard-portal?))))
  1510. (defn set-block-component-editing-mode!
  1511. [value]
  1512. (set-state! :block/component-editing-mode? value))
  1513. (defn get-editor-args
  1514. []
  1515. (:editor/args @state))
  1516. (defn set-page-blocks-cp!
  1517. [value]
  1518. (set-state! [:view/components :page-blocks] value))
  1519. (defn get-page-blocks-cp
  1520. []
  1521. (get-in @state [:view/components :page-blocks]))
  1522. ;; To avoid circular dependencies
  1523. (defn set-component!
  1524. [k value]
  1525. (set-state! [:view/components k] value))
  1526. (defn get-component
  1527. [k]
  1528. (get-in @state [:view/components k]))
  1529. (defn exit-editing-and-set-selected-blocks!
  1530. ([blocks]
  1531. (exit-editing-and-set-selected-blocks! blocks :down))
  1532. ([blocks direction]
  1533. (clear-edit!)
  1534. (set-selection-blocks! blocks direction)))
  1535. (defn set-editing!
  1536. ([edit-input-id content block cursor-range]
  1537. (set-editing! edit-input-id content block cursor-range true))
  1538. ([edit-input-id content block cursor-range move-cursor?]
  1539. (if (> (count content)
  1540. (block-content-max-length (get-current-repo)))
  1541. (let [elements (array-seq (js/document.getElementsByClassName (:block/uuid block)))]
  1542. (when (first elements)
  1543. (util/scroll-to-element (gobj/get (first elements) "id")))
  1544. (exit-editing-and-set-selected-blocks! elements))
  1545. (when (and edit-input-id block
  1546. (or
  1547. (publishing-enable-editing?)
  1548. (not @publishing?)))
  1549. (let [block-element (gdom/getElement (string/replace edit-input-id "edit-block" "ls-block"))
  1550. container (util/get-block-container block-element)
  1551. block (if container
  1552. (assoc block
  1553. :block.temp/container (gobj/get container "id"))
  1554. block)
  1555. content (string/trim (or content ""))]
  1556. (swap! state
  1557. (fn [state]
  1558. (-> state
  1559. (assoc-in [:editor/content edit-input-id] content)
  1560. (assoc
  1561. :editor/block block
  1562. :editor/editing? {edit-input-id true}
  1563. :editor/last-key-code nil
  1564. :editor/set-timestamp-block nil
  1565. :cursor-range cursor-range))))
  1566. (when-let [input (gdom/getElement edit-input-id)]
  1567. (let [pos (count cursor-range)]
  1568. (when content
  1569. (util/set-change-value input content))
  1570. (when move-cursor?
  1571. (cursor/move-cursor-to input pos))
  1572. (when (or (util/mobile?) (mobile-util/native-platform?))
  1573. (set-state! :mobile/show-action-bar? false)))))))))
  1574. (defn remove-watch-state [key]
  1575. (remove-watch state key))
  1576. (defn get-git-auto-commit-enabled?
  1577. []
  1578. (false? (sub [:electron/user-cfgs :git/disable-auto-commit?])))
  1579. (defn set-last-key-code!
  1580. [key-code]
  1581. (set-state! :editor/last-key-code key-code))
  1582. (defn get-last-key-code
  1583. []
  1584. (:editor/last-key-code @state))
  1585. (defn set-block-op-type!
  1586. [op-type]
  1587. (set-state! :editor/block-op-type op-type))
  1588. (defn get-block-op-type
  1589. []
  1590. (:editor/block-op-type @state))
  1591. (defn feature-http-server-enabled?
  1592. []
  1593. (boolean (storage/get ::storage-spec/http-server-enabled)))
  1594. (defn get-plugin-by-id
  1595. [id]
  1596. (when-let [id (and id (keyword id))]
  1597. (get-in @state [:plugin/installed-plugins id])))
  1598. (defn get-enabled?-installed-plugins
  1599. ([theme?] (get-enabled?-installed-plugins theme? true false false))
  1600. ([theme? enabled? include-unpacked? include-all?]
  1601. (filterv
  1602. #(and (if include-unpacked? true (:iir %))
  1603. (if-not (boolean? enabled?) true (= (not enabled?) (boolean (get-in % [:settings :disabled]))))
  1604. (or include-all? (if (boolean? theme?) (= (boolean theme?) (:theme %)) true)))
  1605. (vals (:plugin/installed-plugins @state)))))
  1606. (defn lsp-enabled?-or-theme
  1607. []
  1608. (:plugin/enabled @state))
  1609. (def lsp-enabled?
  1610. (lsp-enabled?-or-theme))
  1611. (defn consume-updates-from-coming-plugin!
  1612. [payload updated?]
  1613. (when-let [id (keyword (:id payload))]
  1614. (let [prev-pending? (boolean (seq (:plugin/updates-pending @state)))]
  1615. (println "Updates: consumed pending - " id)
  1616. (swap! state update :plugin/updates-pending dissoc id)
  1617. (if updated?
  1618. (if-let [error (:error-code payload)]
  1619. (swap! state update-in [:plugin/updates-coming id] assoc :error-code error)
  1620. (swap! state update :plugin/updates-coming dissoc id))
  1621. (swap! state update :plugin/updates-coming assoc id payload))
  1622. (pub-event! [:plugin/consume-updates id prev-pending? updated?]))))
  1623. (defn coming-update-new-version?
  1624. [pkg]
  1625. (and pkg (:latest-version pkg)))
  1626. (defn plugin-update-available?
  1627. [id]
  1628. (when-let [pkg (and id (get (:plugin/updates-coming @state) (keyword id)))]
  1629. (coming-update-new-version? pkg)))
  1630. (defn all-available-coming-updates
  1631. ([] (all-available-coming-updates (:plugin/updates-coming @state)))
  1632. ([updates] (when-let [updates (vals updates)]
  1633. (filterv #(coming-update-new-version? %) updates))))
  1634. (defn get-next-selected-coming-update
  1635. []
  1636. (when-let [updates (all-available-coming-updates)]
  1637. (let [unchecked (:plugin/updates-unchecked @state)]
  1638. (first (filter #(and (not (and (seq unchecked) (contains? unchecked (:id %))))
  1639. (not (:error-code %))) updates)))))
  1640. (defn set-unchecked-update
  1641. [id unchecked?]
  1642. (swap! state update :plugin/updates-unchecked (if unchecked? conj disj) id))
  1643. (defn reset-unchecked-update
  1644. []
  1645. (swap! state assoc :plugin/updates-unchecked #{}))
  1646. (defn reset-all-updates-state
  1647. []
  1648. (swap! state assoc
  1649. :plugin/updates-auto-checking? false
  1650. :plugin/updates-pending {}
  1651. :plugin/updates-coming {}
  1652. :plugin/updates-downloading? false))
  1653. (defn sub-right-sidebar-blocks
  1654. []
  1655. (when-let [current-repo (get-current-repo)]
  1656. (->> (sub :sidebar/blocks)
  1657. (filter #(= (first %) current-repo)))))
  1658. (defn toggle-collapsed-block!
  1659. [block-id]
  1660. (let [current-repo (get-current-repo)]
  1661. (update-state! [:ui/collapsed-blocks current-repo block-id] not)))
  1662. (defn set-collapsed-block!
  1663. [block-id value]
  1664. (let [current-repo (get-current-repo)]
  1665. (set-state! [:ui/collapsed-blocks current-repo block-id] value)))
  1666. (defn sub-collapsed
  1667. [block-id]
  1668. (sub [:ui/collapsed-blocks (get-current-repo) block-id]))
  1669. (defn get-modal-id
  1670. []
  1671. (:modal/id @state))
  1672. (defn edit-in-query-or-refs-component
  1673. []
  1674. (let [config (last (get-editor-args))]
  1675. {:custom-query? (:custom-query? config)
  1676. :ref? (:ref? config)}))
  1677. (defn set-auth-id-token
  1678. [id-token]
  1679. (set-state! :auth/id-token id-token))
  1680. (defn set-auth-refresh-token
  1681. [refresh-token]
  1682. (set-state! :auth/refresh-token refresh-token))
  1683. (defn set-auth-access-token
  1684. [access-token]
  1685. (set-state! :auth/access-token access-token))
  1686. (defn get-auth-id-token []
  1687. (sub :auth/id-token))
  1688. (defn get-auth-refresh-token []
  1689. (:auth/refresh-token @state))
  1690. (defn set-file-sync-manager [graph-uuid v]
  1691. (when (and graph-uuid v)
  1692. (set-state! [:file-sync/graph-state graph-uuid :file-sync/sync-manager] v)))
  1693. (defn get-file-sync-manager [graph-uuid]
  1694. (get-in @state [:file-sync/graph-state graph-uuid :file-sync/sync-manager]))
  1695. (defn clear-file-sync-state! [graph-uuid]
  1696. (set-state! [:file-sync/graph-state graph-uuid] nil))
  1697. (defn clear-file-sync-progress! [graph-uuid]
  1698. (set-state! [:file-sync/graph-state
  1699. graph-uuid
  1700. :file-sync/progress]
  1701. nil))
  1702. (defn set-file-sync-state [graph-uuid v]
  1703. (when v (s/assert :frontend.fs.sync/sync-state v))
  1704. (set-state! [:file-sync/graph-state graph-uuid :file-sync/sync-state] v))
  1705. (defn get-current-file-sync-graph-uuid
  1706. []
  1707. (get-in @state [:file-sync/graph-state :current-graph-uuid]))
  1708. (defn sub-current-file-sync-graph-uuid
  1709. []
  1710. (sub [:file-sync/graph-state :current-graph-uuid]))
  1711. (defn get-file-sync-state
  1712. ([]
  1713. (get-file-sync-state (get-current-file-sync-graph-uuid)))
  1714. ([graph-uuid]
  1715. (get-in @state [:file-sync/graph-state graph-uuid :file-sync/sync-state])))
  1716. (defn sub-file-sync-state
  1717. [graph-uuid]
  1718. (sub [:file-sync/graph-state graph-uuid :file-sync/sync-state]))
  1719. (defn reset-parsing-state!
  1720. []
  1721. (set-state! [:graph/parsing-state (get-current-repo)] {}))
  1722. (defn set-parsing-state!
  1723. [m]
  1724. (update-state! [:graph/parsing-state (get-current-repo)]
  1725. (if (fn? m) m
  1726. (fn [old-value] (merge old-value m)))))
  1727. (defn http-proxy-enabled-or-val? []
  1728. (when-let [{:keys [type protocol host port] :as agent-opts} (sub [:electron/user-cfgs :settings/agent])]
  1729. (when (and (not (contains? #{"system"} type))
  1730. (every? not-empty (vals agent-opts)))
  1731. (str protocol "://" host ":" port))))
  1732. (defn set-mobile-app-state-change
  1733. [is-active?]
  1734. (set-state! :mobile/app-state-change
  1735. {:is-active? is-active?
  1736. :timestamp (inst-ms (js/Date.))}))
  1737. (defn get-sync-graph-by-id
  1738. [graph-uuid]
  1739. (when graph-uuid
  1740. (let [graph (first (filter #(= graph-uuid (:GraphUUID %))
  1741. (get-repos)))]
  1742. (when (:url graph)
  1743. graph))))
  1744. (defn unlinked-dir?
  1745. [dir]
  1746. (contains? (:file/unlinked-dirs @state) dir))
  1747. (defn get-file-rename-event-chan
  1748. []
  1749. (:file/rename-event-chan @state))
  1750. (defn offer-file-rename-event-chan!
  1751. [v]
  1752. {:pre [(map? v)
  1753. (= #{:repo :old-path :new-path} (set (keys v)))]}
  1754. (async/offer! (get-file-rename-event-chan) v))
  1755. (defn set-onboarding-whiteboard!
  1756. [v]
  1757. (set-state! :whiteboard/onboarding-whiteboard? v)
  1758. (storage/set :ls-onboarding-whiteboard? v))
  1759. (defn get-onboarding-whiteboard?
  1760. []
  1761. (get-in @state [:whiteboard/onboarding-whiteboard?]))
  1762. (defn get-local-container-root-url
  1763. []
  1764. (when (mobile-util/native-ios?)
  1765. (get-in @state [:mobile/container-urls :localContainerUrl])))
  1766. (defn get-icloud-container-root-url
  1767. []
  1768. (when (mobile-util/native-ios?)
  1769. (get-in @state [:mobile/container-urls :iCloudContainerUrl])))
  1770. (defn get-current-pdf
  1771. []
  1772. (:pdf/current @state))
  1773. (defn nfs-user-granted?
  1774. [repo]
  1775. (get-in @state [:nfs/user-granted? repo]))
  1776. (defn set-current-pdf!
  1777. [inflated-file]
  1778. (let [settle-file! #(set-state! :pdf/current inflated-file)]
  1779. (if-not (get-current-pdf)
  1780. (settle-file!)
  1781. (when (apply not= (map :identity [inflated-file (get-current-pdf)]))
  1782. (set-state! :pdf/current nil)
  1783. (js/setTimeout #(settle-file!) 16)))))
  1784. (defn focus-whiteboard-shape
  1785. ([shape-id]
  1786. (focus-whiteboard-shape (active-tldraw-app) shape-id))
  1787. ([tln shape-id]
  1788. (when-let [^js api (gobj/get tln "api")]
  1789. (when (and shape-id (parse-uuid shape-id))
  1790. (. api selectShapes shape-id)
  1791. (. api zoomToSelection)))))
  1792. (defn set-user-info!
  1793. [info]
  1794. (when info
  1795. (set-state! :user/info info)
  1796. (let [groups (:UserGroups info)]
  1797. (when (seq groups)
  1798. (storage/set :user-groups groups)))))
  1799. (defn get-user-info []
  1800. (sub :user/info))
  1801. (defn clear-user-info!
  1802. []
  1803. (storage/remove :user-groups))