ide-context.tsx 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import { createContext, FC, useContext, useEffect, useMemo } from 'react'
  2. import { ScopeValueStore } from '../../../../types/ide/scope-value-store'
  3. import { ScopeEventEmitter } from '../../../../types/ide/scope-event-emitter'
  4. import { Socket } from '@/features/ide-react/connection/types/socket'
  5. import { useUserSettingsContext } from './user-settings-context'
  6. import { userStyles } from '../utils/styles'
  7. import { useActiveOverallTheme } from '../hooks/use-active-overall-theme'
  8. export type Ide = {
  9. socket: Socket
  10. }
  11. type IdeContextValue = Ide & {
  12. scopeEventEmitter: ScopeEventEmitter
  13. unstableStore: ScopeValueStore
  14. }
  15. export const IdeContext = createContext<IdeContextValue | undefined>(undefined)
  16. export const IdeProvider: FC<
  17. React.PropsWithChildren<{
  18. ide: Ide
  19. scopeEventEmitter: ScopeEventEmitter
  20. unstableStore: ScopeValueStore
  21. }>
  22. > = ({ ide, scopeEventEmitter, unstableStore, children }) => {
  23. /**
  24. * Expose unstableStore via `window.overleaf.unstable.store`, so it can be accessed by external extensions.
  25. *
  26. * These properties are expected to be available:
  27. * - `editor.view`
  28. * - `editor.open_doc_name`,
  29. * - `editor.open_doc_id`,
  30. * - `settings.theme`
  31. * - `settings.keybindings`
  32. * - `settings.fontSize`
  33. * - `settings.fontFamily`
  34. * - `settings.lineHeight`
  35. */
  36. useEffect(() => {
  37. window.overleaf = {
  38. ...window.overleaf,
  39. unstable: {
  40. ...window.overleaf?.unstable,
  41. store: unstableStore,
  42. },
  43. }
  44. }, [unstableStore])
  45. const { userSettings } = useUserSettingsContext()
  46. const activeOverallTheme = useActiveOverallTheme()
  47. useEffect(() => {
  48. const { fontFamily, lineHeight } = userStyles(userSettings)
  49. unstableStore.set('settings', {
  50. overallTheme: activeOverallTheme,
  51. keybindings: userSettings.mode === 'none' ? 'default' : userSettings.mode,
  52. fontFamily,
  53. lineHeight,
  54. fontSize: userSettings.fontSize,
  55. isNewEditor: true,
  56. })
  57. }, [unstableStore, userSettings, activeOverallTheme])
  58. const value = useMemo<IdeContextValue>(() => {
  59. return {
  60. ...ide,
  61. scopeEventEmitter,
  62. unstableStore,
  63. }
  64. }, [ide, scopeEventEmitter, unstableStore])
  65. return <IdeContext.Provider value={value}>{children}</IdeContext.Provider>
  66. }
  67. export function useIdeContext(): IdeContextValue {
  68. const context = useContext(IdeContext)
  69. if (!context) {
  70. throw new Error('useIdeContext is only available inside IdeProvider')
  71. }
  72. return context
  73. }