Yuki Takei 3 лет назад
Родитель
Сommit
d74c217075

+ 0 - 4
packages/app/src/client/boot.js

@@ -1,9 +1,5 @@
-// import {
-//   applyColorScheme,
-// } from './util/color-scheme';
 import {
   applyOldIos,
 } from './util/old-ios';
 
-// applyColorScheme();
 applyOldIos();

+ 0 - 73
packages/app/src/client/util/color-scheme.js

@@ -1,73 +0,0 @@
-const mediaQueryListForDarkMode = window.matchMedia('(prefers-color-scheme: dark)');
-
-function isUserPreferenceExists() {
-  return localStorage.preferDarkModeByUser != null;
-}
-
-function isPreferedDarkModeByUser() {
-  return localStorage.preferDarkModeByUser === 'true';
-}
-
-function isDarkMode() {
-  if (isUserPreferenceExists()) {
-    return isPreferedDarkModeByUser();
-  }
-  return mediaQueryListForDarkMode.matches;
-}
-
-/**
- * Apply color scheme as 'dark' attribute of <html></html>
- */
-function applyColorScheme() {
-  let isDarkMode = mediaQueryListForDarkMode.matches;
-  if (isUserPreferenceExists()) {
-    isDarkMode = isPreferedDarkModeByUser();
-  }
-
-  // switch to dark mode
-  if (isDarkMode) {
-    document.documentElement.removeAttribute('light');
-    document.documentElement.setAttribute('dark', 'true');
-  }
-  // switch to light mode
-  else {
-    document.documentElement.setAttribute('light', 'true');
-    document.documentElement.removeAttribute('dark');
-  }
-}
-
-/**
- * Remove color scheme preference
- */
-function removeUserPreference() {
-  if (isUserPreferenceExists()) {
-    delete localStorage.removeItem('preferDarkModeByUser');
-  }
-}
-
-/**
- * Set color scheme preference
- * @param {boolean} isDarkMode
- */
-function updateUserPreference(isDarkMode) {
-  // store settings to localStorage
-  localStorage.preferDarkModeByUser = isDarkMode;
-}
-
-/**
- * Set color scheme preference with OS settings
- */
-function updateUserPreferenceWithOsSettings() {
-  localStorage.preferDarkModeByUser = mediaQueryListForDarkMode.matches;
-}
-
-export {
-  mediaQueryListForDarkMode,
-  isUserPreferenceExists,
-  isPreferedDarkModeByUser,
-  isDarkMode,
-  applyColorScheme,
-  removeUserPreference,
-  updateUserPreference,
-  updateUserPreferenceWithOsSettings,
-};

+ 5 - 6
packages/app/src/components/Admin/Customize/CustomizeLayoutSetting.tsx

@@ -4,14 +4,13 @@ import { useTranslation } from 'next-i18next';
 
 import { toastSuccess, toastError } from '~/client/util/apiNotification';
 import { apiv3Get, apiv3Put } from '~/client/util/apiv3-client';
