overleaf/services/web/frontend/js/features/editor-left-menu/context/project-settings-context.tsx
M Fahru 677ec173ed Disable updating project-wide settings while socket is currently listening to update project-wide settings in a project.
This may happen if the project is being used by multiple people, and we want to avoid race condition on the update since it's possible for multiple people to update setting value at the same time.

GitOrigin-RevId: cdad6a6456e2d9e4ef1812ebfd6f6ef59f23747f
2023-01-11 09:08:06 +00:00

175 lines
4.2 KiB
TypeScript

import { createContext, useContext, useMemo, useState } from 'react'
import type { PropsWithChildren } from 'react'
import type {
FontFamily,
LineHeight,
OverallTheme,
} from '../../../../../modules/source-editor/frontend/js/extensions/theme'
import type {
Keybindings,
PdfViewer,
ProjectCompiler,
} from '../../../../../types/project-settings'
import useSetProjectWideSettings from '../hooks/use-set-project-wide-settings'
import useUserWideSettings from '../hooks/use-user-wide-settings'
import useProjectWideSettingsSocketListener from '../hooks/use-project-wide-settings-socket-listener'
type ProjectSettingsContextValue = {
compiler?: ProjectCompiler
setCompiler: (compiler: ProjectCompiler) => void
imageName?: string
setImageName: (imageName: string) => void
rootDocId?: string
setRootDocId: (rootDocId: string) => void
spellCheckLanguage?: string
setSpellCheckLanguage: (spellCheckLanguage: string) => void
autoComplete?: boolean
setAutoComplete: (autoComplete: boolean) => void
autoPairDelimiters?: boolean
setAutoPairDelimiters: (autoPairDelimiters: boolean) => void
syntaxValidation?: boolean
setSyntaxValidation: (syntaxValidation: boolean) => void
mode?: Keybindings
setMode: (mode: Keybindings) => void
editorTheme?: string
setEditorTheme: (editorTheme: string) => void
overallTheme?: OverallTheme
setOverallTheme: (overallTheme: OverallTheme) => void
fontSize?: string
setFontSize: (fontSize: string) => void
fontFamily?: FontFamily
setFontFamily: (fontFamily: FontFamily) => void
lineHeight?: LineHeight
setLineHeight: (lineHeight: LineHeight) => void
pdfViewer?: PdfViewer
setPdfViewer: (pdfViewer: PdfViewer) => void
}
export const ProjectSettingsContext = createContext<
ProjectSettingsContextValue | undefined
>(undefined)
export function ProjectSettingsProvider({
children,
}: PropsWithChildren<Record<string, never>>) {
const [ignoreUpdates, setIgnoreUpdates] = useState(false)
const {
compiler,
setCompiler,
imageName,
setImageName,
rootDocId,
setRootDocId,
spellCheckLanguage,
setSpellCheckLanguage,
} = useSetProjectWideSettings({ ignoreUpdates })
const {
autoComplete,
setAutoComplete,
autoPairDelimiters,
setAutoPairDelimiters,
syntaxValidation,
setSyntaxValidation,
editorTheme,
setEditorTheme,
overallTheme,
setOverallTheme,
mode,
setMode,
fontSize,
setFontSize,
fontFamily,
setFontFamily,
lineHeight,
setLineHeight,
pdfViewer,
setPdfViewer,
} = useUserWideSettings()
useProjectWideSettingsSocketListener({
onListen: () => setIgnoreUpdates(true),
})
const value: ProjectSettingsContextValue = useMemo(
() => ({
compiler,
setCompiler,
imageName,
setImageName,
rootDocId,
setRootDocId,
spellCheckLanguage,
setSpellCheckLanguage,
autoComplete,
setAutoComplete,
autoPairDelimiters,
setAutoPairDelimiters,
syntaxValidation,
setSyntaxValidation,
editorTheme,
setEditorTheme,
overallTheme,
setOverallTheme,
mode,
setMode,
fontSize,
setFontSize,
fontFamily,
setFontFamily,
lineHeight,
setLineHeight,
pdfViewer,
setPdfViewer,
}),
[
compiler,
setCompiler,
imageName,
setImageName,
rootDocId,
setRootDocId,
spellCheckLanguage,
setSpellCheckLanguage,
autoComplete,
setAutoComplete,
autoPairDelimiters,
setAutoPairDelimiters,
syntaxValidation,
setSyntaxValidation,
editorTheme,
setEditorTheme,
overallTheme,
setOverallTheme,
mode,
setMode,
fontSize,
setFontSize,
fontFamily,
setFontFamily,
lineHeight,
setLineHeight,
pdfViewer,
setPdfViewer,
]
)
return (
<ProjectSettingsContext.Provider value={value}>
{children}
</ProjectSettingsContext.Provider>
)
}
export function useProjectSettingsContext() {
const context = useContext(ProjectSettingsContext)
if (!context) {
throw new Error(
'useProjectSettingsContext is only available inside ProjectSettingsProvider'
)
}
return context
}