about summary refs log tree commit diff
path: root/app/javascript/flavours/glitch/features/compose
diff options
context:
space:
mode:
Diffstat (limited to 'app/javascript/flavours/glitch/features/compose')
-rw-r--r--app/javascript/flavours/glitch/features/compose/components/compose_form.js173
-rw-r--r--app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js61
-rw-r--r--app/javascript/flavours/glitch/features/compose/index.js36
3 files changed, 127 insertions, 143 deletions
diff --git a/app/javascript/flavours/glitch/features/compose/components/compose_form.js b/app/javascript/flavours/glitch/features/compose/components/compose_form.js
index 2b9d2dca6..88dce5098 100644
--- a/app/javascript/flavours/glitch/features/compose/components/compose_form.js
+++ b/app/javascript/flavours/glitch/features/compose/components/compose_form.js
@@ -1,23 +1,19 @@
 import React from 'react';
-import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
+import PropTypes from 'prop-types';
+import ReplyIndicatorContainer from '../containers/reply_indicator_container';
+import AutosuggestTextarea from '../../../components/autosuggest_textarea';
 import { defineMessages, injectIntl } from 'react-intl';
+import EmojiPicker from 'flavours/glitch/features/emoji_picker';
+import PollFormContainer from '../containers/poll_form_container';
+import UploadFormContainer from '../containers/upload_form_container';
+import WarningContainer from '../containers/warning_container';
+import { isMobile } from 'flavours/glitch/util/is_mobile';
 import ImmutablePureComponent from 'react-immutable-pure-component';
-
-//  Components.
+import { countableText } from 'flavours/glitch/util/counter';
 import OptionsContainer from '../containers/options_container';
 import Publisher from './publisher';
 import TextareaIcons from './textarea_icons';
