user-settings-context.tsx 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import {
  2. createContext,
  3. useContext,
  4. useMemo,
  5. Dispatch,
  6. SetStateAction,
  7. FC,
  8. useState,
  9. useEffect,
  10. } from 'react'
  11. import { UserSettings, Keybindings } from '../../../../types/user-settings'
  12. import getMeta from '@/utils/meta'
  13. import useScopeValue from '@/shared/hooks/use-scope-value'
  14. import { userStyles } from '../utils/styles'
  15. const defaultSettings: UserSettings = {
  16. pdfViewer: 'pdfjs',
  17. autoComplete: true,
  18. autoPairDelimiters: true,
  19. syntaxValidation: false,
  20. editorTheme: 'textmate',
  21. overallTheme: '',
  22. mode: 'default',
  23. fontSize: 12,
  24. fontFamily: 'monaco',
  25. lineHeight: 'normal',
  26. mathPreview: true,
  27. referencesSearchMode: 'advanced',
  28. enableNewEditor: true,
  29. }
  30. type UserSettingsContextValue = {
  31. userSettings: UserSettings
  32. setUserSettings: Dispatch<
  33. SetStateAction<UserSettingsContextValue['userSettings']>
  34. >
  35. }
  36. type ScopeSettings = {
  37. overallTheme: 'light' | 'dark'
  38. keybindings: Keybindings
  39. fontSize: number
  40. fontFamily: string
  41. lineHeight: number
  42. }
  43. export const UserSettingsContext = createContext<
  44. UserSettingsContextValue | undefined
  45. >(undefined)
  46. export const UserSettingsProvider: FC = ({ children }) => {
  47. const [userSettings, setUserSettings] = useState<UserSettings>(
  48. () => getMeta('ol-userSettings') || defaultSettings
  49. )
  50. // update the global scope 'settings' value, for extensions
  51. const [, setScopeSettings] = useScopeValue<ScopeSettings>('settings')
  52. useEffect(() => {
  53. const { fontFamily, lineHeight } = userStyles(userSettings)
  54. setScopeSettings({
  55. overallTheme: userSettings.overallTheme === 'light-' ? 'light' : 'dark',
  56. keybindings: userSettings.mode === 'none' ? 'default' : userSettings.mode,
  57. fontFamily,
  58. lineHeight,
  59. fontSize: userSettings.fontSize,
  60. })
  61. }, [setScopeSettings, userSettings])
  62. const value = useMemo<UserSettingsContextValue>(
  63. () => ({
  64. userSettings,
  65. setUserSettings,
  66. }),
  67. [userSettings, setUserSettings]
  68. )
  69. return (
  70. <UserSettingsContext.Provider value={value}>
  71. {children}
  72. </UserSettingsContext.Provider>
  73. )
  74. }
  75. export function useUserSettingsContext() {
  76. const context = useContext(UserSettingsContext)
  77. if (!context) {
  78. throw new Error(
  79. 'useUserSettingsContext is only available inside UserSettingsProvider'
  80. )
  81. }
  82. return context
  83. }