Browse Source

refactor breakpoint event handling

Yuki Takei 5 years ago
parent
commit
06c5e6fe61

+ 25 - 37
src/client/js/components/Sidebar.jsx

@@ -38,44 +38,32 @@ class Sidebar extends React.Component {
   initBreakpointEvents() {
     const { appContainer, navigationUIController } = this.props;
 
-    document.addEventListener('DOMContentLoaded', () => {
-      // get the value of '--breakpoint-*'
-      // const breakpointSm = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue('--breakpoint-sm'), 10);
-      const breakpointMd = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue('--breakpoint-md'), 10);
-
-      const smHandler = (mql) => {
-        if (mql.matches) {
-          // cache width
-          this.sidebarWidthCached = navigationUIController.state.productNavWidth;
-
-          appContainer.setState({ isDrawerOpened: false });
-          navigationUIController.disableResize();
-          navigationUIController.expand();
-
-          // fix width
-          navigationUIController.setState({ productNavWidth: sidebarDefaultWidth });
+    const mdOrAvobeHandler = (mql) => {
+      // md or above
+      if (mql.matches) {
+        appContainer.setState({ isDrawerOpened: false });
+        navigationUIController.enableResize();
+
+        // restore width
+        if (this.sidebarWidthCached != null) {
+          navigationUIController.setState({ productNavWidth: this.sidebarWidthCached });
         }
-        else {
-          appContainer.setState({ isDrawerOpened: false });
-          navigationUIController.enableResize();
-
-          // restore width
-          if (this.sidebarWidthCached != null) {
-            navigationUIController.setState({ productNavWidth: this.sidebarWidthCached });
-          }
-        }
-      };
-
-      // const mediaQueryForXs = window.matchMedia(`(max-width: ${breakpointSm}px)`);
-      const mediaQueryForSm = window.matchMedia(`(max-width: ${breakpointMd}px)`);
-
-      // add event listener
-      // mediaQueryForXs.addListener(xsHandler);
-      mediaQueryForSm.addListener(smHandler);
-      // initialize
-      // xsHandler(mediaQueryForXs);
-      smHandler(mediaQueryForSm);
-    });
+      }
+      // sm or below
+      else {
+        // cache width
+        this.sidebarWidthCached = navigationUIController.state.productNavWidth;
+
+        appContainer.setState({ isDrawerOpened: false });
+        navigationUIController.disableResize();
+        navigationUIController.expand();
+
+        // fix width
+        navigationUIController.setState({ productNavWidth: sidebarDefaultWidth });
+      }
+    };
+
+    appContainer.addBreakpointEvents('md', mdOrAvobeHandler, true);
   }
 
   backdropClickedHandler = () => {

+ 35 - 1
src/client/js/services/AppContainer.js

@@ -33,6 +33,7 @@ export default class AppContainer extends Container {
       editorMode: null,
       preferDarkModeByMediaQuery: false,
       preferDarkModeByUser: null,
+      breakpoint: 'xs',
       isDrawerOpened: false,
 
       isPageCreateModalShown: false,
@@ -108,11 +109,22 @@ export default class AppContainer extends Container {
   }
 
   init() {
-    // this.initBreakpointEvents();
+    this.initBreakpointEvents();
     this.initColorScheme();
     this.initPlugins();
   }
 
+  initBreakpointEvents() {
+    // TODO: fix bug -- 2020.05.26
+    // ['xs', 'sm', 'md', 'lg', 'xl'].forEach((breakpoint) => {
+    //   this.addBreakpointEvents(breakpoint, (mql) => {
+    //     if (mql.matches) {
+    //       this.setState({ breakpoint });
+    //     }
+    //   }, true);
+    // });
+  }
+
   async initColorScheme() {
     const switchStateByMediaQuery = (mql) => {
       const preferDarkMode = mql.matches;
@@ -233,6 +245,28 @@ export default class AppContainer extends Container {
     return this.componentInstances[id];
   }
 
+  /**
+   *
+   * @param {string} breakpoint id of breakpoint
+   * @param {function} handler event handler for media query
+   * @param {boolean} invokeOnInit invoke handler after the initialization if true
+   */
+  addBreakpointEvents(breakpoint, handler, invokeOnInit = false) {
+    document.addEventListener('DOMContentLoaded', () => {
+      // get the value of '--breakpoint-*'
+      const breakpointPixel = parseInt(window.getComputedStyle(document.documentElement).getPropertyValue(`--breakpoint-${breakpoint}`), 10);
+
+      const mediaQuery = window.matchMedia(`(min-width: ${breakpointPixel}px)`);
+
+      // add event listener
+      mediaQuery.addListener(handler);
+      // initialize
+      if (invokeOnInit) {
+        handler(mediaQuery);
+      }
+    });
+  }
+
   getOriginRenderer() {
     return this.originRenderer;
   }

+ 23 - 26
src/server/views/layout/layout.html

@@ -86,34 +86,28 @@
       </a>
     </div>
 
-    {# Search #}
-    {% if isSearchServiceConfigured() %}
-    <ul class="navbar-nav grw-navbar-search d-none d-md-block">
-      <li>
-        <div id="grw-search-top" class="search-top" role="search"></div>
-      </li>
-    </ul>
-    {% endif %}
-
     {# Navbar Right #}
     <ul class="navbar-nav ml-auto">
       {% if user %}
-      <!-- TODO GW-79 enable after refactoring  <li id="create-page-button" class="nav-item d-none d-md-block"></li> -->
-      <li class="nav-item d-none d-md-block">
-        <a class="nav-link create-page px-4" href="#" data-target="#create-page" data-toggle="modal">
-          <i class="icon-pencil mr-2"></i>
-          <span>{{ t('New') }}</span>
-        </a>
-      </li>
-      <li class="nav-item d-md-none">
-        <a type="button" class="nav-link px-4" data-target="#grw-search-top-collapse" data-toggle="collapse">
-          <i class="icon-magnifier mr-2"></i>
-        </a>
-      </li>
-      <li id="personal-dropdown" class="nav-item dropdown dropdown-toggle"></li>
+        <!-- TODO GW-79 enable after refactoring  <li id="create-page-button" class="nav-item d-none d-md-block"></li> -->
+        <li class="nav-item d-none d-md-block">
+          <a class="nav-link create-page px-4" href="#" data-target="#create-page" data-toggle="modal">
+            <i class="icon-pencil mr-2"></i>
+            <span>{{ t('New') }}</span>
+          </a>
+        </li>
+        {% if isSearchServiceConfigured() %}
+          <li class="nav-item d-md-none">
+            <a type="button" class="nav-link px-4" data-target="#grw-search-top-collapse" data-toggle="collapse">
+              <i class="icon-magnifier mr-2"></i>
+            </a>
+          </li>
+        {% endif %}
+        <li id="personal-dropdown" class="nav-item dropdown dropdown-toggle"></li>
       {% else %}
-      <li id="login-user" class="nav-item"><a class="nav-link" href="/login">Login</a></li>
+        <li id="login-user" class="nav-item"><a class="nav-link" href="/login">Login</a></li>
       {% endif %}
+
       {% if getConfig('crowi', 'app:confidential') %}
       <li class="nav-item confidential text-light">{{ getConfig('crowi', 'app:confidential') }}</li>
       {% endif %}
@@ -133,9 +127,12 @@
     <div class="flex-grow-1">
       {% block head_warn_alert_siteurl_undefined %}{% include '../widget/alert_siteurl_undefined.html' %}{% endblock %}
 
-      <div id="grw-search-top-collapse" class="collapse d-md-none p-3">
-        <div id="grw-search-top-for-mobile" class="search-top" role="search"></div>
-      </div>
+      {# Search #}
+      {% if isSearchServiceConfigured() %}
+        <div id="grw-search-top-collapse" class="collapse bg-dark p-3">
+          <div id="grw-search-top" class="search-top" role="search"></div>
+        </div>
+      {% endif %}
 
       {% block layout_main %}{% endblock %}
     </div>