about summary refs log tree commit diff
path: root/app/assets/javascripts/components/features/compose/containers
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/components/features/compose/containers')
-rw-r--r--app/assets/javascripts/components/features/compose/containers/autosuggest_status_container.jsx15
-rw-r--r--app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx121
-rw-r--r--app/assets/javascripts/components/features/compose/containers/privacy_dropdown_container.jsx17
-rw-r--r--app/assets/javascripts/components/features/compose/containers/reply_indicator_container.jsx24
-rw-r--r--app/assets/javascripts/components/features/compose/containers/search_container.jsx20
-rw-r--r--app/assets/javascripts/components/features/compose/containers/search_results_container.jsx8
-rw-r--r--app/assets/javascripts/components/features/compose/containers/sensitive_button_container.jsx49
-rw-r--r--app/assets/javascripts/components/features/compose/containers/spoiler_button_container.jsx24
-rw-r--r--app/assets/javascripts/components/features/compose/containers/upload_progress_container.jsx9
9 files changed, 208 insertions, 79 deletions
diff --git a/app/assets/javascripts/components/features/compose/containers/autosuggest_status_container.jsx b/app/assets/javascripts/components/features/compose/containers/autosuggest_status_container.jsx
new file mode 100644
index 000000000..ef46eb09c
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/containers/autosuggest_status_container.jsx
@@ -0,0 +1,15 @@
+import { connect } from 'react-redux';
+import AutosuggestStatus from '../components/autosuggest_status';
+import { makeGetStatus } from '../../../selectors';
+
+const makeMapStateToProps = () => {
+  const getStatus = makeGetStatus();
+
+  const mapStateToProps = (state, { id }) => ({
+    status: getStatus(state, id)
+  });
+
+  return mapStateToProps;
+};
+
+export default connect(makeMapStateToProps)(AutosuggestStatus);
diff --git a/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx
index 2671ea618..604e1182f 100644
--- a/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx
+++ b/app/assets/javascripts/components/features/compose/containers/compose_form_container.jsx
@@ -1,95 +1,78 @@
 import { connect } from 'react-redux';
 import ComposeForm from '../components/compose_form';
+import { uploadCompose } from '../../../actions/compose';
+import { createSelector } from 'reselect';
 import {
   changeCompose,
   submitCompose,
-  cancelReplyCompose,
   clearComposeSuggestions,
   fetchComposeSuggestions,
   selectComposeSuggestion,
-  changeComposeSensitivity,
-  changeComposeSpoilerness,
   changeComposeSpoilerText,
-  changeComposeVisibility,
-  changeComposeListability
+  insertEmojiCompose
 } from '../../../actions/compose';
-import { makeGetStatus } from '../../../selectors';
 
