about summary refs log tree commit diff
path: root/app/assets/javascripts/components/features/ui
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/components/features/ui')
-rw-r--r--app/assets/javascripts/components/features/ui/components/column_link.jsx4
-rw-r--r--app/assets/javascripts/components/features/ui/components/tabs_bar.jsx7
-rw-r--r--app/assets/javascripts/components/features/ui/containers/modal_container.jsx29
-rw-r--r--app/assets/javascripts/components/features/ui/containers/status_list_container.jsx60
-rw-r--r--app/assets/javascripts/components/features/ui/index.jsx21
5 files changed, 90 insertions, 31 deletions
diff --git a/app/assets/javascripts/components/features/ui/components/column_link.jsx b/app/assets/javascripts/components/features/ui/components/column_link.jsx
index a2f7c13a6..901a29f5c 100644
--- a/app/assets/javascripts/components/features/ui/components/column_link.jsx
+++ b/app/assets/javascripts/components/features/ui/components/column_link.jsx
@@ -13,10 +13,10 @@ const iconStyle = {
   marginRight: '5px'
 };
 
-const ColumnLink = ({ icon, text, to, href }) => {
+const ColumnLink = ({ icon, text, to, href, method }) => {
   if (href) {
     return (
-      <a href={href} style={outerStyle} className='column-link'>
+      <a href={href} style={outerStyle} className='column-link' data-method={method}>
         <i className={`fa fa-fw fa-${icon}`} style={iconStyle} />
         {text}
       </a>
diff --git a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx
index 219979522..2f8a28fad 100644
--- a/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx
+++ b/app/assets/javascripts/components/features/ui/components/tabs_bar.jsx
@@ -3,15 +3,14 @@ import { FormattedMessage } from 'react-intl';
 
 const outerStyle = {
   background: '#373b4a',
-  margin: '10px',
   flex: '0 0 auto',
-  marginBottom: '0'
+  overflowY: 'auto'
 };
 
 const tabStyle = {
   display: 'block',
   flex: '1 1 auto',
-  padding: '10px',
+  padding: '10px 5px',
   color: '#fff',
   textDecoration: 'none',
   textAlign: 'center',
@@ -31,7 +30,7 @@ const TabsBar = () => {
       <Link style={tabStyle} activeStyle={tabActiveStyle} to='/statuses/new'><i className='fa fa-fw fa-pencil' /> <FormattedMessage id='tabs_bar.compose' defaultMessage='Compose' /></Link>
       <Link style={tabStyle} activeStyle={tabActiveStyle} to='/timelines/home'><i className='fa fa-fw fa-home' /> <FormattedMessage id='tabs_bar.home' defaultMessage='Home' /></Link>
       <Link style={tabStyle} activeStyle={tabActiveStyle} to='/notifications'><i className='fa fa-fw fa-bell' /> <FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' /></Link>
-      <Link style={tabStyle} activeStyle={tabActiveStyle} to='/timelines/public'><i className='fa fa-fw fa-globe' /> <FormattedMessage id='tabs_bar.public' defaultMessage='Public' /></Link>
+      <Link style={{ ...tabStyle, flexGrow: '0', flexBasis: '30px' }} activeStyle={tabActiveStyle} to='/getting-started'><i className='fa fa-fw fa-bars' /></Link>
     </div>
   );
 };
diff --git a/app/assets/javascripts/components/features/ui/containers/modal_container.jsx b/app/assets/javascripts/components/features/ui/containers/modal_container.jsx
index cd7d63a4a..53d162462 100644
--- a/app/assets/javascripts/components/features/ui/containers/modal_container.jsx
+++ b/app/assets/javascripts/components/features/ui/containers/modal_container.jsx
@@ -1,6 +1,9 @@
-import { connect }           from 'react-redux';
-import { closeModal }        from '../../../actions/modal';
-import Lightbox              from '../../../components/lightbox';
+import { connect } from 'react-redux';
+import { closeModal } from '../../../actions/modal';
+import Lightbox from '../../../components/lightbox';
+import ImageLoader from 'react-imageloader';
+import LoadingIndicator from '../../../components/loading_indicator';
+import PureRenderMixin from 'react-addons-pure-render-mixin';
 
 const mapStateToProps = state => ({
   url: state.getIn(['modal', 'url']),
@@ -23,6 +26,18 @@ const imageStyle = {
   maxHeight: '80vh'
 };
 
+const loadingStyle = {
+  background: '#373b4a',
+  width: '400px',
+  paddingBottom: '120px'
+};
+
+const preloader = () => (
+  <div style={loadingStyle}>
+    <LoadingIndicator />
+  </div>
+);
+
 const Modal = React.createClass({
 
   propTypes: {
@@ -32,12 +47,18 @@ const Modal = React.createClass({
     onOverlayClicked: React.PropTypes.func
   },
 
+  mixins: [PureRenderMixin],
+
   render () {
     const { url, ...other } = this.props;
 
     return (
       <Lightbox {...other}>
-        <img src={url} style={imageStyle} />
+        <ImageLoader
+          src={url}
+          preloader={preloader}
+          imgProps={{ style: imageStyle }}
+        />
       </Lightbox>
     );
   }
diff --git a/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx
index 1621cec7b..8af7b0c3c 100644
--- a/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx
+++ b/app/assets/javascripts/components/features/ui/containers/status_list_container.jsx
@@ -2,26 +2,56 @@ import { connect } from 'react-redux';
 import StatusList from '../../../components/status_list';
 import { expandTimeline, scrollTopTimeline } from '../../../actions/timelines';
 import Immutable from 'immutable';
+import { createSelector } from 'reselect';
+
+const getStatusIds = createSelector([
+  (state, { type }) => state.getIn(['settings', type], Immutable.Map()),
+  (state, { type }) => state.getIn(['timelines', type, 'items'], Immutable.List()),
+  (state)           => state.get('statuses')
+], (columnSettings, statusIds, statuses) => statusIds.filter(id => {
+  const statusForId = statuses.get(id);
+  let showStatus    = true;
+
+  if (columnSettings.getIn(['shows', 'reblog']) === false) {
+    showStatus = showStatus && statusForId.get('reblog') === null;
+  }
+
+  if (columnSettings.getIn(['shows', 'reply']) === false) {
+    showStatus = showStatus && statusForId.get('in_reply_to_id') === null;
+  }
+
+  if (columnSettings.getIn(['regex', 'body'], '').trim().length > 0) {
+    try {
+      const regex = new RegExp(columnSettings.getIn(['regex', 'body']).trim(), 'i');
+      showStatus = showStatus && !regex.test(statusForId.get('reblog') ? statuses.getIn([statusForId.get('reblog'), 'content']) : statusForId.get('content'));
+    } catch(e) {
+      // Bad regex, don't affect filters
+    }
+  }
+
+  return showStatus;
+}));
 
 const mapStateToProps = (state, props) => ({
-  statusIds: state.getIn(['timelines', props.type, 'items'], Immutable.List())
+  statusIds: getStatusIds(state, props),
+  isLoading: state.getIn(['timelines', props.type, 'isLoading'], true)
 });
 
-const mapDispatchToProps = function (dispatch, props) {
-  return {
-    onScrollToBottom () {
-      dispatch(scrollTopTimeline(props.type, false));
-      dispatch(expandTimeline(props.type, props.id));
-    },
+const mapDispatchToProps = (dispatch, { type, id }) => ({
 
-    onScrollToTop () {
-      dispatch(scrollTopTimeline(props.type, true));
-    },
+  onScrollToBottom () {
+    dispatch(scrollTopTimeline(type, false));
+    dispatch(expandTimeline(type, id));
+  },
 
-    onScroll () {
-      dispatch(scrollTopTimeline(props.type, false));
-    }
-  };
-};
+  onScrollToTop () {
+    dispatch(scrollTopTimeline(type, true));
+  },
+
+  onScroll () {
+    dispatch(scrollTopTimeline(type, false));
+  }
+
+});
 
 export default connect(mapStateToProps, mapDispatchToProps)(StatusList);
diff --git a/app/assets/javascripts/components/features/ui/index.jsx b/app/assets/javascripts/components/features/ui/index.jsx
index 76e3dd940..003d061ad 100644
--- a/app/assets/javascripts/components/features/ui/index.jsx
+++ b/app/assets/javascripts/components/features/ui/index.jsx
@@ -8,12 +8,20 @@ import Compose from '../compose';
 import TabsBar from './components/tabs_bar';
 import ModalContainer from './containers/modal_container';
 import Notifications from '../notifications';
+import { connect } from 'react-redux';
+import { isMobile } from '../../is_mobile';
 import { debounce } from 'react-decoration';
 import { uploadCompose } from '../../actions/compose';
-import { connect } from 'react-redux';
+import { refreshTimeline } from '../../actions/timelines';
+import { refreshNotifications } from '../../actions/notifications';
 
 const UI = React.createClass({
 
+  propTypes: {
+    dispatch: React.PropTypes.func.isRequired,
+    children: React.PropTypes.node
+  },
+
   getInitialState () {
     return {
       width: window.innerWidth
@@ -41,7 +49,7 @@ const UI = React.createClass({
   handleDrop (e) {
     e.preventDefault();
 
-    if (e.dataTransfer) {
+    if (e.dataTransfer && e.dataTransfer.files.length === 1) {
       this.props.dispatch(uploadCompose(e.dataTransfer.files));
     }
   },
@@ -50,6 +58,9 @@ const UI = React.createClass({
     window.addEventListener('resize', this.handleResize, { passive: true });
     window.addEventListener('dragover', this.handleDragOver);
     window.addEventListener('drop', this.handleDrop);
+
+    this.props.dispatch(refreshTimeline('home'));
+    this.props.dispatch(refreshNotifications());
   },
 
   componentWillUnmount () {
@@ -59,11 +70,9 @@ const UI = React.createClass({
   },
 
   render () {
-    const layoutBreakpoint = 1024;
-
     let mountedColumns;
 
-    if (this.state.width <= layoutBreakpoint) {
+    if (isMobile(this.state.width)) {
       mountedColumns = (
         <ColumnsArea>
           {this.props.children}
@@ -72,7 +81,7 @@ const UI = React.createClass({
     } else {
       mountedColumns = (
         <ColumnsArea>
-          <Compose />
+          <Compose withHeader={true} />
           <HomeTimeline trackScroll={false} />
           <Notifications trackScroll={false} />
           {this.props.children}