From eec3b11f342ef1fa275b7af410dfb7b63715ad8c Mon Sep 17 00:00:00 2001 From: M Fahru Date: Fri, 23 Dec 2022 16:06:19 -0700 Subject: [PATCH] Migrate updating overallTheme to react GitOrigin-RevId: 024ceb3c32c8d90ac0067fbb72d6e7d327b869f0 --- .../hooks/use-set-overall-theme.tsx | 65 +++++++++++++++++++ .../hooks/use-set-user-wide-settings.tsx | 36 ++-------- .../js/features/editor-left-menu/utils/api.ts | 26 ++++++++ services/web/types/window.ts | 2 + 4 files changed, 97 insertions(+), 32 deletions(-) create mode 100644 services/web/frontend/js/features/editor-left-menu/hooks/use-set-overall-theme.tsx create mode 100644 services/web/frontend/js/features/editor-left-menu/utils/api.ts diff --git a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-overall-theme.tsx b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-overall-theme.tsx new file mode 100644 index 0000000000..7390ca3e48 --- /dev/null +++ b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-overall-theme.tsx @@ -0,0 +1,65 @@ +import { useCallback, useEffect, useState } from 'react' +import _ from 'lodash' +import { OverallTheme } from '../../../../../modules/source-editor/frontend/js/extensions/theme' +import useScopeValue from '../../../shared/hooks/use-scope-value' +import { OverallThemeMeta } from '../../../../../types/project-settings' +import { saveUserSettings } from '../utils/api' + +export default function useSetOverallTheme() { + const [loadingStyleSheet, setLoadingStyleSheet] = useScopeValue('ui.loadingStyleSheet') + const [chosenTheme, setChosenTheme] = useState(null) + const [overallThemeScope, setOverallThemeScope] = useScopeValue( + 'settings.overallTheme' + ) + + useEffect(() => { + const docHeadEl = document.querySelector('head') + const oldStyleSheetEl = document.getElementById('main-stylesheet') + + const newStyleSheetEl = document.createElement('link') + newStyleSheetEl.setAttribute('rel', 'stylesheet') + newStyleSheetEl.setAttribute('id', 'main-stylesheet') + newStyleSheetEl.setAttribute('href', chosenTheme?.path ?? '') + + const loadEventCallback = () => { + setLoadingStyleSheet(false) + + if (docHeadEl && oldStyleSheetEl) { + docHeadEl.removeChild(oldStyleSheetEl) + } + } + + if (loadingStyleSheet) { + newStyleSheetEl.addEventListener('load', loadEventCallback, { + once: true, + }) + + docHeadEl?.appendChild(newStyleSheetEl) + } + + return () => { + newStyleSheetEl.removeEventListener('load', loadEventCallback) + } + }, [loadingStyleSheet, setLoadingStyleSheet, chosenTheme?.path]) + + const setOverallTheme = useCallback( + (overallTheme: OverallTheme) => { + if (overallThemeScope !== overallTheme) { + const chosenTheme = _.find( + window.overallThemes, + theme => theme.val === overallTheme + ) + + if (chosenTheme) { + setLoadingStyleSheet(true) + setChosenTheme(chosenTheme) + setOverallThemeScope(overallTheme) + saveUserSettings({ overallTheme }) + } + } + }, + [overallThemeScope, setLoadingStyleSheet, setOverallThemeScope] + ) + + return setOverallTheme +} diff --git a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-user-wide-settings.tsx b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-user-wide-settings.tsx index bdb9b814b5..aa0471d1a9 100644 --- a/services/web/frontend/js/features/editor-left-menu/hooks/use-set-user-wide-settings.tsx +++ b/services/web/frontend/js/features/editor-left-menu/hooks/use-set-user-wide-settings.tsx @@ -2,30 +2,12 @@ import { useCallback } from 'react' import { FontFamily, LineHeight, - OverallTheme, } from '../../../../../modules/source-editor/frontend/js/extensions/theme' import { Keybindings, PdfViewer } from '../../../../../types/project-settings' -import { postJSON } from '../../../infrastructure/fetch-json' import useScopeValue from '../../../shared/hooks/use-scope-value' - -type UserSettingsScope = { - pdfViewer: PdfViewer - autoComplete: boolean - autoPairDelimiters: boolean - syntaxValidation: boolean - editorTheme: string - overallTheme: OverallTheme - mode: Keybindings - fontSize: string - fontFamily: FontFamily - lineHeight: LineHeight -} - -function saveUserSettings(data: Partial) { - postJSON('/user/settings', { - body: data, - }) -} +import { saveUserSettings } from '../utils/api' +import type { UserSettingsScope } from '../utils/api' +import useSetOverallTheme from './use-set-overall-theme' export default function useSetUserWideSettings() { const [userSettings, setUserSettings] = useScopeValue( @@ -33,6 +15,7 @@ export default function useSetUserWideSettings() { true ) + const setOverallTheme = useSetOverallTheme() const setAutoComplete = useCallback( (autoComplete: boolean) => { if (userSettings.autoComplete !== autoComplete) { @@ -73,17 +56,6 @@ export default function useSetUserWideSettings() { [userSettings, setUserSettings] ) - // TODO: business logic - const setOverallTheme = useCallback( - (overallTheme: OverallTheme) => { - if (userSettings.overallTheme !== overallTheme) { - setUserSettings({ ...userSettings, overallTheme }) - saveUserSettings({ overallTheme }) - } - }, - [userSettings, setUserSettings] - ) - const setMode = useCallback( (mode: Keybindings) => { if (userSettings.mode !== mode) { diff --git a/services/web/frontend/js/features/editor-left-menu/utils/api.ts b/services/web/frontend/js/features/editor-left-menu/utils/api.ts new file mode 100644 index 0000000000..d8d04d22b9 --- /dev/null +++ b/services/web/frontend/js/features/editor-left-menu/utils/api.ts @@ -0,0 +1,26 @@ +import { + FontFamily, + LineHeight, + OverallTheme, +} from '../../../../../modules/source-editor/frontend/js/extensions/theme' +import { Keybindings, PdfViewer } from '../../../../../types/project-settings' +import { postJSON } from '../../../infrastructure/fetch-json' + +export type UserSettingsScope = { + pdfViewer: PdfViewer + autoComplete: boolean + autoPairDelimiters: boolean + syntaxValidation: boolean + editorTheme: string + overallTheme: OverallTheme + mode: Keybindings + fontSize: string + fontFamily: FontFamily + lineHeight: LineHeight +} + +export function saveUserSettings(data: Partial) { + postJSON('/user/settings', { + body: data, + }) +} diff --git a/services/web/types/window.ts b/services/web/types/window.ts index 80d4acf8b6..3ca12be73f 100644 --- a/services/web/types/window.ts +++ b/services/web/types/window.ts @@ -1,5 +1,6 @@ import { ExposedSettings } from './exposed-settings' import { OAuthProviders } from './oauth-providers' +import { OverallThemeMeta } from './project-settings' import { User } from './user' declare global { @@ -31,5 +32,6 @@ declare global { MathJax: { Hub: Record } + overallThemes: OverallThemeMeta[] } }