-const makeMapStateToProps = () => {
-  const getStatus = makeGetStatus();
+const getMentionedUsernames = createSelector(state => state.getIn(['compose', 'text']), text => text.match(/(?:^|[^\/\w])@([a-z0-9_]+@[a-z0-9\.\-]+)/ig));
 
-  const mapStateToProps = function (state, props) {
-    const mentionedUsernamesWithDomains = state.getIn(['compose', 'text']).match(/(?:^|[^\/\w])@([a-z0-9_]+@[a-z0-9\.\-]+)/ig);
+const getMentionedDomains = createSelector(getMentionedUsernames, mentionedUsernamesWithDomains => {
+  return mentionedUsernamesWithDomains !== null ? [...new Set(mentionedUsernamesWithDomains.map(item => item.split('@')[2]))] : [];
+});
 
-    return {
-      text: state.getIn(['compose', 'text']),
-      suggestion_token: state.getIn(['compose', 'suggestion_token']),
-      suggestions: state.getIn(['compose', 'suggestions']),
-      sensitive: state.getIn(['compose', 'sensitive']),
-      spoiler: state.getIn(['compose', 'spoiler']),
-      spoiler_text: state.getIn(['compose', 'spoiler_text']),
-      unlisted: state.getIn(['compose', 'unlisted'], ),
-      private: state.getIn(['compose', 'private']),
-      fileDropDate: state.getIn(['compose', 'fileDropDate']),
-      is_submitting: state.getIn(['compose', 'is_submitting']),
-      is_uploading: state.getIn(['compose', 'is_uploading']),
-      in_reply_to: getStatus(state, state.getIn(['compose', 'in_reply_to'])),
-      media_count: state.getIn(['compose', 'media_attachments']).size,
-      me: state.getIn(['compose', 'me']),
-      needsPrivacyWarning: state.getIn(['compose', 'private']) && mentionedUsernamesWithDomains !== null,
-      mentionedDomains: mentionedUsernamesWithDomains !== null ? [...new Set(mentionedUsernamesWithDomains.map(item => item.split('@')[2]))] : []
-    };
-  };
-
-  return mapStateToProps;
-};
+const mapStateToProps = (state, props) => {
+  const mentionedUsernames = getMentionedUsernames(state);
+  const mentionedUsernamesWithDomains = getMentionedDomains(state);
 
-const mapDispatchToProps = function (dispatch) {
   return {
-    onChange (text) {
-      dispatch(changeCompose(text));
-    },
+    text: state.getIn(['compose', 'text']),
+    suggestion_token: state.getIn(['compose', 'suggestion_token']),
+    suggestions: state.getIn(['compose', 'suggestions']),
+    spoiler: state.getIn(['compose', 'spoiler']),
+    spoiler_text: state.getIn(['compose', 'spoiler_text']),
+    privacy: state.getIn(['compose', 'privacy']),
+    focusDate: state.getIn(['compose', 'focusDate']),
+    preselectDate: state.getIn(['compose', 'preselectDate']),
+    is_submitting: state.getIn(['compose', 'is_submitting']),
+    is_uploading: state.getIn(['compose', 'is_uploading']),
+    me: state.getIn(['compose', 'me']),
+    needsPrivacyWarning: (state.getIn(['compose', 'privacy']) === 'private' || state.getIn(['compose', 'privacy']) === 'direct') && mentionedUsernames !== null,
+    mentionedDomains: mentionedUsernamesWithDomains
+  };
+};
 
-    onSubmit () {
-      dispatch(submitCompose());
-    },
+const mapDispatchToProps = (dispatch) => ({
 
-    onCancelReply () {
-      dispatch(cancelReplyCompose());
-    },
+  onChange (text) {
+    dispatch(changeCompose(text));
+  },
 
-    onClearSuggestions () {
-      dispatch(clearComposeSuggestions());
-    },
+  onSubmit () {
+    dispatch(submitCompose());
+  },
 
-    onFetchSuggestions (token) {
-      dispatch(fetchComposeSuggestions(token));
-    },
+  onClearSuggestions () {
+    dispatch(clearComposeSuggestions());
+  },
 
-    onSuggestionSelected (position, token, accountId) {
-      dispatch(selectComposeSuggestion(position, token, accountId));
-    },
+  onFetchSuggestions (token) {
+    dispatch(fetchComposeSuggestions(token));
+  },
 
-    onChangeSensitivity (checked) {
-      dispatch(changeComposeSensitivity(checked));
-    },
+  onSuggestionSelected (position, token, accountId) {
+    dispatch(selectComposeSuggestion(position, token, accountId));
+  },
 
-    onChangeSpoilerness (checked) {
-      dispatch(changeComposeSpoilerness(checked));
-    },
+  onChangeSpoilerText (checked) {
+    dispatch(changeComposeSpoilerText(checked));
+  },
 
-    onChangeSpoilerText (checked) {
-      dispatch(changeComposeSpoilerText(checked));
-    },
+  onPaste (files) {
+    dispatch(uploadCompose(files));
+  },
 
-    onChangeVisibility (checked) {
-      dispatch(changeComposeVisibility(checked));
-    },
+  onPickEmoji (position, data) {
+    dispatch(insertEmojiCompose(position, data));
+  },
 
-    onChangeListability (checked) {
-      dispatch(changeComposeListability(checked));
-    }
-  }
-};
+});
 
