use-set-overall-theme.tsx 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { useCallback, useEffect, useState } from 'react'
  2. import _ from 'lodash'
  3. import useScopeValue from '../../../shared/hooks/use-scope-value'
  4. import type { OverallThemeMeta } from '../../../../../types/project-settings'
  5. import { saveUserSettings, type UserSettings } from '../utils/api'
  6. export default function useSetOverallTheme() {
  7. const [chosenTheme, setChosenTheme] = useState<OverallThemeMeta | null>(null)
  8. const [loadingStyleSheet, setLoadingStyleSheet] = useScopeValue<boolean>(
  9. 'ui.loadingStyleSheet'
  10. )
  11. const [overallTheme, setOverallTheme] = useScopeValue<
  12. UserSettings['overallTheme']
  13. >('settings.overallTheme')
  14. useEffect(() => {
  15. const docHeadEl = document.querySelector('head')
  16. const oldStyleSheetEl = document.getElementById('main-stylesheet')
  17. const newStyleSheetEl = document.createElement('link')
  18. newStyleSheetEl.setAttribute('rel', 'stylesheet')
  19. newStyleSheetEl.setAttribute('id', 'main-stylesheet')
  20. newStyleSheetEl.setAttribute('href', chosenTheme?.path ?? '')
  21. const loadEventCallback = () => {
  22. setLoadingStyleSheet(false)
  23. if (docHeadEl && oldStyleSheetEl) {
  24. docHeadEl.removeChild(oldStyleSheetEl)
  25. }
  26. }
  27. if (loadingStyleSheet) {
  28. newStyleSheetEl.addEventListener('load', loadEventCallback, {
  29. once: true,
  30. })
  31. docHeadEl?.appendChild(newStyleSheetEl)
  32. }
  33. return () => {
  34. newStyleSheetEl.removeEventListener('load', loadEventCallback)
  35. }
  36. }, [loadingStyleSheet, setLoadingStyleSheet, chosenTheme?.path])
  37. return useCallback(
  38. (newOverallTheme: UserSettings['overallTheme']) => {
  39. if (overallTheme !== newOverallTheme) {
  40. const chosenTheme = _.find(
  41. window.overallThemes,
  42. theme => theme.val === newOverallTheme
  43. )
  44. if (chosenTheme) {
  45. setLoadingStyleSheet(true)
  46. setChosenTheme(chosenTheme)
  47. setOverallTheme(newOverallTheme)
  48. saveUserSettings('overallTheme', newOverallTheme)
  49. }
  50. }
  51. },
  52. [overallTheme, setLoadingStyleSheet, setOverallTheme]
  53. )
  54. }