settings.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. class app.Settings
  2. PREFERENCE_KEYS = [
  3. 'hideDisabled'
  4. 'hideIntro'
  5. 'manualUpdate'
  6. 'fastScroll'
  7. 'arrowScroll'
  8. 'analyticsConsent'
  9. 'docs'
  10. 'dark' # legacy
  11. 'theme'
  12. 'layout'
  13. 'size'
  14. 'tips'
  15. 'noAutofocus'
  16. 'autoInstall'
  17. 'spaceScroll'
  18. 'spaceTimeout'
  19. ]
  20. INTERNAL_KEYS = [
  21. 'count'
  22. 'schema'
  23. 'version'
  24. 'news'
  25. ]
  26. LAYOUTS: [
  27. '_max-width'
  28. '_sidebar-hidden'
  29. '_native-scrollbars'
  30. '_text-justify-hyphenate'
  31. ]
  32. @defaults:
  33. count: 0
  34. hideDisabled: false
  35. hideIntro: false
  36. news: 0
  37. manualUpdate: false
  38. schema: 1
  39. analyticsConsent: false
  40. theme: 'auto'
  41. spaceScroll: 1
  42. spaceTimeout: 0.5
  43. constructor: ->
  44. @store = new CookiesStore
  45. @cache = {}
  46. @autoSupported = window.matchMedia('(prefers-color-scheme)').media != 'not all'
  47. if @autoSupported
  48. @darkModeQuery = window.matchMedia('(prefers-color-scheme: dark)')
  49. @darkModeQuery.addListener => @setTheme(@get('theme'))
  50. get: (key) ->
  51. return @cache[key] if @cache.hasOwnProperty(key)
  52. @cache[key] = @store.get(key) ? @constructor.defaults[key]
  53. if key == 'theme' and @cache[key] == 'auto' and !@darkModeQuery
  54. @cache[key] = 'default'
  55. else
  56. @cache[key]
  57. set: (key, value) ->
  58. @store.set(key, value)
  59. delete @cache[key]
  60. @setTheme(value) if key == 'theme'
  61. return
  62. del: (key) ->
  63. @store.del(key)
  64. delete @cache[key]
  65. return
  66. hasDocs: ->
  67. try !!@store.get('docs')
  68. getDocs: ->
  69. @store.get('docs')?.split('/') or app.config.default_docs
  70. setDocs: (docs) ->
  71. @set 'docs', docs.join('/')
  72. return
  73. getTips: ->
  74. @store.get('tips')?.split('/') or []
  75. setTips: (tips) ->
  76. @set 'tips', tips.join('/')
  77. return
  78. setLayout: (name, enable) ->
  79. @toggleLayout(name, enable)
  80. layout = (@store.get('layout') || '').split(' ')
  81. $.arrayDelete(layout, '')
  82. if enable
  83. layout.push(name) if layout.indexOf(name) is -1
  84. else
  85. $.arrayDelete(layout, name)
  86. if layout.length > 0
  87. @set 'layout', layout.join(' ')
  88. else
  89. @del 'layout'
  90. return
  91. hasLayout: (name) ->
  92. layout = (@store.get('layout') || '').split(' ')
  93. layout.indexOf(name) isnt -1
  94. setSize: (value) ->
  95. @set 'size', value
  96. return
  97. dump: ->
  98. @store.dump()
  99. export: ->
  100. data = @dump()
  101. delete data[key] for key in INTERNAL_KEYS
  102. data
  103. import: (data) ->
  104. for key, value of @export()
  105. @del key unless data.hasOwnProperty(key)
  106. for key, value of data
  107. @set key, value if PREFERENCE_KEYS.indexOf(key) isnt -1
  108. return
  109. reset: ->
  110. @store.reset()
  111. @cache = {}
  112. return
  113. initLayout: ->
  114. if @get('dark') is 1
  115. @set('theme', 'dark')
  116. @del 'dark'
  117. @setTheme(@get('theme'))
  118. @toggleLayout(layout, @hasLayout(layout)) for layout in @LAYOUTS
  119. @initSidebarWidth()
  120. return
  121. setTheme: (theme) ->
  122. if theme is 'auto'
  123. theme = if @darkModeQuery.matches then 'dark' else 'default'
  124. classList = document.documentElement.classList
  125. classList.remove('_theme-default', '_theme-dark')
  126. classList.add('_theme-' + theme)
  127. @updateColorMeta()
  128. return
  129. updateColorMeta: ->
  130. color = getComputedStyle(document.documentElement).getPropertyValue('--headerBackground').trim()
  131. $('meta[name=theme-color]').setAttribute('content', color)
  132. return
  133. toggleLayout: (layout, enable) ->
  134. classList = document.body.classList
  135. # sidebar is always shown for settings; its state is updated in app.views.Settings
  136. classList.toggle(layout, enable) unless layout is '_sidebar-hidden' and app.router?.isSettings
  137. classList.toggle('_overlay-scrollbars', $.overlayScrollbarsEnabled())
  138. return
  139. initSidebarWidth: ->
  140. size = @get('size')
  141. document.documentElement.style.setProperty('--sidebarWidth', size + 'px') if size
  142. return