about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch/features
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/flavours/glitch/features')
-rw-r--r--app/javascript/flavours/glitch/features/ui/index.js114
1 files changed, 54 insertions, 60 deletions
diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js
index 2be6d9478..c861f5568 100644
--- a/app/javascript/flavours/glitch/features/ui/index.js
+++ b/app/javascript/flavours/glitch/features/ui/index.js
@@ -5,13 +5,14 @@ import LoadingBarContainer from './containers/loading_bar_container';
 import ModalContainer from './containers/modal_container';
 import { connect } from 'react-redux';
 import { Redirect, withRouter } from 'react-router-dom';
-import { isMobile } from 'flavours/glitch/util/is_mobile';
+import { layoutFromWindow } from 'flavours/glitch/util/is_mobile';
 import { debounce } from 'lodash';
 import { uploadCompose, resetCompose, changeComposeSpoilerness } from 'flavours/glitch/actions/compose';
 import { expandHomeTimeline } from 'flavours/glitch/actions/timelines';
 import { expandNotifications, notificationsSetVisibility } from 'flavours/glitch/actions/notifications';
 import { fetchRules } from 'flavours/glitch/actions/rules';
 import { clearHeight } from 'flavours/glitch/actions/height_cache';
+import { changeLayout } from 'flavours/glitch/actions/app';
 import { synchronouslySubmitMarkers, submitMarkers, fetchMarkers } from 'flavours/glitch/actions/markers';
 import { WrappedSwitch, WrappedRoute } from 'flavours/glitch/util/react_router_helpers';
 import UploadArea from './components/upload_area';
