editor-properties-context.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import {
  2. createContext,
  3. Dispatch,
  4. FC,
  5. PropsWithChildren,
  6. SetStateAction,
  7. useCallback,
  8. useContext,
  9. useEffect,
  10. useState,
  11. } from 'react'
  12. import customLocalStorage from '@/infrastructure/local-storage'
  13. import getMeta from '@/utils/meta'
  14. import { useUnstableStoreSync } from '@/shared/hooks/use-unstable-store-sync'
  15. import { sendMB } from '@/infrastructure/event-tracking'
  16. import { useEditorOpenDocContext } from '@/features/ide-react/context/editor-open-doc-context'
  17. import { getVisualEditorStorageKey } from '@/features/source-editor/utils/visual-editor'
  18. // Context value type
  19. export type EditorPropertiesContextValue = {
  20. showVisual: boolean
  21. setShowVisual: Dispatch<SetStateAction<boolean>>
  22. showVisualForFile: (filename: string) => boolean
  23. showSymbolPalette: boolean
  24. setShowSymbolPalette: Dispatch<SetStateAction<boolean>>
  25. toggleSymbolPalette: () => void
  26. opening: boolean
  27. setOpening: Dispatch<SetStateAction<boolean>>
  28. trackChanges: boolean
  29. setTrackChanges: Dispatch<SetStateAction<boolean>>
  30. wantTrackChanges: boolean
  31. setWantTrackChanges: Dispatch<SetStateAction<boolean>>
  32. errorState: boolean
  33. setErrorState: Dispatch<SetStateAction<boolean>>
  34. }
  35. export const EditorPropertiesContext = createContext<
  36. EditorPropertiesContextValue | undefined
  37. >(undefined)
  38. function migrateTexVisualMode(): boolean {
  39. const projectId = getMeta('ol-project_id')
  40. const editorModeKey = `editor.mode.${projectId}`
  41. const editorModeVal = customLocalStorage.getItem(editorModeKey)
  42. if (editorModeVal) {
  43. customLocalStorage.removeItem(editorModeKey)
  44. return editorModeVal === 'rich-text'
  45. }
  46. return false
  47. }
  48. export function showVisualForFile(filename: string): boolean {
  49. const key = getVisualEditorStorageKey(filename)
  50. const stored = customLocalStorage.getItem(key)
  51. if (stored !== null) {
  52. return stored === 'visual'
  53. }
  54. if (key === 'editor.lastUsedMode') {
  55. return migrateTexVisualMode()
  56. }
  57. return false
  58. }
  59. export const EditorPropertiesProvider: FC<PropsWithChildren> = ({
  60. children,
  61. }) => {
  62. const { openDocName } = useEditorOpenDocContext()
  63. const [showVisual, setShowVisualState] = useState(() =>
  64. openDocName != null ? showVisualForFile(openDocName) : false
  65. )
  66. useEffect(() => {
  67. setShowVisualState(
  68. openDocName != null ? showVisualForFile(openDocName) : false
  69. )
  70. }, [openDocName])
  71. const setShowVisual: Dispatch<SetStateAction<boolean>> = useCallback(
  72. value => {
  73. setShowVisualState(prev => {
  74. const actual = typeof value === 'function' ? value(prev) : value
  75. if (openDocName != null) {
  76. const key = getVisualEditorStorageKey(openDocName)
  77. customLocalStorage.setItem(key, actual ? 'visual' : 'code')
  78. }
  79. return actual
  80. })
  81. },
  82. [openDocName]
  83. )
  84. // Sync the showVisual state with the exposed store
  85. useUnstableStoreSync('editor.showVisual', showVisual)
  86. const [showSymbolPalette, setShowSymbolPalette] = useState(false)
  87. const toggleSymbolPalette = useCallback(() => {
  88. setShowSymbolPalette(show => {
  89. const newValue = !show
  90. sendMB(newValue ? 'symbol-palette-show' : 'symbol-palette-hide')
  91. return newValue
  92. })
  93. }, [setShowSymbolPalette])
  94. const [opening, setOpening] = useState(true)
  95. const [trackChanges, setTrackChanges] = useState(false)
  96. const [wantTrackChanges, setWantTrackChanges] = useState(false)
  97. const [errorState, setErrorState] = useState(false)
  98. const value = {
  99. showVisual,
  100. setShowVisual,
  101. showVisualForFile,
  102. showSymbolPalette,
  103. setShowSymbolPalette,
  104. toggleSymbolPalette,
  105. opening,
  106. setOpening,
  107. trackChanges,
  108. setTrackChanges,
  109. wantTrackChanges,
  110. setWantTrackChanges,
  111. errorState,
  112. setErrorState,
  113. }
  114. return (
  115. <EditorPropertiesContext.Provider value={value}>
  116. {children}
  117. </EditorPropertiesContext.Provider>
  118. )
  119. }
  120. export const useEditorPropertiesContext = (): EditorPropertiesContextValue => {
  121. const context = useContext(EditorPropertiesContext)
  122. if (!context) {
  123. throw new Error(
  124. 'useEditorPropertiesContext is only available inside EditorPropertiesContext.Provider'
  125. )
  126. }
  127. return context
  128. }