Просмотр исходного кода

BugFix: PersonalDropdown color scheme switch

Yuki Takei 5 лет назад
Родитель
Сommit
9e21a4d265

+ 31 - 19
src/client/js/components/Navbar/PersonalDropdown.jsx

@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { useState } from 'react';
 import PropTypes from 'prop-types';
 
 import { withTranslation } from 'react-i18next';
@@ -9,6 +9,15 @@ import { withUnstatedContainers } from '../UnstatedUtils';
 import AppContainer from '../../services/AppContainer';
 import NavigationContainer from '../../services/NavigationContainer';
 
+import {
+  isUserPreferenceExists,
+  isDarkMode as isDarkModeByUtil,
+  applyColorScheme,
+  removeUserPreference,
+  updateUserPreference,
+  updateUserPreferenceWithOsSettings,
+} from '../../util/color-scheme';
+
 import UserPicture from '../User/UserPicture';
 
 const PersonalDropdown = (props) => {
@@ -16,6 +25,9 @@ const PersonalDropdown = (props) => {
   const { t, appContainer, navigationContainer } = props;
   const user = appContainer.currentUser || {};
 
+  const [useOsSettings, setOsSettings] = useState(isUserPreferenceExists());
+  const [isDarkMode, setIsDarkMode] = useState(isDarkModeByUtil());
+
   const logoutHandler = () => {
     const { interceptorManager } = appContainer;
 
@@ -37,18 +49,25 @@ const PersonalDropdown = (props) => {
   };
 
   const followOsCheckboxModifiedHandler = (bool) => {
-    // reset user preference
     if (bool) {
-      appContainer.setColorSchemePreference(null);
+      removeUserPreference();
     }
-    // set preferDarkModeByMediaQuery as users preference
     else {
-      appContainer.setColorSchemePreference(appContainer.state.preferDarkModeByMediaQuery);
+      updateUserPreferenceWithOsSettings();
     }
+    applyColorScheme();
+
+    // update states
+    setOsSettings(bool);
+    setIsDarkMode(isDarkModeByUtil());
   };
 
   const userPreferenceSwitchModifiedHandler = (bool) => {
-    appContainer.setColorSchemePreference(bool);
+    updateUserPreference(bool);
+    applyColorScheme();
+
+    // update state
+    setIsDarkMode(isDarkModeByUtil());
   };
 
 
@@ -56,15 +75,8 @@ const PersonalDropdown = (props) => {
    * render
    */
   const {
-    preferDarkModeByMediaQuery, preferDarkModeByUser, preferDrawerModeByUser, preferDrawerModeOnEditByUser,
+    preferDrawerModeByUser, preferDrawerModeOnEditByUser,
   } = navigationContainer.state;
-  const isUserPreferenceExists = preferDarkModeByUser != null;
-  const isDarkMode = () => {
-    if (isUserPreferenceExists) {
-      return preferDarkModeByUser;
-    }
-    return preferDarkModeByMediaQuery;
-  };
 
   /* eslint-disable react/prop-types */
   const DrawerIcon = props => (
@@ -167,7 +179,7 @@ const PersonalDropdown = (props) => {
                   id="cbFollowOs"
                   className="custom-control-input"
                   type="checkbox"
-                  checked={!isUserPreferenceExists}
+                  checked={useOsSettings}
                   onChange={e => followOsCheckboxModifiedHandler(e.target.checked)}
                 />
                 <label className="custom-control-label text-nowrap" htmlFor="cbFollowOs">{t('personal_dropdown.use_os_settings')}</label>
@@ -176,19 +188,19 @@ const PersonalDropdown = (props) => {
           </div>
           <div className="form-row justify-content-center">
             <div className="form-group col-auto mb-0 d-flex align-items-center">
-              <span className={isUserPreferenceExists ? '' : 'text-muted'}>Light</span>
+              <span className={useOsSettings ? '' : 'text-muted'}>Light</span>
               <div className="custom-control custom-switch custom-checkbox-secondary ml-2">
                 <input
                   id="swUserPreference"
                   className="custom-control-input"
                   type="checkbox"
-                  checked={isDarkMode()}
-                  disabled={!isUserPreferenceExists}
+                  checked={isDarkMode}
+                  disabled={useOsSettings}
                   onChange={e => userPreferenceSwitchModifiedHandler(e.target.checked)}
                 />
                 <label className="custom-control-label" htmlFor="swUserPreference"></label>
               </div>
-              <span className={isUserPreferenceExists ? '' : 'text-muted'}>Dark</span>
+              <span className={useOsSettings ? '' : 'text-muted'}>Dark</span>
             </div>
           </div>
         </form>

+ 2 - 11
src/client/js/services/AppContainer.js

@@ -11,7 +11,6 @@ import GrowiRenderer from '../util/GrowiRenderer';
 import {
   mediaQueryListForDarkMode,
   applyColorScheme,
-  savePreferenceByUser,
 } from '../util/color-scheme';
 import Apiv1ErrorHandler from '../util/apiv1ErrorHandler';
 
@@ -37,6 +36,8 @@ export default class AppContainer extends Container {
     super();
 
     this.state = {
+      preferDarkModeByMediaQuery: false,
+
       // stetes for contents
       recentlyUpdatedPages: [],
     };
@@ -309,16 +310,6 @@ export default class AppContainer extends Container {
     targetComponent.launchDrawioModal(beginLineNumber, endLineNumber);
   }
 
-  /**
-   * Set color scheme preference by user
-   * @param {boolean} isDarkMode
-   */
-  async setColorSchemePreference(isDarkMode) {
-    this.setState({ preferDarkModeByUser: isDarkMode });
-    savePreferenceByUser(isDarkMode);
-    applyColorScheme();
-  }
-
   async apiGet(path, params) {
     return this.apiRequest('get', path, { params });
   }

+ 42 - 14
src/client/js/util/color-scheme.js

@@ -1,14 +1,27 @@
 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() {
-  const { preferDarkModeByUser } = localStorage;
-
   let isDarkMode = mediaQueryListForDarkMode.matches;
-  if (preferDarkModeByUser != null) {
-    isDarkMode = preferDarkModeByUser === 'true';
+  if (isUserPreferenceExists()) {
+    isDarkMode = isPreferedDarkModeByUser();
   }
 
   // switch to dark mode
@@ -24,22 +37,37 @@ function applyColorScheme() {
 }
 
 /**
- * Set color scheme preference by user
- * @param {boolean} isDarkMode
+ * Remove color scheme preference
  */
-function savePreferenceByUser(isDarkMode) {
-  // store settings to localStorage
-  const { localStorage } = window;
-  if (isDarkMode == null) {
+function removeUserPreference() {
+  if (isUserPreferenceExists()) {
     delete localStorage.removeItem('preferDarkModeByUser');
   }
-  else {
-    localStorage.preferDarkModeByUser = isDarkMode;
-  }
+}
+
+/**
+ * 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,
-  savePreferenceByUser,
+  removeUserPreference,
+  updateUserPreference,
+  updateUserPreferenceWithOsSettings,
 };