@@ -66,10 +67,12 @@ const messages = defineMessages({
 });
 
 const mapStateToProps = state => ({
+  layout: state.getIn(['meta', 'layout']),
   hasComposingText: state.getIn(['compose', 'text']).trim().length !== 0,
   hasMediaAttachments: state.getIn(['compose', 'media_attachments']).size > 0,
   canUploadMore: !state.getIn(['compose', 'media_attachments']).some(x => ['audio', 'video'].includes(x.get('type'))) && state.getIn(['compose', 'media_attachments']).size < 4,
-  layout: state.getIn(['local_settings', 'layout']),
+  layout: state.getIn(['meta', 'layout']),
+  layout_local_setting: state.getIn(['local_settings', 'layout']),
   isWide: state.getIn(['local_settings', 'stretch']),
   navbarUnder: state.getIn(['local_settings', 'navbar_under']),
   dropdownMenuIsOpen: state.getIn(['dropdown_menu', 'openId']) !== null,
@@ -120,26 +123,13 @@ class SwitchingColumnsArea extends React.PureComponent {
 
   static propTypes = {
     children: PropTypes.node,
-    layout: PropTypes.string,
     location: PropTypes.object,
     navbarUnder: PropTypes.bool,
-    onLayoutChange: PropTypes.func.isRequired,
+    mobile: PropTypes.bool,
   };
 
-  state = {
-    mobile: isMobile(window.innerWidth, this.props.layout),
-  };
-
-  componentWillReceiveProps (nextProps) {
-    if (nextProps.layout !== this.props.layout) {
-      this.setState({ mobile: isMobile(window.innerWidth, nextProps.layout) });
-    }
-  }
-
   componentWillMount () {
-    window.addEventListener('resize', this.handleResize, { passive: true });
-
-    if (this.state.mobile) {
+    if (this.props.mobile) {
       document.body.classList.toggle('layout-single-column', true);
       document.body.classList.toggle('layout-multiple-columns', false);
     } else {
@@ -148,37 +138,14 @@ class SwitchingColumnsArea extends React.PureComponent {
     }
   }
 
-  componentDidUpdate (prevProps, prevState) {
+  componentDidUpdate (prevProps) {
     if (![this.props.location.pathname, '/'].includes(prevProps.location.pathname)) {
       this.node.handleChildrenContentChange();
     }
 
-    if (prevState.mobile !== this.state.mobile) {
-      document.body.classList.toggle('layout-single-column', this.state.mobile);
-      document.body.classList.toggle('layout-multiple-columns', !this.state.mobile);
-    }
-  }
-
-  componentWillUnmount () {
-    window.removeEventListener('resize', this.handleResize);
-  }
-
-  handleLayoutChange = debounce(() => {
-    // The cached heights are no longer accurate, invalidate
-    this.props.onLayoutChange();
-  }, 500, {
-    trailing: true,
-  })
-
-  handleResize = () => {
-    const mobile = isMobile(window.innerWidth, this.props.layout);
-
-    if (mobile !== this.state.mobile) {
-      this.handleLayoutChange.cancel();
-      this.props.onLayoutChange();
-      this.setState({ mobile });
-    } else {
-      this.handleLayoutChange();
+    if (prevProps.mobile !== this.props.mobile) {
+      document.body.classList.toggle('layout-single-column', this.props.mobile);
+      document.body.classList.toggle('layout-multiple-columns', !this.props.mobile);
     }
   }
 
@@ -189,12 +156,11 @@ class SwitchingColumnsArea extends React.PureComponent {
   }
 
   render () {
-    const { children, navbarUnder } = this.props;
-    const singleColumn = this.state.mobile;
-    const redirect = singleColumn ? <Redirect from='/' to='/home' exact /> : <Redirect from='/' to='/getting-started' exact />;
+    const { children, mobile, navbarUnder } = this.props;
+    const redirect = mobile ? <Redirect from='/' to='/home' exact /> : <Redirect from='/' to='/getting-started' exact />;
 
     return (
-      <ColumnsAreaContainer ref={this.setRef} singleColumn={singleColumn} navbarUnder={navbarUnder}>
+      <ColumnsAreaContainer ref={this.setRef} singleColumn={mobile} navbarUnder={navbarUnder}>
         <WrappedSwitch>
           {redirect}
           <WrappedRoute path='/getting-started' component={GettingStarted} content={children} />
@@ -256,7 +222,7 @@ class UI extends React.Component {
   static propTypes = {
     dispatch: PropTypes.func.isRequired,
     children: PropTypes.node,
-    layout: PropTypes.string,
+    layout_local_setting: PropTypes.string,
     isWide: PropTypes.bool,
     systemFontUi: PropTypes.bool,
     navbarUnder: PropTypes.bool,
@@ -272,6 +238,7 @@ class UI extends React.Component {
     unreadNotifications: PropTypes.number,
     showFaviconBadge: PropTypes.bool,
     moved: PropTypes.map,
+    layout: PropTypes.string.isRequired,
     firstLaunch: PropTypes.bool,
     username: PropTypes.string,
   };
@@ -293,11 +260,6 @@ class UI extends React.Component {
     }
   }
 
-  handleLayoutChange = () => {
-    // The cached heights are no longer accurate, invalidate
-    this.props.dispatch(clearHeight());
-  }
-
   handleDragEnter = (e) => {
     e.preventDefault();
 
@@ -378,8 +340,27 @@ class UI extends React.Component {
     }
   }
 
-  componentWillMount () {
+  handleLayoutChange = debounce(() => {
+    this.props.dispatch(clearHeight()); // The cached heights are no longer accurate, invalidate
+  }, 500, {
+    trailing: true,
+  });
+
+  handleResize = () => {
+    const layout = layoutFromWindow(this.props.layout_local_setting);
+
+    if (layout !== this.props.layout) {
+      this.handleLayoutChange.cancel();
+      this.props.dispatch(changeLayout(layout));
+    } else {
+      this.handleLayoutChange();
+    }
+  }
+
+  componentDidMount () {
     window.addEventListener('beforeunload', this.handleBeforeUnload, false);
+    window.addEventListener('resize', this.handleResize, { passive: true });
+
     document.addEventListener('dragenter', this.handleDragEnter, false);
     document.addEventListener('dragover', this.handleDragOver, false);
     document.addEventListener('drop', this.handleDrop, false);
@@ -403,9 +384,7 @@ class UI extends React.Component {
     this.props.dispatch(expandNotifications());
 
     setTimeout(() => this.props.dispatch(fetchRules()), 3000);
-  }
 
-  componentDidMount () {
     this.hotkeys.__mousetrap__.stopCallback = (e, element) => {
       return ['TEXTAREA', 'SELECT', 'INPUT'].includes(element.tagName);
     };
@@ -427,6 +406,19 @@ class UI extends React.Component {
     }
   }
 
+  componentWillReceiveProps (nextProps) {
+    if (nextProps.layout_local_setting !== this.props.layout_local_setting) {
+      const layout = layoutFromWindow(nextProps.layout_local_setting);
+
+      if (layout !== this.props.layout) {
+        this.handleLayoutChange.cancel();
+        this.props.dispatch(changeLayout(layout));
+      } else {
+        this.handleLayoutChange();
+      }
+    }
+  }
+
   componentDidUpdate (prevProps) {
     if (this.props.unreadNotifications != prevProps.unreadNotifications ||
         this.props.showFaviconBadge != prevProps.showFaviconBadge) {
@@ -446,6 +438,8 @@ class UI extends React.Component {
     }
 
     window.removeEventListener('beforeunload', this.handleBeforeUnload);
+    window.removeEventListener('resize', this.handleResize);
+
     document.removeEventListener('dragenter', this.handleDragEnter);
     document.removeEventListener('dragover', this.handleDragOver);
     document.removeEventListener('drop', this.handleDrop);
@@ -576,7 +570,7 @@ class UI extends React.Component {
 
   render () {
     const { draggingOver } = this.state;
-    const { children, layout, isWide, navbarUnder, location, dropdownMenuIsOpen, moved } = this.props;
+    const { children, isWide, navbarUnder, location, dropdownMenuIsOpen, layout, moved } = this.props;
 
     const columnsClass = layout => {
       switch (layout) {
@@ -632,11 +626,11 @@ class UI extends React.Component {
               )}}
             />
           </div>)}
-          <SwitchingColumnsArea location={location} layout={layout} navbarUnder={navbarUnder} onLayoutChange={this.handleLayoutChange}>
+          <SwitchingColumnsArea location={location} mobile={layout === 'mobile' || layout === 'single-column'} navbarUnder={navbarUnder}>
             {children}
           </SwitchingColumnsArea>
 
-          <PictureInPicture />
+          {layout !== 'mobile' && <PictureInPicture />}
           <NotificationsContainer />
           <LoadingBarContainer className='loading-bar' />
           <ModalContainer />