2
0

useHandleAppTheme.ts 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. import { useEffect, useLayoutEffect, useState } from "react";
  2. import { THEME } from "../packages/excalidraw";
  3. import { EVENT } from "../packages/excalidraw/constants";
  4. import type { Theme } from "../packages/excalidraw/element/types";
  5. import { CODES, KEYS } from "../packages/excalidraw/keys";
  6. import { STORAGE_KEYS } from "./app_constants";
  7. const getDarkThemeMediaQuery = (): MediaQueryList | undefined =>
  8. window.matchMedia?.("(prefers-color-scheme: dark)");
  9. export const useHandleAppTheme = () => {
  10. const [appTheme, setAppTheme] = useState<Theme | "system">(() => {
  11. return (
  12. (localStorage.getItem(STORAGE_KEYS.LOCAL_STORAGE_THEME) as
  13. | Theme
  14. | "system"
  15. | null) || THEME.LIGHT
  16. );
  17. });
  18. const [editorTheme, setEditorTheme] = useState<Theme>(THEME.LIGHT);
  19. useEffect(() => {
  20. const mediaQuery = getDarkThemeMediaQuery();
  21. const handleChange = (e: MediaQueryListEvent) => {
  22. setEditorTheme(e.matches ? THEME.DARK : THEME.LIGHT);
  23. };
  24. if (appTheme === "system") {
  25. mediaQuery?.addEventListener("change", handleChange);
  26. }
  27. const handleKeydown = (event: KeyboardEvent) => {
  28. if (
  29. !event[KEYS.CTRL_OR_CMD] &&
  30. event.altKey &&
  31. event.shiftKey &&
  32. event.code === CODES.D
  33. ) {
  34. event.preventDefault();
  35. event.stopImmediatePropagation();
  36. setAppTheme(editorTheme === THEME.DARK ? THEME.LIGHT : THEME.DARK);
  37. }
  38. };
  39. document.addEventListener(EVENT.KEYDOWN, handleKeydown, { capture: true });
  40. return () => {
  41. mediaQuery?.removeEventListener("change", handleChange);
  42. document.removeEventListener(EVENT.KEYDOWN, handleKeydown, {
  43. capture: true,
  44. });
  45. };
  46. }, [appTheme, editorTheme, setAppTheme]);
  47. useLayoutEffect(() => {
  48. localStorage.setItem(STORAGE_KEYS.LOCAL_STORAGE_THEME, appTheme);
  49. if (appTheme === "system") {
  50. setEditorTheme(
  51. getDarkThemeMediaQuery()?.matches ? THEME.DARK : THEME.LIGHT,
  52. );
  53. } else {
  54. setEditorTheme(appTheme);
  55. }
  56. }, [appTheme]);
  57. return { editorTheme, appTheme, setAppTheme };
  58. };