-import UploadFormContainer from '../containers/upload_form_container';
-import PollFormContainer from '../containers/poll_form_container';
-import WarningContainer from '../containers/warning_container';
-import ReplyIndicatorContainer from '../containers/reply_indicator_container';
-import EmojiPicker from 'flavours/glitch/features/emoji_picker';
-import AutosuggestTextarea from '../../../components/autosuggest_textarea';
-
-//  Utils.
-import { countableText } from 'flavours/glitch/util/counter';
-import { isMobile } from 'flavours/glitch/util/is_mobile';
 
 const messages = defineMessages({
   placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What is on your mind?' },
@@ -37,84 +33,50 @@ class ComposeForm extends ImmutablePureComponent {
 
   static propTypes = {
     intl: PropTypes.object.isRequired,
-
-    //  State props.
-    advancedOptions: ImmutablePropTypes.map,
-    amUnlocked: PropTypes.bool,
+    text: PropTypes.string,
+    suggestions: ImmutablePropTypes.list,
+    spoiler: PropTypes.bool,
+    privacy: PropTypes.string,
+    spoilerText: PropTypes.string,
     focusDate: PropTypes.instanceOf(Date),
     caretPosition: PropTypes.number,
+    preselectDate: PropTypes.instanceOf(Date),
     isSubmitting: PropTypes.bool,
     isChangingUpload: PropTypes.bool,
     isUploading: PropTypes.bool,
+    onChange: PropTypes.func,
+    onSubmit: PropTypes.func,
+    onClearSuggestions: PropTypes.func,
+    onFetchSuggestions: PropTypes.func,
+    onSuggestionSelected: PropTypes.func,
+    onChangeSpoilerText: PropTypes.func,
+    onPaste: PropTypes.func,
+    onPickEmoji: PropTypes.func,
+    showSearch: PropTypes.bool,
+    anyMedia: PropTypes.bool,
+
+    advancedOptions: ImmutablePropTypes.map,
     layout: PropTypes.string,
     media: ImmutablePropTypes.list,
-    preselectDate: PropTypes.instanceOf(Date),
-    privacy: PropTypes.string,
     sideArm: PropTypes.string,
     sensitive: PropTypes.bool,
-    showSearch: PropTypes.bool,
-    spoiler: PropTypes.bool,
-    spoilerText: PropTypes.string,
-    suggestionToken: PropTypes.string,
-    suggestions: ImmutablePropTypes.list,
-    text: PropTypes.string,
-    anyMedia: PropTypes.bool,
     spoilersAlwaysOn: PropTypes.bool,
     mediaDescriptionConfirmation: PropTypes.bool,
     preselectOnReply: PropTypes.bool,
-
-    //  Dispatch props.
-    onChangeSpoilerText: PropTypes.func,
     onChangeSpoilerness: PropTypes.func,
-    onChangeText: PropTypes.func,
     onChangeVisibility: PropTypes.func,
-    onClearSuggestions: PropTypes.func,
-    onFetchSuggestions: PropTypes.func,
-    onInsertEmoji: PropTypes.func,
     onMount: PropTypes.func,
-    onSelectSuggestion: PropTypes.func,
-    onSubmit: PropTypes.func,
     onUnmount: PropTypes.func,
-    onUpload: PropTypes.func,
+    onPaste: PropTypes.func,
     onMediaDescriptionConfirm: PropTypes.func,
   };
 
-  //  Changes the text value of the spoiler.
-  handleChangeSpoiler = ({ target: { value } }) => {
-    const { onChangeSpoilerText } = this.props;
-    if (onChangeSpoilerText) {
-      onChangeSpoilerText(value);
-    }
-  }
-
-  //  Inserts an emoji at the caret.
-  handleEmoji = (data) => {
-    const { textarea: { selectionStart } } = this;
-    const { onInsertEmoji } = this.props;
-    if (onInsertEmoji) {
-      onInsertEmoji(selectionStart, data);
-    }
-  }
-
-  //  Handles the secondary submit button.
-  handleSecondarySubmit = () => {
-    const { handleSubmit } = this.handlers;
-    const {
-      onChangeVisibility,
-      sideArm,
-    } = this.props;
-    if (sideArm !== 'none' && onChangeVisibility) {
-      onChangeVisibility(sideArm);
-    }
-    handleSubmit();
-  }
+  static defaultProps = {
+    showSearch: false,
+  };
 
-  //  Selects a suggestion from the autofill.
-  handleSelect = (tokenStart, token, value) => {
-    const { onSelectSuggestion } = this.props;
-    if (onSelectSuggestion) {
-      onSelectSuggestion(tokenStart, token, value);
-    }
+  handleChange = (e) => {
+    this.props.onChange(e.target.value);
   }
 
   handleKeyDown = ({ ctrlKey, keyCode, metaKey, altKey }) => {
@@ -129,18 +91,10 @@ class ComposeForm extends ImmutablePureComponent {
     }
   }
 
-  //  When the escape key is released, we focus the UI.
-  handleKeyUp = ({ key }) => {
-    if (key === 'Escape') {
-      document.querySelector('.ui').parentElement.focus();
-    }
-  }
-
-  //  Submits the status.
   handleSubmit = () => {
     const { textarea: { value }, uploadForm } = this;
     const {
-      onChangeText,
+      onChange,
       onSubmit,
       isSubmitting,
       isChangingUpload,
@@ -154,8 +108,8 @@ class ComposeForm extends ImmutablePureComponent {
 
     //  If something changes inside the textarea, then we update the
     //  state before submitting.
-    if (onChangeText && text !== value) {
-      onChangeText(value);
+    if (onChange && text !== value) {
+      onChange(value);
     }
 
     // Submit disabled:
@@ -178,6 +132,48 @@ class ComposeForm extends ImmutablePureComponent {
     }
   }
 
+  //  Changes the text value of the spoiler.
+  handleChangeSpoiler = ({ target: { value } }) => {
+    const { onChangeSpoilerText } = this.props;
+    if (onChangeSpoilerText) {
+      onChangeSpoilerText(value);
+    }
+  }
+
+  //  Inserts an emoji at the caret.
+  handleEmoji = (data) => {
+    const { textarea: { selectionStart } } = this;
+    const { onPickEmoji } = this.props;
+    if (onPickEmoji) {
+      onPickEmoji(selectionStart, data);
+    }
+  }
+
+  //  Handles the secondary submit button.
+  handleSecondarySubmit = () => {
+    const { handleSubmit } = this.handlers;
+    const {
+      onChangeVisibility,
+      sideArm,
+    } = this.props;
+    if (sideArm !== 'none' && onChangeVisibility) {
+      onChangeVisibility(sideArm);
+    }
+    handleSubmit();
+  }
+
+  //  Selects a suggestion from the autofill.
+  onSuggestionSelected = (tokenStart, token, value) => {
+    this.props.onSuggestionSelected(tokenStart, token, value);
+  }
+
+  //  When the escape key is released, we focus the UI.
+  handleKeyUp = ({ key }) => {
+    if (key === 'Escape') {
+      document.querySelector('.ui').parentElement.focus();
+    }
+  }
+
   //  Sets a reference to the textarea.
   setAutosuggestTextarea = (textareaComponent) => {
     if (textareaComponent) {
@@ -265,9 +261,6 @@ class ComposeForm extends ImmutablePureComponent {
     }
   }
 
-  handleChange = (e) => {
-    this.props.onChangeText(e.target.value);
-  }
 
   render () {
     const {
@@ -279,7 +272,6 @@ class ComposeForm extends ImmutablePureComponent {
     } = this;
     const {
       advancedOptions,
-      amUnlocked,
       anyMedia,
       intl,
       isSubmitting,
@@ -288,11 +280,10 @@ class ComposeForm extends ImmutablePureComponent {
       layout,
       media,
       onChangeSpoilerness,
-      onChangeText,
       onChangeVisibility,
       onClearSuggestions,
       onFetchSuggestions,
-      onUpload,
+      onPaste,
       privacy,
       sensitive,
       showSearch,
@@ -343,8 +334,8 @@ class ComposeForm extends ImmutablePureComponent {
             onKeyDown={this.handleKeyDown}
             onSuggestionsFetchRequested={onFetchSuggestions}
             onSuggestionsClearRequested={onClearSuggestions}
-            onSuggestionSelected={this.handleSelect}
-            onPaste={onUpload}
+            onSuggestionSelected={this.onSuggestionSelected}
+            onPaste={onPaste}
             autoFocus={!showSearch && !isMobile(window.innerWidth, layout)}
           />
 
@@ -361,7 +352,7 @@ class ComposeForm extends ImmutablePureComponent {
           disabled={isSubmitting}
           onChangeVisibility={onChangeVisibility}
           onToggleSpoiler={spoilersAlwaysOn ? null : onChangeSpoilerness}
-          onUpload={onUpload}
+          onPaste={onPaste}
           privacy={privacy}
           sensitive={sensitive || (spoilersAlwaysOn && spoilerText && spoilerText.length > 0)}
           spoiler={spoilersAlwaysOn ? (spoilerText && spoilerText.length > 0) : spoiler}
diff --git a/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js b/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js
index f4161aa8f..5458e0919 100644
--- a/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js
+++ b/app/javascript/flavours/glitch/features/compose/containers/compose_form_container.js
@@ -1,4 +1,5 @@
 import { connect } from 'react-redux';
+import { defineMessages } from 'react-intl';
 import ComposeForm from '../components/compose_form';
 import {
   changeCompose,
@@ -20,7 +21,6 @@ import {
 import { changeLocalSetting } from 'flavours/glitch/actions/local_settings';
 
 import { privacyPreference } from 'flavours/glitch/util/privacy_preference';
-import { me } from 'flavours/glitch/util/initial_state';
 
 const messages = defineMessages({
   missingDescriptionMessage: {  id: 'confirmations.missing_media_description.message',
@@ -28,7 +28,6 @@ const messages = defineMessages({
   missingDescriptionConfirm: {  id: 'confirmations.missing_media_description.confirm',
                                 defaultMessage: 'Send anyway' },
 });
-import { defineMessages } from 'react-intl';
 
 //  State mapping.
 function mapStateToProps (state) {
@@ -49,7 +48,6 @@ function mapStateToProps (state) {
   sideArmPrivacy = sideArmPrivacy || sideArmBasePrivacy;
   return {
     advancedOptions: state.getIn(['compose', 'advanced_options']),
-    amUnlocked: !state.getIn(['accounts', me, 'locked']),
     focusDate: state.getIn(['compose', 'focusDate']),
     caretPosition: state.getIn(['compose', 'caretPosition']),
     isSubmitting: state.getIn(['compose', 'is_submitting']),
@@ -64,7 +62,6 @@ function mapStateToProps (state) {
     showSearch: state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']),
     spoiler: spoilersAlwaysOn || state.getIn(['compose', 'spoiler']),
     spoilerText: state.getIn(['compose', 'spoiler_text']),
-    suggestionToken: state.getIn(['compose', 'suggestion_token']),
     suggestions: state.getIn(['compose', 'suggestions']),
     text: state.getIn(['compose', 'text']),
     anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
@@ -76,33 +73,55 @@ function mapStateToProps (state) {
 
 //  Dispatch mapping.
 const mapDispatchToProps = (dispatch, { intl }) => ({
-  onChangeSpoilerText(text) {
-    dispatch(changeComposeSpoilerText(text));
-  },
-  onChangeSpoilerness() {
-    dispatch(changeComposeSpoilerness());
-  },
-  onChangeText(text) {
+
+  onChange(text) {
     dispatch(changeCompose(text));
   },
-  onChangeVisibility(value) {
-    dispatch(changeComposeVisibility(value));
+
+  onSubmit(routerHistory) {
+    dispatch(submitCompose(routerHistory));
   },
+
   onClearSuggestions() {
     dispatch(clearComposeSuggestions());
   },
+
   onFetchSuggestions(token) {
     dispatch(fetchComposeSuggestions(token));
   },
-  onInsertEmoji(position, emoji) {
+
+  onSuggestionSelected(position, token, suggestion) {
+    dispatch(selectComposeSuggestion(position, token, suggestion));
+  },
+
+  onChangeSpoilerText(text) {
+    dispatch(changeComposeSpoilerText(text));
+  },
+
+  onPaste(files) {
+    dispatch(uploadCompose(files));
+  },
+
+  onPickEmoji(position, emoji) {
     dispatch(insertEmojiCompose(position, emoji));
   },
+
+  onChangeSpoilerness() {
+    dispatch(changeComposeSpoilerness());
+  },
+
+  onChangeVisibility(value) {
+    dispatch(changeComposeVisibility(value));
+  },
+
   onMount() {
     dispatch(mountCompose());
   },
-  onSelectSuggestion(position, token, suggestion) {
-    dispatch(selectComposeSuggestion(position, token, suggestion));
+
+  onUnmount() {
+    dispatch(unmountCompose());
   },
+
   onMediaDescriptionConfirm(routerHistory) {
     dispatch(openModal('CONFIRM', {
       message: intl.formatMessage(messages.missingDescriptionMessage),
@@ -111,15 +130,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
       onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_missing_media_description'], false)),
     }));
   },
-  onSubmit(routerHistory) {
-    dispatch(submitCompose(routerHistory));
-  },
-  onUnmount() {
-    dispatch(unmountCompose());
-  },
-  onUpload(files) {
-    dispatch(uploadCompose(files));
-  },
+
 });
 
 export default connect(mapStateToProps, mapDispatchToProps)(ComposeForm);
diff --git a/app/javascript/flavours/glitch/features/compose/index.js b/app/javascript/flavours/glitch/features/compose/index.js
index 01e7d1906..a7795a04d 100644
--- a/app/javascript/flavours/glitch/features/compose/index.js
+++ b/app/javascript/flavours/glitch/features/compose/index.js
@@ -1,63 +1,46 @@
-//  Package imports.
 import React from 'react';
-import { connect } from 'react-redux';
+import ComposeFormContainer from './containers/compose_form_container';
+import NavigationContainer from './containers/navigation_container';
 import PropTypes from 'prop-types';
 import ImmutablePropTypes from 'react-immutable-proptypes';
+import { connect } from 'react-redux';
 import { injectIntl, defineMessages } from 'react-intl';
 import classNames from 'classnames';
-
-//  Actions.
-import { cycleElefriendCompose } from 'flavours/glitch/actions/compose';
-
-//  Components.
-import ComposeFormContainer from './containers/compose_form_container';
-import HeaderContainer from './containers/header_container';
 import SearchContainer from './containers/search_container';
-import SearchResultsContainer from './containers/search_results_container';
-import NavigationContainer from './containers/navigation_container';
+import Motion from 'flavours/glitch/util/optional_motion';
 import spring from 'react-motion/lib/spring';
-
-//  Utils.
+import SearchResultsContainer from './containers/search_results_container';
 import { me, mascot } from 'flavours/glitch/util/initial_state';
-import Motion from 'flavours/glitch/util/optional_motion';
+import { cycleElefriendCompose } from 'flavours/glitch/actions/compose';
+import HeaderContainer from './containers/header_container';
 
-//  Messages.
 const messages = defineMessages({
   compose: { id: 'navigation_bar.compose', defaultMessage: 'Compose new toot' },
 });
 
-//  State mapping.
 const mapStateToProps = (state, ownProps) => ({
   elefriend: state.getIn(['compose', 'elefriend']),
   showSearch: ownProps.multiColumn ? state.getIn(['search', 'submitted']) && !state.getIn(['search', 'hidden']) : ownProps.isSearchPage,
 });
 
-//  Dispatch mapping.
 const mapDispatchToProps = (dispatch, { intl }) => ({
   onClickElefriend () {
     dispatch(cycleElefriendCompose());
   },
 });
 
-//  The component.
 export default @connect(mapStateToProps, mapDispatchToProps)
 @injectIntl
 class Compose extends React.PureComponent {
   static propTypes = {
-    intl: PropTypes.object.isRequired,
-    isSearchPage: PropTypes.bool,
     multiColumn: PropTypes.bool,
     showSearch: PropTypes.bool,
-
-    //  State props.
+    isSearchPage: PropTypes.bool,
     elefriend: PropTypes.number,
-    unreadNotifications: PropTypes.number,
-
-    //  Dispatch props.
     onClickElefriend: PropTypes.func,
+    intl: PropTypes.object.isRequired,
   };
 
-  //  Rendering.
   render () {
     const {
       elefriend,
@@ -69,7 +52,6 @@ class Compose extends React.PureComponent {
     } = this.props;
     const computedClass = classNames('drawer', `mbstobon-${elefriend}`);
 
-    //  The result.
     return (
       <div className={computedClass} role='region' aria-label={intl.formatMessage(messages.compose)}>
         {multiColumn && <HeaderContainer />}