use-active-overall-theme.tsx 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. import { useUserSettingsContext } from '@/shared/context/user-settings-context'
  2. import { OverallTheme } from '@/shared/utils/styles'
  3. import { isIEEEBranded } from '@/utils/is-ieee-branded'
  4. import { useEffect, useMemo, useState } from 'react'
  5. export type ActiveOverallTheme = 'dark' | 'light'
  6. const mediaWatcher = window.matchMedia?.('(prefers-color-scheme: dark)') ?? {
  7. // If matchMedia is not supported, use the default (dark) theme
  8. matches: true,
  9. addEventListener: () => {},
  10. removeEventListener: () => {},
  11. }
  12. function getTheme(
  13. overallTheme: OverallTheme,
  14. prefersDark: boolean
  15. ): ActiveOverallTheme {
  16. if (isIEEEBranded()) {
  17. return 'dark'
  18. }
  19. if (overallTheme === 'light-') {
  20. return 'light'
  21. }
  22. if (overallTheme === 'system') {
  23. return prefersDark ? 'dark' : 'light'
  24. }
  25. return 'dark'
  26. }
  27. export const useActiveOverallTheme = (): ActiveOverallTheme => {
  28. const [browserPrefersDarkMode, setBrowserPrefersDarkMode] = useState(
  29. mediaWatcher.matches
  30. )
  31. const {
  32. userSettings: { overallTheme },
  33. } = useUserSettingsContext()
  34. const activeOverallTheme = useMemo<ActiveOverallTheme>(() => {
  35. return getTheme(overallTheme, browserPrefersDarkMode)
  36. }, [overallTheme, browserPrefersDarkMode])
  37. useEffect(() => {
  38. const listener = (e: MediaQueryListEvent) => {
  39. setBrowserPrefersDarkMode(e.matches)
  40. }
  41. mediaWatcher.addEventListener('change', listener)
  42. return () => {
  43. mediaWatcher.removeEventListener('change', listener)
  44. }
  45. }, [])
  46. return activeOverallTheme
  47. }