diff --git a/services/web/frontend/js/features/editor-left-menu/context/project-settings-context.tsx b/services/web/frontend/js/features/editor-left-menu/context/project-settings-context.tsx index 5a2a5ce7ac..2562ecb48d 100644 --- a/services/web/frontend/js/features/editor-left-menu/context/project-settings-context.tsx +++ b/services/web/frontend/js/features/editor-left-menu/context/project-settings-context.tsx @@ -1,4 +1,4 @@ -import { createContext, useContext, useMemo } from 'react' +import { createContext, useContext, useMemo, useState } from 'react' import type { PropsWithChildren } from 'react' import type { FontFamily, @@ -52,6 +52,8 @@ export const ProjectSettingsContext = createContext< export function ProjectSettingsProvider({ children, }: PropsWithChildren>) { + const [ignoreUpdates, setIgnoreUpdates] = useState(false) + const { compiler, setCompiler, @@ -61,7 +63,7 @@ export function ProjectSettingsProvider({ setRootDocId, spellCheckLanguage, setSpellCheckLanguage, - } = useSetProjectWideSettings() + } = useSetProjectWideSettings({ ignoreUpdates }) const { autoComplete, @@ -86,7 +88,9 @@ export function ProjectSettingsProvider({ setPdfViewer, } = useUserWideSettings() - useProjectWideSettingsSocketListener() + useProjectWideSettingsSocketListener({ + onListen: () => setIgnoreUpdates(true), + }) const value: ProjectSettingsContextValue = useMemo( () => ({ diff --git a/services/web/frontend/js/features/editor-left-menu/hooks/use-project-wide-settings-socket-listener.tsx b/services/web/frontend/js/features/editor-left-menu/hooks/use-project-wide-settings-socket-listener.tsx index 8a2eb0bc0c..746a6fa6dc 100644 --- a/services/web/frontend/js/features/editor-left-menu/hooks/use-project-wide-settings-socket-listener.tsx +++ b/services/web/frontend/js/features/editor-left-menu/hooks/use-project-wide-settings-socket-listener.tsx @@ -1,21 +1,52 @@ -import { useEffect } from 'react' +import { useCallback, useEffect } from 'react' import { ProjectCompiler } from '../../../../../types/project-settings' import { useIdeContext } from '../../../shared/context/ide-context' import useScopeValue from '../../../shared/hooks/use-scope-value' -export default function useProjectWideSettingsSocketListener() { +type UseProjectWideSettingsSocketListener = { + onListen: () => void +} + +export default function useProjectWideSettingsSocketListener({ + onListen, +}: UseProjectWideSettingsSocketListener) { const ide = useIdeContext() - const [compiler, setCompiler] = + const [compilerScope, setCompilerScope] = useScopeValue('project.compiler') - const [imageName, setImageName] = useScopeValue('project.imageName') - const [spellCheckLanguage, setSpellCheckLanguage] = useScopeValue( - 'project.spellCheckLanguage' + const [imageNameScope, setImageNameScope] = + useScopeValue('project.imageName') + const [spellCheckLanguageScope, setSpellCheckLanguageScope] = + useScopeValue('project.spellCheckLanguage') + + const setCompiler = useCallback( + (compiler: ProjectCompiler) => { + onListen() + setCompilerScope(compiler) + }, + [setCompilerScope, onListen] + ) + + const setImageName = useCallback( + (imageName: string) => { + onListen() + setImageNameScope(imageName) + }, + [setImageNameScope, onListen] + ) + + const setSpellCheckLanguage = useCallback( + (spellCheckLanguage: string) => { + onListen() + setSpellCheckLanguageScope(spellCheckLanguage) + }, + [setSpellCheckLanguageScope, onListen] ) useEffect(() => { // data is not available on initial mounting - const dataAvailable = compiler && imageName && spellCheckLanguage + const dataAvailable = + compilerScope && imageNameScope && spellCheckLanguageScope if (dataAvailable && ide?.socket) { ide.socket.on('compilerUpdated', setCompiler) @@ -32,11 +63,11 @@ export default function useProjectWideSettingsSocketListener() { } }, [ ide?.socket, - compiler, + compilerScope, setCompiler, - imageName, + imageNameScope, setImageName, - spellCheckLanguage, + spellCheckLanguageScope, setSpellCheckLanguage, ]) } diff --git a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-project-wide-settings.tsx b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-project-wide-settings.tsx index cd4800f5c2..21ded370a3 100644 --- a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-project-wide-settings.tsx +++ b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-project-wide-settings.tsx @@ -6,8 +6,13 @@ import { ProjectSettingsScope, saveProjectSettings } from '../utils/api' import useSetRootDocId from './use-set-root-doc-id' import useSetSpellCheckLanguage from './use-set-spell-check-language' -// TODO: handle ignoreUpdates -export default function useSetProjectWideSettings() { +type UseSetProjectWideSettings = { + ignoreUpdates: boolean +} + +export default function useSetProjectWideSettings({ + ignoreUpdates, +}: UseSetProjectWideSettings) { // The value will be undefined on mount const [project, setProject] = useScopeValue( 'project', @@ -17,26 +22,30 @@ export default function useSetProjectWideSettings() { const setCompiler = useCallback( (compiler: ProjectCompiler) => { - if (project?.compiler) { + const allowUpdate = !ignoreUpdates && project?.compiler + + if (allowUpdate) { setProject({ ...project, compiler }) saveProjectSettings({ projectId, compiler }) } }, - [projectId, project, setProject] + [projectId, project, setProject, ignoreUpdates] ) const setImageName = useCallback( (imageName: string) => { - if (project?.imageName) { + const allowUpdate = !ignoreUpdates && project?.imageName + + if (allowUpdate) { setProject({ ...project, imageName }) saveProjectSettings({ projectId, imageName }) } }, - [projectId, project, setProject] + [projectId, project, setProject, ignoreUpdates] ) - const setRootDocId = useSetRootDocId() - const setSpellCheckLanguage = useSetSpellCheckLanguage() + const setRootDocId = useSetRootDocId({ ignoreUpdates }) + const setSpellCheckLanguage = useSetSpellCheckLanguage({ ignoreUpdates }) return { compiler: project?.compiler, diff --git a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-root-doc-id.tsx b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-root-doc-id.tsx index 535ea77e41..7268d2fb5b 100644 --- a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-root-doc-id.tsx +++ b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-root-doc-id.tsx @@ -4,7 +4,11 @@ import { useProjectContext } from '../../../shared/context/project-context' import useScopeValue from '../../../shared/hooks/use-scope-value' import { saveProjectSettings } from '../utils/api' -export default function useSetRootDocId() { +type UseSetRootDocId = { + ignoreUpdates: boolean +} + +export default function useSetRootDocId({ ignoreUpdates }: UseSetRootDocId) { const [rootDocIdScope, setRootDocIdScope] = useScopeValue('project.rootDoc_id') const { permissionsLevel } = useEditorContext() @@ -12,12 +16,13 @@ export default function useSetRootDocId() { const setRootDocId = useCallback( async (rootDocId: string) => { - const disallowChange = - typeof rootDocIdScope === 'undefined' || - permissionsLevel === 'readOnly' || - rootDocIdScope === rootDocId + const allowUpdate = + !ignoreUpdates && + typeof rootDocIdScope !== 'undefined' && + permissionsLevel !== 'readOnly' && + rootDocIdScope !== rootDocId - if (!disallowChange) { + if (allowUpdate) { try { await saveProjectSettings({ projectId, rootDoc_id: rootDocId }) setRootDocIdScope(rootDocId) @@ -26,7 +31,13 @@ export default function useSetRootDocId() { } } }, - [permissionsLevel, projectId, rootDocIdScope, setRootDocIdScope] + [ + permissionsLevel, + projectId, + rootDocIdScope, + setRootDocIdScope, + ignoreUpdates, + ] ) return setRootDocId } diff --git a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-spell-check-language.tsx b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-spell-check-language.tsx index 413c2ead6f..61fa12820f 100644 --- a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-spell-check-language.tsx +++ b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-spell-check-language.tsx @@ -4,17 +4,25 @@ import { useProjectContext } from '../../../shared/context/project-context' import useScopeValue from '../../../shared/hooks/use-scope-value' import { saveProjectSettings, saveUserSettings } from '../utils/api' -export default function useSetSpellCheckLanguage() { +type UseSetSpellCheckLanguage = { + ignoreUpdates: boolean +} + +export default function useSetSpellCheckLanguage({ + ignoreUpdates, +}: UseSetSpellCheckLanguage) { const [spellCheckLanguageScope, setSpellCheckLanguageScope] = useScopeValue('project.spellCheckLanguage') const { _id: projectId } = useProjectContext() const setSpellCheckLanguage = useCallback( (spellCheckLanguage: string) => { - if ( - spellCheckLanguageScope && + const allowUpdate = + !ignoreUpdates && + spellCheckLanguage && spellCheckLanguage !== spellCheckLanguageScope - ) { + + if (allowUpdate) { sendMB('setting-changed', { changedSetting: 'spellCheckLanguage', changedSettingVal: spellCheckLanguage, @@ -27,7 +35,12 @@ export default function useSetSpellCheckLanguage() { saveUserSettings({ spellCheckLanguage }) } }, - [projectId, setSpellCheckLanguageScope, spellCheckLanguageScope] + [ + projectId, + setSpellCheckLanguageScope, + spellCheckLanguageScope, + ignoreUpdates, + ] ) return setSpellCheckLanguage