about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/flavours/glitch')
-rw-r--r--app/javascript/flavours/glitch/actions/compose.js5
-rw-r--r--app/javascript/flavours/glitch/components/status_content.js11
-rw-r--r--app/javascript/flavours/glitch/features/composer/index.js7
-rw-r--r--app/javascript/flavours/glitch/features/getting_started/index.js51
-rw-r--r--app/javascript/flavours/glitch/features/ui/components/column_link.js8
-rw-r--r--app/javascript/flavours/glitch/reducers/compose.js3
-rw-r--r--app/javascript/flavours/glitch/styles/components/index.scss11
7 files changed, 74 insertions, 22 deletions
diff --git a/app/javascript/flavours/glitch/actions/compose.js b/app/javascript/flavours/glitch/actions/compose.js
index c46387104..1e9386859 100644
--- a/app/javascript/flavours/glitch/actions/compose.js
+++ b/app/javascript/flavours/glitch/actions/compose.js
@@ -102,8 +102,9 @@ export function mentionCompose(account, router) {
 export function submitCompose() {
   return function (dispatch, getState) {
     let status = getState().getIn(['compose', 'text'], '');
+    let media  = getState().getIn(['compose', 'media_attachments']);
 
-    if (!status || !status.length) {
+    if ((!status || !status.length) && media.size === 0) {
       return;
     }
 
@@ -114,7 +115,7 @@ export function submitCompose() {
     api(getState).post('/api/v1/statuses', {
       status,
       in_reply_to_id: getState().getIn(['compose', 'in_reply_to'], null),
-      media_ids: getState().getIn(['compose', 'media_attachments']).map(item => item.get('id')),
+      media_ids: media.map(item => item.get('id')),
       sensitive: getState().getIn(['compose', 'sensitive']),
       spoiler_text: getState().getIn(['compose', 'spoiler_text'], ''),
       visibility: getState().getIn(['compose', 'privacy']),
diff --git a/app/javascript/flavours/glitch/components/status_content.js b/app/javascript/flavours/glitch/components/status_content.js
index 0c40e62cc..a15bf7c52 100644
--- a/app/javascript/flavours/glitch/components/status_content.js
+++ b/app/javascript/flavours/glitch/components/status_content.js
@@ -23,7 +23,12 @@ export default class StatusContent extends React.PureComponent {
   };
 
   _updateStatusLinks () {
-    const node  = this.node;
+    const node = this.node;
+
+    if (!node) {
+      return;
+    }
+
     const links = node.querySelectorAll('a');
 
     for (var i = 0; i < links.length; ++i) {
@@ -126,6 +131,10 @@ export default class StatusContent extends React.PureComponent {
       disabled,
     } = this.props;
 
+    if (status.get('content').length === 0) {
+      return null;
+    }
+
     const hidden = this.props.setExpansion ? !this.props.expanded : this.state.hidden;
 
     const content = { __html: status.get('contentHtml') };
diff --git a/app/javascript/flavours/glitch/features/composer/index.js b/app/javascript/flavours/glitch/features/composer/index.js
index e50f3ec3f..792ed79a3 100644
--- a/app/javascript/flavours/glitch/features/composer/index.js
+++ b/app/javascript/flavours/glitch/features/composer/index.js
@@ -73,6 +73,7 @@ function mapStateToProps (state) {
     suggestionToken: state.getIn(['compose', 'suggestion_token']),
     suggestions: state.getIn(['compose', 'suggestions']),
     text: state.getIn(['compose', 'text']),
+    anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
   };
 };
 
@@ -272,6 +273,7 @@ class Composer extends React.Component {
       acceptContentTypes,
       advancedOptions,
       amUnlocked,
+      anyMedia,
       intl,
       isSubmitting,
       isUploading,
@@ -305,6 +307,8 @@ class Composer extends React.Component {
       text,
     } = this.props;
 
+    let disabledButton = isSubmitting || isUploading || (!!text.length && !text.trim().length && !anyMedia);
+
     return (
       <div className='composer'>
         <ComposerSpoiler
@@ -374,7 +378,7 @@ class Composer extends React.Component {
         />
         <ComposerPublisher
           countText={`${spoilerText}${countableText(text)}${advancedOptions && advancedOptions.get('do_not_federate') ? ' 👁️' : ''}`}
-          disabled={isSubmitting || isUploading || !!text.length && !text.trim().length}
+          disabled={disabledButton}
           intl={intl}
           onSecondarySubmit={handleSecondarySubmit}
           onSubmit={handleSubmit}
@@ -436,6 +440,7 @@ Composer.propTypes = {
   onUndoUpload: PropTypes.func,
   onUnmount: PropTypes.func,
   onUpload: PropTypes.func,
+  anyMedia: PropTypes.bool,
 };
 
 //  Connecting and export.
diff --git a/app/javascript/flavours/glitch/features/getting_started/index.js b/app/javascript/flavours/glitch/features/getting_started/index.js
index 0077f193b..bf9fe118a 100644
--- a/app/javascript/flavours/glitch/features/getting_started/index.js
+++ b/app/javascript/flavours/glitch/features/getting_started/index.js
@@ -9,6 +9,8 @@ import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
 import ImmutablePureComponent from 'react-immutable-pure-component';
 import { me } from 'flavours/glitch/util/initial_state';
+import { fetchFollowRequests } from 'flavours/glitch/actions/accounts';
+import { List as ImmutableList } from 'immutable';
 import { createSelector } from 'reselect';
 import { fetchLists } from 'flavours/glitch/actions/lists';
 
@@ -45,13 +47,31 @@ const makeMapStateToProps = () => {
     lists: getOrderedLists(state),
     myAccount: state.getIn(['accounts', me]),
     columns: state.getIn(['settings', 'columns']),
+    unreadFollowRequests: state.getIn(['user_lists', 'follow_requests', 'items'], ImmutableList()).size,
+    unreadNotifications: state.getIn(['notifications', 'unread']),
   });
 
   return mapStateToProps;
 };
 
+const mapDispatchToProps = dispatch => ({
+  fetchFollowRequests: () => dispatch(fetchFollowRequests()),
+  fetchLists: () => dispatch(fetchLists()),
+  openSettings: () => dispatch(openModal('SETTINGS', {})),
+});
+
+const badgeDisplay = (number, limit) => {
+  if (number === 0) {
+    return undefined;
+  } else if (limit && number >= limit) {
+    return `${limit}+`;
+  } else {
+    return number;
+  }
+};
+
+@connect(makeMapStateToProps, mapDispatchToProps)
 @injectIntl
-@connect(makeMapStateToProps)
 export default class GettingStarted extends ImmutablePureComponent {
 
   static propTypes = {
@@ -59,25 +79,28 @@ export default class GettingStarted extends ImmutablePureComponent {
     myAccount: ImmutablePropTypes.map.isRequired,
     columns: ImmutablePropTypes.list,
     multiColumn: PropTypes.bool,
-    dispatch: PropTypes.func.isRequired,
+    fetchFollowRequests: PropTypes.func.isRequired,
+    unreadFollowRequests: PropTypes.number,
+    unreadNotifications: PropTypes.number,
     lists: ImmutablePropTypes.list,
+    fetchLists: PropTypes.func.isRequired,
+    openSettings: PropTypes.func.isRequired,
   };
 
-  openSettings = () => {
-    this.props.dispatch(openModal('SETTINGS', {}));
+  componentWillMount () {
+    this.props.fetchLists();
   }
 
-  openOnboardingModal = (e) => {
-    e.preventDefault();
-    this.props.dispatch(openModal('ONBOARDING'));
-  }
+  componentDidMount () {
+    const { myAccount, fetchFollowRequests } = this.props;
 
-  componentWillMount () {
-    this.props.dispatch(fetchLists());
+    if (myAccount.get('locked')) {
+      fetchFollowRequests();
+    }
   }
 
   render () {
-    const { intl, myAccount, columns, multiColumn, lists } = this.props;
+    const { intl, myAccount, columns, multiColumn, unreadFollowRequests, unreadNotifications, lists, openSettings } = this.props;
 
     const navItems = [];
     let listItems = [];
@@ -88,7 +111,7 @@ export default class GettingStarted extends ImmutablePureComponent {
       }
 
       if (!columns.find(item => item.get('id') === 'NOTIFICATIONS')) {
-        navItems.push(<ColumnLink key='1' icon='bell' text={intl.formatMessage(messages.notifications)} to='/notifications' />);
+        navItems.push(<ColumnLink key='1' icon='bell' text={intl.formatMessage(messages.notifications)} badge={badgeDisplay(unreadNotifications)} to='/notifications' />);
       }
 
       if (!columns.find(item => item.get('id') === 'COMMUNITY')) {
@@ -105,7 +128,7 @@ export default class GettingStarted extends ImmutablePureComponent {
     }
 
     if (myAccount.get('locked')) {
-      navItems.push(<ColumnLink key='5' icon='users' text={intl.formatMessage(messages.follow_requests)} to='/follow_requests' />);
+      navItems.push(<ColumnLink key='5' icon='users' text={intl.formatMessage(messages.follow_requests)} badge={badgeDisplay(unreadFollowRequests, 40)} to='/follow_requests' />);
     }
 
     navItems.push(<ColumnLink key='6' icon='ellipsis-h' text={intl.formatMessage(messages.misc)} to='/getting-started-misc' />);
@@ -129,7 +152,7 @@ export default class GettingStarted extends ImmutablePureComponent {
             {listItems}
             <ColumnSubheading text={intl.formatMessage(messages.settings_subheading)} />
             <ColumnLink icon='cog' text={intl.formatMessage(messages.preferences)} href='/settings/preferences' />
-            <ColumnLink icon='cogs' text={intl.formatMessage(messages.settings)} onClick={this.openSettings} />
+            <ColumnLink icon='cogs' text={intl.formatMessage(messages.settings)} onClick={openSettings} />
             <ColumnLink icon='sign-out' text={intl.formatMessage(messages.sign_out)} href='/auth/sign_out' method='delete' />
           </div>
 
diff --git a/app/javascript/flavours/glitch/features/ui/components/column_link.js b/app/javascript/flavours/glitch/features/ui/components/column_link.js
index b845d1895..b058aa963 100644
--- a/app/javascript/flavours/glitch/features/ui/components/column_link.js
+++ b/app/javascript/flavours/glitch/features/ui/components/column_link.js
@@ -2,12 +2,15 @@ import React from 'react';
 import PropTypes from 'prop-types';
 import { Link } from 'react-router-dom';
 
-const ColumnLink = ({ icon, text, to, onClick, href, method }) => {
+const ColumnLink = ({ icon, text, to, onClick, href, method, badge }) => {
+  const badgeElement = typeof badge !== 'undefined' ? <span className='column-link__badge'>{badge}</span> : null;
+
   if (href) {
     return (
       <a href={href} className='column-link' data-method={method}>
         <i className={`fa fa-fw fa-${icon} column-link__icon`} />
         {text}
+        {badgeElement}
       </a>
     );
   } else if (to) {
@@ -15,6 +18,7 @@ const ColumnLink = ({ icon, text, to, onClick, href, method }) => {
       <Link to={to} className='column-link'>
         <i className={`fa fa-fw fa-${icon} column-link__icon`} />
         {text}
+        {badgeElement}
       </Link>
     );
   } else {
@@ -22,6 +26,7 @@ const ColumnLink = ({ icon, text, to, onClick, href, method }) => {
       <a onClick={onClick} className='column-link' role='button' tabIndex='0' data-method={method}>
         <i className={`fa fa-fw fa-${icon} column-link__icon`} />
         {text}
+        {badgeElement}
       </a>
     );
   }
@@ -34,6 +39,7 @@ ColumnLink.propTypes = {
   onClick: PropTypes.func,
   href: PropTypes.string,
   method: PropTypes.string,
+  badge: PropTypes.node,
 };
 
 export default ColumnLink;
diff --git a/app/javascript/flavours/glitch/reducers/compose.js b/app/javascript/flavours/glitch/reducers/compose.js
index 722670cf1..8973c7713 100644
--- a/app/javascript/flavours/glitch/reducers/compose.js
+++ b/app/javascript/flavours/glitch/reducers/compose.js
@@ -158,7 +158,6 @@ function appendMedia(state, media) {
     map.update('media_attachments', list => list.push(media));
     map.set('is_uploading', false);
     map.set('resetFileKey', Math.floor((Math.random() * 0x10000)));
-    map.update('text', oldText => `${oldText.trim()} ${media.get('text_url')}`);
     map.set('focusDate', new Date());
     map.set('idempotencyKey', uuid());
 
@@ -169,12 +168,10 @@ function appendMedia(state, media) {
 };
 
 function removeMedia(state, mediaId) {
-  const media    = state.get('media_attachments').find(item => item.get('id') === mediaId);
   const prevSize = state.get('media_attachments').size;
 
   return state.withMutations(map => {
     map.update('media_attachments', list => list.filterNot(item => item.get('id') === mediaId));
-    map.update('text', text => text.replace(media.get('text_url'), '').trim());
     map.set('idempotencyKey', uuid());
 
     if (prevSize === 1) {
diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss
index 10cad345e..3d16c856d 100644
--- a/app/javascript/flavours/glitch/styles/components/index.scss
+++ b/app/javascript/flavours/glitch/styles/components/index.scss
@@ -753,6 +753,17 @@
   }
 }
 
+.column-link__badge {
+  display: inline-block;
+  border-radius: 4px;
+  font-size: 12px;
+  line-height: 19px;
+  font-weight: 500;
+  background: $ui-base-color;
+  padding: 4px 8px;
+  margin: -6px 10px;
+}
+
 .keyboard-shortcuts {
   padding: 8px 0 0;
   overflow: hidden;