first commit
This commit is contained in:
@@ -0,0 +1,58 @@
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import { useIdeContext } from '../../../shared/context/ide-context'
|
||||
import useScopeValue from '../../../shared/hooks/use-scope-value'
|
||||
import type { ProjectSettings } from '../utils/api'
|
||||
|
||||
export default function useProjectWideSettingsSocketListener() {
|
||||
const { socket } = useIdeContext()
|
||||
|
||||
const [project, setProject] = useScopeValue<ProjectSettings | undefined>(
|
||||
'project'
|
||||
)
|
||||
|
||||
const setCompiler = useCallback(
|
||||
(compiler: ProjectSettings['compiler']) => {
|
||||
if (project) {
|
||||
setProject({ ...project, compiler })
|
||||
}
|
||||
},
|
||||
[project, setProject]
|
||||
)
|
||||
|
||||
const setImageName = useCallback(
|
||||
(imageName: ProjectSettings['imageName']) => {
|
||||
if (project) {
|
||||
setProject({ ...project, imageName })
|
||||
}
|
||||
},
|
||||
[project, setProject]
|
||||
)
|
||||
|
||||
const setSpellCheckLanguage = useCallback(
|
||||
(spellCheckLanguage: ProjectSettings['spellCheckLanguage']) => {
|
||||
if (project) {
|
||||
setProject({ ...project, spellCheckLanguage })
|
||||
}
|
||||
},
|
||||
[project, setProject]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
// data is not available on initial mounting
|
||||
const dataAvailable = !!project
|
||||
|
||||
if (dataAvailable && socket) {
|
||||
socket.on('compilerUpdated', setCompiler)
|
||||
socket.on('imageNameUpdated', setImageName)
|
||||
socket.on('spellCheckLanguageUpdated', setSpellCheckLanguage)
|
||||
return () => {
|
||||
socket.removeListener('compilerUpdated', setCompiler)
|
||||
socket.removeListener('imageNameUpdated', setImageName)
|
||||
socket.removeListener(
|
||||
'spellCheckLanguageUpdated',
|
||||
setSpellCheckLanguage
|
||||
)
|
||||
}
|
||||
}
|
||||
}, [socket, project, setCompiler, setImageName, setSpellCheckLanguage])
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { useCallback } from 'react'
|
||||
import useScopeValue from '../../../shared/hooks/use-scope-value'
|
||||
import type { ProjectSettings } from '../utils/api'
|
||||
import useRootDocId from './use-root-doc-id'
|
||||
import useSaveProjectSettings from './use-save-project-settings'
|
||||
import useSetSpellCheckLanguage from './use-set-spell-check-language'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
|
||||
export default function useProjectWideSettings() {
|
||||
// The value will be undefined on mount
|
||||
const [project] = useScopeValue<ProjectSettings | undefined>('project')
|
||||
const saveProjectSettings = useSaveProjectSettings()
|
||||
|
||||
const setCompiler = useCallback(
|
||||
(newCompiler: ProjectSettings['compiler']) => {
|
||||
saveProjectSettings('compiler', newCompiler).catch(debugConsole.error)
|
||||
},
|
||||
[saveProjectSettings]
|
||||
)
|
||||
|
||||
const setImageName = useCallback(
|
||||
(newImageName: ProjectSettings['imageName']) => {
|
||||
saveProjectSettings('imageName', newImageName).catch(debugConsole.error)
|
||||
},
|
||||
[saveProjectSettings]
|
||||
)
|
||||
|
||||
const { setRootDocId, rootDocId } = useRootDocId()
|
||||
const setSpellCheckLanguage = useSetSpellCheckLanguage()
|
||||
|
||||
return {
|
||||
compiler: project?.compiler,
|
||||
setCompiler,
|
||||
imageName: project?.imageName,
|
||||
setImageName,
|
||||
rootDocId,
|
||||
setRootDocId,
|
||||
spellCheckLanguage: project?.spellCheckLanguage,
|
||||
setSpellCheckLanguage,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
import { useCallback } from 'react'
|
||||
import { useEditorContext } from '../../../shared/context/editor-context'
|
||||
import useScopeValue from '../../../shared/hooks/use-scope-value'
|
||||
import type { ProjectSettings } from '../utils/api'
|
||||
import useSaveProjectSettings from './use-save-project-settings'
|
||||
|
||||
export default function useRootDocId() {
|
||||
const [rootDocId] =
|
||||
useScopeValue<ProjectSettings['rootDocId']>('project.rootDoc_id')
|
||||
const { permissionsLevel } = useEditorContext()
|
||||
const saveProjectSettings = useSaveProjectSettings()
|
||||
|
||||
const setRootDocIdFunc = useCallback(
|
||||
async (newRootDocId: ProjectSettings['rootDocId']) => {
|
||||
// rootDocId will be undefined on angular scope on initialisation
|
||||
const allowUpdate =
|
||||
typeof rootDocId !== 'undefined' && permissionsLevel !== 'readOnly'
|
||||
|
||||
if (allowUpdate) {
|
||||
try {
|
||||
await saveProjectSettings('rootDocId', newRootDocId)
|
||||
} catch (err) {
|
||||
// TODO: retry mechanism (max 10x before failed completely and rollback the old value)
|
||||
}
|
||||
}
|
||||
},
|
||||
[permissionsLevel, rootDocId, saveProjectSettings]
|
||||
)
|
||||
|
||||
return {
|
||||
rootDocId,
|
||||
setRootDocId: setRootDocIdFunc,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { type ProjectSettings, saveProjectSettings } from '../utils/api'
|
||||
import { useProjectContext } from '../../../shared/context/project-context'
|
||||
import useScopeValue from '../../../shared/hooks/use-scope-value'
|
||||
|
||||
export default function useSaveProjectSettings() {
|
||||
// projectSettings value will be undefined on mount
|
||||
const [projectSettings, setProjectSettings] = useScopeValue<
|
||||
ProjectSettings | undefined
|
||||
>('project')
|
||||
const { _id: projectId } = useProjectContext()
|
||||
|
||||
return async (
|
||||
key: keyof ProjectSettings,
|
||||
newSetting: ProjectSettings[keyof ProjectSettings]
|
||||
) => {
|
||||
if (projectSettings) {
|
||||
const currentSetting = projectSettings[key]
|
||||
if (currentSetting !== newSetting) {
|
||||
await saveProjectSettings(projectId, {
|
||||
[key]: newSetting,
|
||||
})
|
||||
|
||||
// rootDocId is used in our tsx and our endpoint, but rootDoc_id is used in our project $scope, etc
|
||||
// as we use both namings in many files, and convert back and forth,
|
||||
// its complicated to seperate and choose one name for all usages
|
||||
// todo: make rootDocId or rootDoc_id consistent, and remove need for this/ other conversions
|
||||
const settingsKey = key === 'rootDocId' ? 'rootDoc_id' : key
|
||||
setProjectSettings({ ...projectSettings, [settingsKey]: newSetting })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { useUserSettingsContext } from '@/shared/context/user-settings-context'
|
||||
import { saveUserSettings } from '../utils/api'
|
||||
import { UserSettings } from '../../../../../types/user-settings'
|
||||
|
||||
export default function useSaveUserSettings() {
|
||||
const { userSettings, setUserSettings } = useUserSettingsContext()
|
||||
|
||||
return (
|
||||
key: keyof UserSettings,
|
||||
newSetting: UserSettings[keyof UserSettings]
|
||||
) => {
|
||||
const currentSetting = userSettings[key]
|
||||
|
||||
if (currentSetting !== newSetting) {
|
||||
setUserSettings({ ...userSettings, [key]: newSetting })
|
||||
saveUserSettings(key, newSetting)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
import { useCallback, useEffect } from 'react'
|
||||
import _ from 'lodash'
|
||||
import { saveUserSettings } from '../utils/api'
|
||||
import { UserSettings } from '../../../../../types/user-settings'
|
||||
import { useUserSettingsContext } from '@/shared/context/user-settings-context'
|
||||
import getMeta from '@/utils/meta'
|
||||
import { isIEEEBranded } from '@/utils/is-ieee-branded'
|
||||
|
||||
export default function useSetOverallTheme() {
|
||||
const { userSettings, setUserSettings } = useUserSettingsContext()
|
||||
const { overallTheme } = userSettings
|
||||
|
||||
const setOverallTheme = useCallback(
|
||||
(overallTheme: UserSettings['overallTheme']) => {
|
||||
setUserSettings(settings => ({ ...settings, overallTheme }))
|
||||
},
|
||||
[setUserSettings]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
// Sets the body's data-theme attribute for theming
|
||||
const theme =
|
||||
overallTheme === 'light-' && !isIEEEBranded() ? 'light' : 'default'
|
||||
document.body.dataset.theme = theme
|
||||
}, [overallTheme])
|
||||
|
||||
return useCallback(
|
||||
(newOverallTheme: UserSettings['overallTheme']) => {
|
||||
if (overallTheme !== newOverallTheme) {
|
||||
const chosenTheme = _.find(
|
||||
getMeta('ol-overallThemes'),
|
||||
theme => theme.val === newOverallTheme
|
||||
)
|
||||
|
||||
if (chosenTheme) {
|
||||
setOverallTheme(newOverallTheme)
|
||||
saveUserSettings('overallTheme', newOverallTheme)
|
||||
}
|
||||
}
|
||||
},
|
||||
[overallTheme, setOverallTheme]
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
import { useCallback } from 'react'
|
||||
import useScopeValue from '../../../shared/hooks/use-scope-value'
|
||||
import { type ProjectSettings, saveUserSettings } from '../utils/api'
|
||||
import useSaveProjectSettings from './use-save-project-settings'
|
||||
|
||||
export default function useSetSpellCheckLanguage() {
|
||||
const [spellCheckLanguage, setSpellCheckLanguage] = useScopeValue<
|
||||
ProjectSettings['spellCheckLanguage']
|
||||
>('project.spellCheckLanguage')
|
||||
const saveProjectSettings = useSaveProjectSettings()
|
||||
|
||||
return useCallback(
|
||||
(newSpellCheckLanguage: ProjectSettings['spellCheckLanguage']) => {
|
||||
const allowUpdate =
|
||||
spellCheckLanguage != null &&
|
||||
newSpellCheckLanguage !== spellCheckLanguage
|
||||
|
||||
if (allowUpdate) {
|
||||
setSpellCheckLanguage(newSpellCheckLanguage)
|
||||
|
||||
// Save project settings is created from hooks because it will save the value on
|
||||
// both server-side and client-side (angular scope)
|
||||
saveProjectSettings('spellCheckLanguage', newSpellCheckLanguage)
|
||||
|
||||
// For user settings, we only need to save it on server-side,
|
||||
// so we import the function directly without hooks
|
||||
saveUserSettings('spellCheckLanguage', newSpellCheckLanguage)
|
||||
}
|
||||
},
|
||||
[setSpellCheckLanguage, spellCheckLanguage, saveProjectSettings]
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
import { useCallback } from 'react'
|
||||
import { useUserSettingsContext } from '@/shared/context/user-settings-context'
|
||||
import useSetOverallTheme from './use-set-overall-theme'
|
||||
import useSaveUserSettings from './use-save-user-settings'
|
||||
import { UserSettings } from '../../../../../types/user-settings'
|
||||
|
||||
export default function useUserWideSettings() {
|
||||
const saveUserSettings = useSaveUserSettings()
|
||||
|
||||
const { userSettings } = useUserSettingsContext()
|
||||
const {
|
||||
overallTheme,
|
||||
autoComplete,
|
||||
autoPairDelimiters,
|
||||
syntaxValidation,
|
||||
editorTheme,
|
||||
mode,
|
||||
fontSize,
|
||||
fontFamily,
|
||||
lineHeight,
|
||||
pdfViewer,
|
||||
mathPreview,
|
||||
} = userSettings
|
||||
|
||||
const setOverallTheme = useSetOverallTheme()
|
||||
const setAutoComplete = useCallback(
|
||||
(autoComplete: UserSettings['autoComplete']) => {
|
||||
saveUserSettings('autoComplete', autoComplete)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
const setAutoPairDelimiters = useCallback(
|
||||
(autoPairDelimiters: UserSettings['autoPairDelimiters']) => {
|
||||
saveUserSettings('autoPairDelimiters', autoPairDelimiters)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
const setSyntaxValidation = useCallback(
|
||||
(syntaxValidation: UserSettings['syntaxValidation']) => {
|
||||
saveUserSettings('syntaxValidation', syntaxValidation)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
const setEditorTheme = useCallback(
|
||||
(editorTheme: UserSettings['editorTheme']) => {
|
||||
saveUserSettings('editorTheme', editorTheme)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
const setMode = useCallback(
|
||||
(mode: UserSettings['mode']) => {
|
||||
saveUserSettings('mode', mode)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
const setFontSize = useCallback(
|
||||
(fontSize: UserSettings['fontSize']) => {
|
||||
saveUserSettings('fontSize', fontSize)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
const setFontFamily = useCallback(
|
||||
(fontFamily: UserSettings['fontFamily']) => {
|
||||
saveUserSettings('fontFamily', fontFamily)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
const setLineHeight = useCallback(
|
||||
(lineHeight: UserSettings['lineHeight']) => {
|
||||
saveUserSettings('lineHeight', lineHeight)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
const setPdfViewer = useCallback(
|
||||
(pdfViewer: UserSettings['pdfViewer']) => {
|
||||
saveUserSettings('pdfViewer', pdfViewer)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
const setMathPreview = useCallback(
|
||||
(mathPreview: UserSettings['mathPreview']) => {
|
||||
saveUserSettings('mathPreview', mathPreview)
|
||||
},
|
||||
[saveUserSettings]
|
||||
)
|
||||
|
||||
return {
|
||||
autoComplete,
|
||||
setAutoComplete,
|
||||
autoPairDelimiters,
|
||||
setAutoPairDelimiters,
|
||||
syntaxValidation,
|
||||
setSyntaxValidation,
|
||||
editorTheme,
|
||||
setEditorTheme,
|
||||
overallTheme,
|
||||
setOverallTheme,
|
||||
mode,
|
||||
setMode,
|
||||
fontSize,
|
||||
setFontSize,
|
||||
fontFamily,
|
||||
setFontFamily,
|
||||
lineHeight,
|
||||
setLineHeight,
|
||||
pdfViewer,
|
||||
setPdfViewer,
|
||||
mathPreview,
|
||||
setMathPreview,
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user