You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

56 lines
1.7 KiB

11 months ago
10 months ago
11 months ago
  1. import { REFETCH_LOGO_EVENT } from "@/LogoContext";
  2. import { useState, useEffect } from "react";
  3. const availableThemes = {
  4. default: "默认",
  5. light: "高亮",
  6. };
  7. /**
  8. * Determines the current theme of the application
  9. * @returns {{theme: ('default' | 'light'), setTheme: function, availableThemes: object}} The current theme, a function to set the theme, and the available themes
  10. */
  11. export function useTheme() {
  12. const [theme, _setTheme] = useState(() => {
  13. return localStorage.getItem("theme") || "default";
  14. });
  15. useEffect(() => {
  16. if (localStorage.getItem("theme") !== null) return;
  17. if (!window.matchMedia) return;
  18. if (window.matchMedia("(prefers-color-scheme: light)").matches)
  19. return _setTheme("light");
  20. _setTheme("default");
  21. }, []);
  22. useEffect(() => {
  23. document.documentElement.setAttribute("data-theme", theme);
  24. document.body.classList.toggle("light", theme === "light");
  25. localStorage.setItem("theme", theme);
  26. window.dispatchEvent(new Event(REFETCH_LOGO_EVENT));
  27. }, [theme]);
  28. // In development, attach keybind combinations to toggle theme
  29. useEffect(() => {
  30. if (!import.meta.env.DEV) return;
  31. function toggleOnKeybind(e) {
  32. if (e.metaKey && e.key === ".") {
  33. e.preventDefault();
  34. setTheme((prev) => (prev === "light" ? "default" : "light"));
  35. }
  36. }
  37. document.addEventListener("keydown", toggleOnKeybind);
  38. return () => document.removeEventListener("keydown", toggleOnKeybind);
  39. }, []);
  40. /**
  41. * Sets the theme of the application and runs any
  42. * other necessary side effects
  43. * @param {string} newTheme The new theme to set
  44. */
  45. function setTheme(newTheme) {
  46. _setTheme(newTheme);
  47. }
  48. return { theme, setTheme, availableThemes };
  49. }