-export default connect(makeMapStateToProps, mapDispatchToProps)(ComposeForm);
+export default connect(mapStateToProps, mapDispatchToProps)(ComposeForm);
diff --git a/app/assets/javascripts/components/features/compose/containers/privacy_dropdown_container.jsx b/app/assets/javascripts/components/features/compose/containers/privacy_dropdown_container.jsx
new file mode 100644
index 000000000..1eee8f84c
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/containers/privacy_dropdown_container.jsx
@@ -0,0 +1,17 @@
+import { connect } from 'react-redux';
+import PrivacyDropdown from '../components/privacy_dropdown';
+import { changeComposeVisibility } from '../../../actions/compose';
+
+const mapStateToProps = state => ({
+  value: state.getIn(['compose', 'privacy'])
+});
+
+const mapDispatchToProps = dispatch => ({
+
+  onChange (value) {
+    dispatch(changeComposeVisibility(value));
+  }
+
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(PrivacyDropdown);
diff --git a/app/assets/javascripts/components/features/compose/containers/reply_indicator_container.jsx b/app/assets/javascripts/components/features/compose/containers/reply_indicator_container.jsx
new file mode 100644
index 000000000..39b48f3b6
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/containers/reply_indicator_container.jsx
@@ -0,0 +1,24 @@
+import { connect } from 'react-redux';
+import { cancelReplyCompose } from '../../../actions/compose';
+import { makeGetStatus } from '../../../selectors';
+import ReplyIndicator from '../components/reply_indicator';
+
+const makeMapStateToProps = () => {
+  const getStatus = makeGetStatus();
+
+  const mapStateToProps = (state, props) => ({
+    status: getStatus(state, state.getIn(['compose', 'in_reply_to'])),
+  });
+
+  return mapStateToProps;
+};
+
+const mapDispatchToProps = dispatch => ({
+
+  onCancel () {
+    dispatch(cancelReplyCompose());
+  }
+
+});
+
+export default connect(makeMapStateToProps, mapDispatchToProps)(ReplyIndicator);
diff --git a/app/assets/javascripts/components/features/compose/containers/search_container.jsx b/app/assets/javascripts/components/features/compose/containers/search_container.jsx
index 17a68f2fc..906c0c28c 100644
--- a/app/assets/javascripts/components/features/compose/containers/search_container.jsx
+++ b/app/assets/javascripts/components/features/compose/containers/search_container.jsx
@@ -1,15 +1,15 @@
 import { connect } from 'react-redux';
 import {
   changeSearch,
-  clearSearchSuggestions,
-  fetchSearchSuggestions,
-  resetSearch
+  clearSearch,
+  submitSearch,
+  showSearch
 } from '../../../actions/search';
 import Search from '../components/search';
 
 const mapStateToProps = state => ({
-  suggestions: state.getIn(['search', 'suggestions']),
-  value: state.getIn(['search', 'value'])
+  value: state.getIn(['search', 'value']),
+  submitted: state.getIn(['search', 'submitted'])
 });
 
 const mapDispatchToProps = dispatch => ({
@@ -19,15 +19,15 @@ const mapDispatchToProps = dispatch => ({
   },
 
   onClear () {
-    dispatch(clearSearchSuggestions());
+    dispatch(clearSearch());
   },
 
-  onFetch (value) {
-    dispatch(fetchSearchSuggestions(value));
+  onSubmit () {
+    dispatch(submitSearch());
   },
 
-  onReset () {
-    dispatch(resetSearch());
+  onShow () {
+    dispatch(showSearch());
   }
 
 });
diff --git a/app/assets/javascripts/components/features/compose/containers/search_results_container.jsx b/app/assets/javascripts/components/features/compose/containers/search_results_container.jsx
new file mode 100644
index 000000000..e5911fd38
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/containers/search_results_container.jsx
@@ -0,0 +1,8 @@
+import { connect } from 'react-redux';
+import SearchResults from '../components/search_results';
+
+const mapStateToProps = state => ({
+  results: state.getIn(['search', 'results'])
+});
+
+export default connect(mapStateToProps)(SearchResults);
diff --git a/app/assets/javascripts/components/features/compose/containers/sensitive_button_container.jsx b/app/assets/javascripts/components/features/compose/containers/sensitive_button_container.jsx
new file mode 100644
index 000000000..074b568f4
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/containers/sensitive_button_container.jsx
@@ -0,0 +1,49 @@
+import { connect } from 'react-redux';
+import TextIconButton from '../components/text_icon_button';
+import { changeComposeSensitivity } from '../../../actions/compose';
+import { Motion, spring } from 'react-motion';
+import { injectIntl, defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+  title: { id: 'compose_form.sensitive', defaultMessage: 'Mark media as sensitive' }
+});
+
+const mapStateToProps = state => ({
+  visible: state.getIn(['compose', 'media_attachments']).size > 0,
+  active: state.getIn(['compose', 'sensitive'])
+});
+
+const mapDispatchToProps = dispatch => ({
+
+  onClick () {
+    dispatch(changeComposeSensitivity());
+  }
+
+});
+
+const SensitiveButton = React.createClass({
+
+  propTypes: {
+    visible: React.PropTypes.bool,
+    active: React.PropTypes.bool,
+    onClick: React.PropTypes.func.isRequired,
+    intl: React.PropTypes.object.isRequired
+  },
+
+  render () {
+    const { visible, active, onClick, intl } = this.props;
+
+    return (
+      <Motion defaultStyle={{ scale: 0.87 }} style={{ scale: spring(visible ? 1 : 0.87, { stiffness: 200, damping: 3 }) }}>
+        {({ scale }) =>
+          <div style={{ display: visible ? 'block' : 'none', transform: `translateZ(0) scale(${scale})` }}>
+            <TextIconButton onClick={onClick} label='NSFW' title={intl.formatMessage(messages.title)} active={active} />
+          </div>
+        }
+      </Motion>
+    );
+  }
+
+});
+
+export default connect(mapStateToProps, mapDispatchToProps)(injectIntl(SensitiveButton));
diff --git a/app/assets/javascripts/components/features/compose/containers/spoiler_button_container.jsx b/app/assets/javascripts/components/features/compose/containers/spoiler_button_container.jsx
new file mode 100644
index 000000000..61ac32b85
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/containers/spoiler_button_container.jsx
@@ -0,0 +1,24 @@
+import { connect } from 'react-redux';
+import TextIconButton from '../components/text_icon_button';
+import { changeComposeSpoilerness } from '../../../actions/compose';
+import { injectIntl, defineMessages } from 'react-intl';
+
+const messages = defineMessages({
+  title: { id: 'compose_form.spoiler', defaultMessage: 'Hide text behind content warning' }
+});
+
+const mapStateToProps = (state, { intl }) => ({
+  label: 'CW',
+  title: intl.formatMessage(messages.title),
+  active: state.getIn(['compose', 'spoiler'])
+});
+
+const mapDispatchToProps = dispatch => ({
+
+  onClick () {
+    dispatch(changeComposeSpoilerness());
+  }
+
+});
+
+export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(TextIconButton));
diff --git a/app/assets/javascripts/components/features/compose/containers/upload_progress_container.jsx b/app/assets/javascripts/components/features/compose/containers/upload_progress_container.jsx
new file mode 100644
index 000000000..b0f1d4d19
--- /dev/null
+++ b/app/assets/javascripts/components/features/compose/containers/upload_progress_container.jsx
@@ -0,0 +1,9 @@
+import { connect } from 'react-redux';
+import UploadProgress from '../components/upload_progress';
+
+const mapStateToProps = (state, props) => ({
+  active: state.getIn(['compose', 'is_uploading']),
+  progress: state.getIn(['compose', 'progress'])
+});
+
+export default connect(mapStateToProps)(UploadProgress);