-import { isDarkMode as isDarkModeByUtil } from '~/client/util/color-scheme';
-
-const isDarkMode = isDarkModeByUtil();
-const colorText = isDarkMode ? 'dark' : 'light';
+import { useNextThemes } from '~/stores/use-next-themes';
 
 const CustomizeLayoutSetting = (): JSX.Element => {
   const { t } = useTranslation();
 
+  const { resolvedTheme } = useNextThemes();
+
   const [isContainerFluid, setIsContainerFluid] = useState(false);
   const [retrieveError, setRetrieveError] = useState();
 
@@ -54,7 +53,7 @@ const CustomizeLayoutSetting = (): JSX.Element => {
                 onClick={() => setIsContainerFluid(false)}
                 role="button"
               >
-                <img src={`/images/customize-settings/default-${colorText}.svg`} />
+                <img src={`/images/customize-settings/default-${resolvedTheme}.svg`} />
                 <div className="card-body text-center">
                   {t('admin:customize_setting.layout_options.default')}
                 </div>
@@ -64,7 +63,7 @@ const CustomizeLayoutSetting = (): JSX.Element => {
                 onClick={() => setIsContainerFluid(true)}
                 role="button"
               >
-                <img src={`/images/customize-settings/fluid-${colorText}.svg`} />
+                <img src={`/images/customize-settings/fluid-${resolvedTheme}.svg`} />
                 <div className="card-body  text-center">
                   {t('admin:customize_setting.layout_options.expanded')}
                 </div>

+ 12 - 28
packages/app/src/components/Navbar/AppearanceModeDropdown.tsx

@@ -1,5 +1,5 @@
 import React, {
-  FC, useState, useCallback, useRef,
+  FC, useCallback, useRef,
 } from 'react';
 
 import { useTranslation } from 'next-i18next';
@@ -7,15 +7,8 @@ import { useRipple } from 'react-use-ripple';
 import { UncontrolledTooltip } from 'reactstrap';
 
 import { useUserUISettings } from '~/client/services/user-ui-settings';
-import {
-  isUserPreferenceExists,
-  isDarkMode as isDarkModeByUtil,
-  applyColorScheme,
-  removeUserPreference,
-  updateUserPreference,
-  updateUserPreferenceWithOsSettings,
-} from '~/client/util/color-scheme';
 import { usePreferDrawerModeByUser, usePreferDrawerModeOnEditByUser } from '~/stores/ui';
+import { Themes, useNextThemes } from '~/stores/use-next-themes';
 
 import MoonIcon from '../Icons/MoonIcon';
 import SidebarDockIcon from '../Icons/SidebarDockIcon';
@@ -31,9 +24,9 @@ export const AppearanceModeDropdown:FC<AppearanceModeDropdownProps> = (props: Ap
 
   const { isAuthenticated } = props;
 
-  const [useOsSettings, setOsSettings] = useState(!isUserPreferenceExists());
-  const [isDarkMode, setIsDarkMode] = useState(isDarkModeByUtil());
-
+  const {
+    setTheme, resolvedTheme, useOsSettings, isDarkMode,
+  } = useNextThemes();
   const { data: isPreferDrawerMode, update: updatePreferDrawerMode } = usePreferDrawerModeByUser();
   const { data: isPreferDrawerModeOnEdit, mutate: mutatePreferDrawerModeOnEdit } = usePreferDrawerModeOnEditByUser();
   const { scheduleToPut } = useUserUISettings();
@@ -52,27 +45,18 @@ export const AppearanceModeDropdown:FC<AppearanceModeDropdownProps> = (props: Ap
     }
   }, [updatePreferDrawerMode, mutatePreferDrawerModeOnEdit, scheduleToPut]);
 
-  const followOsCheckboxModifiedHandler = useCallback((useOsSettings: boolean) => {
-    if (useOsSettings) {
-      removeUserPreference();
+  const followOsCheckboxModifiedHandler = useCallback((isChecked: boolean) => {
+    if (isChecked) {
+      setTheme(Themes.system);
     }
     else {
-      updateUserPreferenceWithOsSettings();
+      setTheme(resolvedTheme ?? Themes.light);
     }
-    applyColorScheme();
-
-    // update states
-    setOsSettings(useOsSettings);
-    setIsDarkMode(isDarkModeByUtil());
-  }, []);
+  }, [resolvedTheme, setTheme]);
 
   const userPreferenceSwitchModifiedHandler = useCallback((isDarkMode: boolean) => {
-    updateUserPreference(isDarkMode);
-    applyColorScheme();
-
-    // update state
-    setIsDarkMode(isDarkModeByUtil());
-  }, []);
+    setTheme(isDarkMode ? 'dark' : 'light');
+  }, [setTheme]);
 
   /* eslint-disable react/prop-types */
   const IconWithTooltip = ({

+ 4 - 3
packages/app/src/components/PageEditor/EmojiPicker.tsx

@@ -3,7 +3,7 @@ import React, { FC } from 'react';
 import { Picker } from 'emoji-mart';
 import { Modal } from 'reactstrap';
 
-import { isDarkMode } from '~/client/util/color-scheme';
+import { useNextThemes } from '~/stores/use-next-themes';
 
 import EmojiPickerHelper, { getEmojiTranslation } from './EmojiPickerHelper';
 
@@ -20,6 +20,8 @@ const EmojiPicker: FC<Props> = (props: Props) => {
     onClose, emojiSearchText, emojiPickerHelper, isOpen,
   } = props;
 
+  const { resolvedTheme } = useNextThemes();
+
   // Set search emoji input and trigger search
   const searchEmoji = () => {
     const input = window.document.querySelector('[id^="emoji-mart-search"]') as HTMLInputElement;
@@ -42,7 +44,6 @@ const EmojiPicker: FC<Props> = (props: Props) => {
 
 
   const translation = getEmojiTranslation();
-  const theme = isDarkMode() ? 'dark' : 'light';
 
   return (
     <Modal isOpen={isOpen} toggle={onClose} onOpened={searchEmoji} backdropClassName="emoji-picker-modal" fade={false}>
@@ -52,7 +53,7 @@ const EmojiPicker: FC<Props> = (props: Props) => {
         title={translation.title}
         emojiTooltip
         style={emojiPickerHelper.setStyle()}
-        theme={theme}
+        theme={resolvedTheme}
       />
     </Modal>
   );

+ 22 - 0
packages/app/src/stores/use-next-themes.ts

@@ -0,0 +1,22 @@
+import { useTheme } from 'next-themes';
+import { UseThemeProps } from 'next-themes/dist/types';
+
+export const Themes = {
+  light: 'light',
+  dark: 'dark',
+  system: 'system',
+} as const;
+export type Themes = typeof Themes[keyof typeof Themes];
+
+export type NextThemesComputedValues = {
+  useOsSettings: boolean,
+  isDarkMode: boolean,
+}
+
+export const useNextThemes = (): UseThemeProps & NextThemesComputedValues => {
+  const props = useTheme();
+  return Object.assign(props, {
+    useOsSettings: props.theme === Themes.system,
+    isDarkMode: props.resolvedTheme === Themes.dark,
+  });
+};