features/composer/index.js → ComposeForm
This commit is contained in:
		
							parent
							
								
									281a82d878
								
							
						
					
					
						commit
						1bc4b8a0a5
					
				
					 5 changed files with 272 additions and 280 deletions
				
			
		| 
						 | 
					@ -1,57 +1,26 @@
 | 
				
			||||||
//  Package imports.
 | 
					 | 
				
			||||||
import PropTypes from 'prop-types';
 | 
					 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
 | 
					import PropTypes from 'prop-types';
 | 
				
			||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
					import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
				
			||||||
import { defineMessages } from 'react-intl';
 | 
					import { defineMessages, injectIntl } from 'react-intl';
 | 
				
			||||||
 | 
					import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const APPROX_HASHTAG_RE = /(?:^|[^\/\)\w])#(\S+)/i;
 | 
					const APPROX_HASHTAG_RE = /(?:^|[^\/\)\w])#(\S+)/i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//  Actions.
 | 
					 | 
				
			||||||
import {
 | 
					 | 
				
			||||||
  cancelReplyCompose,
 | 
					 | 
				
			||||||
  changeCompose,
 | 
					 | 
				
			||||||
  changeComposeAdvancedOption,
 | 
					 | 
				
			||||||
  changeComposeSensitivity,
 | 
					 | 
				
			||||||
  changeComposeSpoilerText,
 | 
					 | 
				
			||||||
  changeComposeSpoilerness,
 | 
					 | 
				
			||||||
  changeComposeVisibility,
 | 
					 | 
				
			||||||
  changeUploadCompose,
 | 
					 | 
				
			||||||
  clearComposeSuggestions,
 | 
					 | 
				
			||||||
  fetchComposeSuggestions,
 | 
					 | 
				
			||||||
  insertEmojiCompose,
 | 
					 | 
				
			||||||
  mountCompose,
 | 
					 | 
				
			||||||
  selectComposeSuggestion,
 | 
					 | 
				
			||||||
  submitCompose,
 | 
					 | 
				
			||||||
  undoUploadCompose,
 | 
					 | 
				
			||||||
  unmountCompose,
 | 
					 | 
				
			||||||
  uploadCompose,
 | 
					 | 
				
			||||||
} from 'flavours/glitch/actions/compose';
 | 
					 | 
				
			||||||
import {
 | 
					 | 
				
			||||||
  closeModal,
 | 
					 | 
				
			||||||
  openModal,
 | 
					 | 
				
			||||||
} from 'flavours/glitch/actions/modal';
 | 
					 | 
				
			||||||
import { changeLocalSetting } from 'flavours/glitch/actions/local_settings';
 | 
					 | 
				
			||||||
import { addPoll, removePoll } from 'flavours/glitch/actions/compose';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//  Components.
 | 
					//  Components.
 | 
				
			||||||
import ComposerOptions from './options';
 | 
					import ComposerOptions from '../../composer/options';
 | 
				
			||||||
import ComposerPublisher from './publisher';
 | 
					import ComposerPublisher from '../../composer/publisher';
 | 
				
			||||||
import ComposerReply from './reply';
 | 
					import ComposerReply from '../../composer/reply';
 | 
				
			||||||
import ComposerSpoiler from './spoiler';
 | 
					import ComposerSpoiler from '../../composer/spoiler';
 | 
				
			||||||
import ComposerTextarea from './textarea';
 | 
					import ComposerTextarea from '../../composer/textarea';
 | 
				
			||||||
import ComposerUploadForm from './upload_form';
 | 
					import ComposerUploadForm from '../../composer/upload_form';
 | 
				
			||||||
import ComposerPollForm from './poll_form';
 | 
					import ComposerPollForm from '../../composer/poll_form';
 | 
				
			||||||
import ComposerWarning from './warning';
 | 
					import ComposerWarning from '../../composer/warning';
 | 
				
			||||||
import ComposerHashtagWarning from './hashtag_warning';
 | 
					import ComposerHashtagWarning from '../../composer/hashtag_warning';
 | 
				
			||||||
import ComposerDirectWarning from './direct_warning';
 | 
					import ComposerDirectWarning from '../../composer/direct_warning';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//  Utils.
 | 
					//  Utils.
 | 
				
			||||||
import { countableText } from 'flavours/glitch/util/counter';
 | 
					import { countableText } from 'flavours/glitch/util/counter';
 | 
				
			||||||
import { me } from 'flavours/glitch/util/initial_state';
 | 
					 | 
				
			||||||
import { isMobile } from 'flavours/glitch/util/is_mobile';
 | 
					import { isMobile } from 'flavours/glitch/util/is_mobile';
 | 
				
			||||||
import { assignHandlers } from 'flavours/glitch/util/react_helpers';
 | 
					 | 
				
			||||||
import { wrap } from 'flavours/glitch/util/redux_helpers';
 | 
					 | 
				
			||||||
import { privacyPreference } from 'flavours/glitch/util/privacy_preference';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const messages = defineMessages({
 | 
					const messages = defineMessages({
 | 
				
			||||||
  missingDescriptionMessage: {  id: 'confirmations.missing_media_description.message',
 | 
					  missingDescriptionMessage: {  id: 'confirmations.missing_media_description.message',
 | 
				
			||||||
| 
						 | 
					@ -60,163 +29,88 @@ const messages = defineMessages({
 | 
				
			||||||
                                defaultMessage: 'Send anyway' },
 | 
					                                defaultMessage: 'Send anyway' },
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//  State mapping.
 | 
					export default @injectIntl
 | 
				
			||||||
function mapStateToProps (state) {
 | 
					class ComposeForm extends ImmutablePureComponent {
 | 
				
			||||||
  const spoilersAlwaysOn = state.getIn(['local_settings', 'always_show_spoilers_field']);
 | 
					
 | 
				
			||||||
  const inReplyTo = state.getIn(['compose', 'in_reply_to']);
 | 
					  static contextTypes = {
 | 
				
			||||||
  const replyPrivacy = inReplyTo ? state.getIn(['statuses', inReplyTo, 'visibility']) : null;
 | 
					    router: PropTypes.object,
 | 
				
			||||||
  const sideArmBasePrivacy = state.getIn(['local_settings', 'side_arm']);
 | 
					 | 
				
			||||||
  const sideArmRestrictedPrivacy = replyPrivacy ? privacyPreference(replyPrivacy, sideArmBasePrivacy) : null;
 | 
					 | 
				
			||||||
  let sideArmPrivacy = null;
 | 
					 | 
				
			||||||
  switch (state.getIn(['local_settings', 'side_arm_reply_mode'])) {
 | 
					 | 
				
			||||||
    case 'copy':
 | 
					 | 
				
			||||||
      sideArmPrivacy = replyPrivacy;
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
    case 'restrict':
 | 
					 | 
				
			||||||
      sideArmPrivacy = sideArmRestrictedPrivacy;
 | 
					 | 
				
			||||||
      break;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  sideArmPrivacy = sideArmPrivacy || sideArmBasePrivacy;
 | 
					 | 
				
			||||||
  return {
 | 
					 | 
				
			||||||
    acceptContentTypes: state.getIn(['media_attachments', 'accept_content_types']).toArray().join(','),
 | 
					 | 
				
			||||||
    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']),
 | 
					 | 
				
			||||||
    isChangingUpload: state.getIn(['compose', 'is_changing_upload']),
 | 
					 | 
				
			||||||
    isUploading: state.getIn(['compose', 'is_uploading']),
 | 
					 | 
				
			||||||
    layout: state.getIn(['local_settings', 'layout']),
 | 
					 | 
				
			||||||
    media: state.getIn(['compose', 'media_attachments']),
 | 
					 | 
				
			||||||
    preselectDate: state.getIn(['compose', 'preselectDate']),
 | 
					 | 
				
			||||||
    privacy: state.getIn(['compose', 'privacy']),
 | 
					 | 
				
			||||||
    progress: state.getIn(['compose', 'progress']),
 | 
					 | 
				
			||||||
    inReplyTo: inReplyTo ? state.getIn(['statuses', inReplyTo]) : null,
 | 
					 | 
				
			||||||
    replyAccount: inReplyTo ? state.getIn(['statuses', inReplyTo, 'account']) : null,
 | 
					 | 
				
			||||||
    replyContent: inReplyTo ? state.getIn(['statuses', inReplyTo, 'contentHtml']) : null,
 | 
					 | 
				
			||||||
    resetFileKey: state.getIn(['compose', 'resetFileKey']),
 | 
					 | 
				
			||||||
    sideArm: sideArmPrivacy,
 | 
					 | 
				
			||||||
    sensitive: state.getIn(['compose', 'sensitive']),
 | 
					 | 
				
			||||||
    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,
 | 
					 | 
				
			||||||
    poll: state.getIn(['compose', 'poll']),
 | 
					 | 
				
			||||||
    spoilersAlwaysOn: spoilersAlwaysOn,
 | 
					 | 
				
			||||||
    mediaDescriptionConfirmation: state.getIn(['local_settings', 'confirm_missing_media_description']),
 | 
					 | 
				
			||||||
    preselectOnReply: state.getIn(['local_settings', 'preselect_on_reply']),
 | 
					 | 
				
			||||||
  };
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//  Dispatch mapping.
 | 
					  static propTypes = {
 | 
				
			||||||
const mapDispatchToProps = (dispatch, { intl }) => ({
 | 
					    intl: PropTypes.object.isRequired,
 | 
				
			||||||
  onCancelReply() {
 | 
					 | 
				
			||||||
    dispatch(cancelReplyCompose());
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onChangeAdvancedOption(option, value) {
 | 
					 | 
				
			||||||
    dispatch(changeComposeAdvancedOption(option, value));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onChangeDescription(id, description) {
 | 
					 | 
				
			||||||
    dispatch(changeUploadCompose(id, { description }));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onChangeSensitivity() {
 | 
					 | 
				
			||||||
    dispatch(changeComposeSensitivity());
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onChangeSpoilerText(text) {
 | 
					 | 
				
			||||||
    dispatch(changeComposeSpoilerText(text));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onChangeSpoilerness() {
 | 
					 | 
				
			||||||
    dispatch(changeComposeSpoilerness());
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onChangeText(text) {
 | 
					 | 
				
			||||||
    dispatch(changeCompose(text));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onChangeVisibility(value) {
 | 
					 | 
				
			||||||
    dispatch(changeComposeVisibility(value));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onTogglePoll() {
 | 
					 | 
				
			||||||
    dispatch((_, getState) => {
 | 
					 | 
				
			||||||
      if (getState().getIn(['compose', 'poll'])) {
 | 
					 | 
				
			||||||
        dispatch(removePoll());
 | 
					 | 
				
			||||||
      } else {
 | 
					 | 
				
			||||||
        dispatch(addPoll());
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onClearSuggestions() {
 | 
					 | 
				
			||||||
    dispatch(clearComposeSuggestions());
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onCloseModal() {
 | 
					 | 
				
			||||||
    dispatch(closeModal());
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onFetchSuggestions(token) {
 | 
					 | 
				
			||||||
    dispatch(fetchComposeSuggestions(token));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onInsertEmoji(position, emoji) {
 | 
					 | 
				
			||||||
    dispatch(insertEmojiCompose(position, emoji));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onMount() {
 | 
					 | 
				
			||||||
    dispatch(mountCompose());
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onOpenActionsModal(props) {
 | 
					 | 
				
			||||||
    dispatch(openModal('ACTIONS', props));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onOpenDoodleModal() {
 | 
					 | 
				
			||||||
    dispatch(openModal('DOODLE', { noEsc: true }));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onOpenFocalPointModal(id) {
 | 
					 | 
				
			||||||
    dispatch(openModal('FOCAL_POINT', { id }));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onSelectSuggestion(position, token, suggestion) {
 | 
					 | 
				
			||||||
    dispatch(selectComposeSuggestion(position, token, suggestion));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onMediaDescriptionConfirm(routerHistory) {
 | 
					 | 
				
			||||||
    dispatch(openModal('CONFIRM', {
 | 
					 | 
				
			||||||
      message: intl.formatMessage(messages.missingDescriptionMessage),
 | 
					 | 
				
			||||||
      confirm: intl.formatMessage(messages.missingDescriptionConfirm),
 | 
					 | 
				
			||||||
      onConfirm: () => dispatch(submitCompose(routerHistory)),
 | 
					 | 
				
			||||||
      onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_missing_media_description'], false)),
 | 
					 | 
				
			||||||
    }));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onSubmit(routerHistory) {
 | 
					 | 
				
			||||||
    dispatch(submitCompose(routerHistory));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onUndoUpload(id) {
 | 
					 | 
				
			||||||
    dispatch(undoUploadCompose(id));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onUnmount() {
 | 
					 | 
				
			||||||
    dispatch(unmountCompose());
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  onUpload(files) {
 | 
					 | 
				
			||||||
    dispatch(uploadCompose(files));
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
//  Handlers.
 | 
					    //  State props.
 | 
				
			||||||
const handlers = {
 | 
					    acceptContentTypes: PropTypes.string,
 | 
				
			||||||
 | 
					    advancedOptions: ImmutablePropTypes.map,
 | 
				
			||||||
 | 
					    amUnlocked: PropTypes.bool,
 | 
				
			||||||
 | 
					    focusDate: PropTypes.instanceOf(Date),
 | 
				
			||||||
 | 
					    caretPosition: PropTypes.number,
 | 
				
			||||||
 | 
					    isSubmitting: PropTypes.bool,
 | 
				
			||||||
 | 
					    isChangingUpload: PropTypes.bool,
 | 
				
			||||||
 | 
					    isUploading: PropTypes.bool,
 | 
				
			||||||
 | 
					    layout: PropTypes.string,
 | 
				
			||||||
 | 
					    media: ImmutablePropTypes.list,
 | 
				
			||||||
 | 
					    preselectDate: PropTypes.instanceOf(Date),
 | 
				
			||||||
 | 
					    privacy: PropTypes.string,
 | 
				
			||||||
 | 
					    progress: PropTypes.number,
 | 
				
			||||||
 | 
					    inReplyTo: ImmutablePropTypes.map,
 | 
				
			||||||
 | 
					    resetFileKey: PropTypes.number,
 | 
				
			||||||
 | 
					    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.
 | 
				
			||||||
 | 
					    onCancelReply: PropTypes.func,
 | 
				
			||||||
 | 
					    onChangeAdvancedOption: PropTypes.func,
 | 
				
			||||||
 | 
					    onChangeDescription: PropTypes.func,
 | 
				
			||||||
 | 
					    onChangeSensitivity: PropTypes.func,
 | 
				
			||||||
 | 
					    onChangeSpoilerText: PropTypes.func,
 | 
				
			||||||
 | 
					    onChangeSpoilerness: PropTypes.func,
 | 
				
			||||||
 | 
					    onChangeText: PropTypes.func,
 | 
				
			||||||
 | 
					    onChangeVisibility: PropTypes.func,
 | 
				
			||||||
 | 
					    onClearSuggestions: PropTypes.func,
 | 
				
			||||||
 | 
					    onCloseModal: PropTypes.func,
 | 
				
			||||||
 | 
					    onFetchSuggestions: PropTypes.func,
 | 
				
			||||||
 | 
					    onInsertEmoji: PropTypes.func,
 | 
				
			||||||
 | 
					    onMount: PropTypes.func,
 | 
				
			||||||
 | 
					    onOpenActionsModal: PropTypes.func,
 | 
				
			||||||
 | 
					    onOpenDoodleModal: PropTypes.func,
 | 
				
			||||||
 | 
					    onSelectSuggestion: PropTypes.func,
 | 
				
			||||||
 | 
					    onSubmit: PropTypes.func,
 | 
				
			||||||
 | 
					    onUndoUpload: PropTypes.func,
 | 
				
			||||||
 | 
					    onUnmount: PropTypes.func,
 | 
				
			||||||
 | 
					    onUpload: PropTypes.func,
 | 
				
			||||||
 | 
					    onMediaDescriptionConfirm: PropTypes.func,
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //  Changes the text value of the spoiler.
 | 
					  //  Changes the text value of the spoiler.
 | 
				
			||||||
  handleChangeSpoiler ({ target: { value } }) {
 | 
					  handleChangeSpoiler = ({ target: { value } }) => {
 | 
				
			||||||
    const { onChangeSpoilerText } = this.props;
 | 
					    const { onChangeSpoilerText } = this.props;
 | 
				
			||||||
    if (onChangeSpoilerText) {
 | 
					    if (onChangeSpoilerText) {
 | 
				
			||||||
      onChangeSpoilerText(value);
 | 
					      onChangeSpoilerText(value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //  Inserts an emoji at the caret.
 | 
					  //  Inserts an emoji at the caret.
 | 
				
			||||||
  handleEmoji (data) {
 | 
					  handleEmoji = (data) => {
 | 
				
			||||||
    const { textarea: { selectionStart } } = this;
 | 
					    const { textarea: { selectionStart } } = this;
 | 
				
			||||||
    const { onInsertEmoji } = this.props;
 | 
					    const { onInsertEmoji } = this.props;
 | 
				
			||||||
    if (onInsertEmoji) {
 | 
					    if (onInsertEmoji) {
 | 
				
			||||||
      onInsertEmoji(selectionStart, data);
 | 
					      onInsertEmoji(selectionStart, data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //  Handles the secondary submit button.
 | 
					  //  Handles the secondary submit button.
 | 
				
			||||||
  handleSecondarySubmit () {
 | 
					  handleSecondarySubmit = () => {
 | 
				
			||||||
    const { handleSubmit } = this.handlers;
 | 
					    const { handleSubmit } = this.handlers;
 | 
				
			||||||
    const {
 | 
					    const {
 | 
				
			||||||
      onChangeVisibility,
 | 
					      onChangeVisibility,
 | 
				
			||||||
| 
						 | 
					@ -226,18 +120,18 @@ const handlers = {
 | 
				
			||||||
      onChangeVisibility(sideArm);
 | 
					      onChangeVisibility(sideArm);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    handleSubmit();
 | 
					    handleSubmit();
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //  Selects a suggestion from the autofill.
 | 
					  //  Selects a suggestion from the autofill.
 | 
				
			||||||
  handleSelect (tokenStart, token, value) {
 | 
					  handleSelect = (tokenStart, token, value) => {
 | 
				
			||||||
    const { onSelectSuggestion } = this.props;
 | 
					    const { onSelectSuggestion } = this.props;
 | 
				
			||||||
    if (onSelectSuggestion) {
 | 
					    if (onSelectSuggestion) {
 | 
				
			||||||
      onSelectSuggestion(tokenStart, token, value);
 | 
					      onSelectSuggestion(tokenStart, token, value);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //  Submits the status.
 | 
					  //  Submits the status.
 | 
				
			||||||
  handleSubmit () {
 | 
					  handleSubmit = () => {
 | 
				
			||||||
    const { textarea: { value }, uploadForm } = this;
 | 
					    const { textarea: { value }, uploadForm } = this;
 | 
				
			||||||
    const {
 | 
					    const {
 | 
				
			||||||
      onChangeText,
 | 
					      onChangeText,
 | 
				
			||||||
| 
						 | 
					@ -276,40 +170,26 @@ const handlers = {
 | 
				
			||||||
    } else if (onSubmit) {
 | 
					    } else if (onSubmit) {
 | 
				
			||||||
      onSubmit(this.context.router ? this.context.router.history : null);
 | 
					      onSubmit(this.context.router ? this.context.router.history : null);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //  Sets a reference to the upload form.
 | 
					  //  Sets a reference to the upload form.
 | 
				
			||||||
  handleRefUploadForm (uploadFormComponent) {
 | 
					  handleRefUploadForm = (uploadFormComponent) => {
 | 
				
			||||||
    this.uploadForm = uploadFormComponent;
 | 
					    this.uploadForm = uploadFormComponent;
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //  Sets a reference to the textarea.
 | 
					  //  Sets a reference to the textarea.
 | 
				
			||||||
  handleRefTextarea (textareaComponent) {
 | 
					  handleRefTextarea = (textareaComponent) => {
 | 
				
			||||||
    if (textareaComponent) {
 | 
					    if (textareaComponent) {
 | 
				
			||||||
      this.textarea = textareaComponent.textarea;
 | 
					      this.textarea = textareaComponent.textarea;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  },
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //  Sets a reference to the CW field.
 | 
					  //  Sets a reference to the CW field.
 | 
				
			||||||
  handleRefSpoilerText (spoilerComponent) {
 | 
					  handleRefSpoilerText = (spoilerComponent) => {
 | 
				
			||||||
    if (spoilerComponent) {
 | 
					    if (spoilerComponent) {
 | 
				
			||||||
      this.spoilerText = spoilerComponent.spoilerText;
 | 
					      this.spoilerText = spoilerComponent.spoilerText;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//  The component.
 | 
					 | 
				
			||||||
class Composer extends React.Component {
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  //  Constructor.
 | 
					 | 
				
			||||||
  constructor (props) {
 | 
					 | 
				
			||||||
    super(props);
 | 
					 | 
				
			||||||
    assignHandlers(this, handlers);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //  Instance variables.
 | 
					 | 
				
			||||||
    this.textarea = null;
 | 
					 | 
				
			||||||
    this.spoilerText = null;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  //  Tells our state the composer has been mounted.
 | 
					  //  Tells our state the composer has been mounted.
 | 
				
			||||||
  componentDidMount () {
 | 
					  componentDidMount () {
 | 
				
			||||||
| 
						 | 
					@ -394,7 +274,7 @@ class Composer extends React.Component {
 | 
				
			||||||
      handleRefUploadForm,
 | 
					      handleRefUploadForm,
 | 
				
			||||||
      handleRefTextarea,
 | 
					      handleRefTextarea,
 | 
				
			||||||
      handleRefSpoilerText,
 | 
					      handleRefSpoilerText,
 | 
				
			||||||
    } = this.handlers;
 | 
					    } = this;
 | 
				
			||||||
    const {
 | 
					    const {
 | 
				
			||||||
      acceptContentTypes,
 | 
					      acceptContentTypes,
 | 
				
			||||||
      advancedOptions,
 | 
					      advancedOptions,
 | 
				
			||||||
| 
						 | 
					@ -533,68 +413,3 @@ class Composer extends React.Component {
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
//  Props.
 | 
					 | 
				
			||||||
Composer.propTypes = {
 | 
					 | 
				
			||||||
  intl: PropTypes.object.isRequired,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  //  State props.
 | 
					 | 
				
			||||||
  acceptContentTypes: PropTypes.string,
 | 
					 | 
				
			||||||
  advancedOptions: ImmutablePropTypes.map,
 | 
					 | 
				
			||||||
  amUnlocked: PropTypes.bool,
 | 
					 | 
				
			||||||
  focusDate: PropTypes.instanceOf(Date),
 | 
					 | 
				
			||||||
  caretPosition: PropTypes.number,
 | 
					 | 
				
			||||||
  isSubmitting: PropTypes.bool,
 | 
					 | 
				
			||||||
  isChangingUpload: PropTypes.bool,
 | 
					 | 
				
			||||||
  isUploading: PropTypes.bool,
 | 
					 | 
				
			||||||
  layout: PropTypes.string,
 | 
					 | 
				
			||||||
  media: ImmutablePropTypes.list,
 | 
					 | 
				
			||||||
  preselectDate: PropTypes.instanceOf(Date),
 | 
					 | 
				
			||||||
  privacy: PropTypes.string,
 | 
					 | 
				
			||||||
  progress: PropTypes.number,
 | 
					 | 
				
			||||||
  inReplyTo: ImmutablePropTypes.map,
 | 
					 | 
				
			||||||
  resetFileKey: PropTypes.number,
 | 
					 | 
				
			||||||
  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.
 | 
					 | 
				
			||||||
  onCancelReply: PropTypes.func,
 | 
					 | 
				
			||||||
  onChangeAdvancedOption: PropTypes.func,
 | 
					 | 
				
			||||||
  onChangeDescription: PropTypes.func,
 | 
					 | 
				
			||||||
  onChangeSensitivity: PropTypes.func,
 | 
					 | 
				
			||||||
  onChangeSpoilerText: PropTypes.func,
 | 
					 | 
				
			||||||
  onChangeSpoilerness: PropTypes.func,
 | 
					 | 
				
			||||||
  onChangeText: PropTypes.func,
 | 
					 | 
				
			||||||
  onChangeVisibility: PropTypes.func,
 | 
					 | 
				
			||||||
  onClearSuggestions: PropTypes.func,
 | 
					 | 
				
			||||||
  onCloseModal: PropTypes.func,
 | 
					 | 
				
			||||||
  onFetchSuggestions: PropTypes.func,
 | 
					 | 
				
			||||||
  onInsertEmoji: PropTypes.func,
 | 
					 | 
				
			||||||
  onMount: PropTypes.func,
 | 
					 | 
				
			||||||
  onOpenActionsModal: PropTypes.func,
 | 
					 | 
				
			||||||
  onOpenDoodleModal: PropTypes.func,
 | 
					 | 
				
			||||||
  onSelectSuggestion: PropTypes.func,
 | 
					 | 
				
			||||||
  onSubmit: PropTypes.func,
 | 
					 | 
				
			||||||
  onUndoUpload: PropTypes.func,
 | 
					 | 
				
			||||||
  onUnmount: PropTypes.func,
 | 
					 | 
				
			||||||
  onUpload: PropTypes.func,
 | 
					 | 
				
			||||||
  onMediaDescriptionConfirm: PropTypes.func,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Composer.contextTypes = {
 | 
					 | 
				
			||||||
  router: PropTypes.object,
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//  Connecting and export.
 | 
					 | 
				
			||||||
export { Composer as WrappedComponent };
 | 
					 | 
				
			||||||
export default wrap(Composer, mapStateToProps, mapDispatchToProps, true);
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,175 @@
 | 
				
			||||||
 | 
					import { connect } from 'react-redux';
 | 
				
			||||||
 | 
					import ComposeForm from '../components/compose_form';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  cancelReplyCompose,
 | 
				
			||||||
 | 
					  changeCompose,
 | 
				
			||||||
 | 
					  changeComposeAdvancedOption,
 | 
				
			||||||
 | 
					  changeComposeSensitivity,
 | 
				
			||||||
 | 
					  changeComposeSpoilerText,
 | 
				
			||||||
 | 
					  changeComposeSpoilerness,
 | 
				
			||||||
 | 
					  changeComposeVisibility,
 | 
				
			||||||
 | 
					  changeUploadCompose,
 | 
				
			||||||
 | 
					  clearComposeSuggestions,
 | 
				
			||||||
 | 
					  fetchComposeSuggestions,
 | 
				
			||||||
 | 
					  insertEmojiCompose,
 | 
				
			||||||
 | 
					  mountCompose,
 | 
				
			||||||
 | 
					  selectComposeSuggestion,
 | 
				
			||||||
 | 
					  submitCompose,
 | 
				
			||||||
 | 
					  undoUploadCompose,
 | 
				
			||||||
 | 
					  unmountCompose,
 | 
				
			||||||
 | 
					  uploadCompose,
 | 
				
			||||||
 | 
					} from 'flavours/glitch/actions/compose';
 | 
				
			||||||
 | 
					import {
 | 
				
			||||||
 | 
					  closeModal,
 | 
				
			||||||
 | 
					  openModal,
 | 
				
			||||||
 | 
					} from 'flavours/glitch/actions/modal';
 | 
				
			||||||
 | 
					import { changeLocalSetting } from 'flavours/glitch/actions/local_settings';
 | 
				
			||||||
 | 
					import { addPoll, removePoll } from 'flavours/glitch/actions/compose';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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',
 | 
				
			||||||
 | 
					                                defaultMessage: 'At least one media attachment is lacking a description. Consider describing all media attachments for the visually impaired before sending your toot.' },
 | 
				
			||||||
 | 
					  missingDescriptionConfirm: {  id: 'confirmations.missing_media_description.confirm',
 | 
				
			||||||
 | 
					                                defaultMessage: 'Send anyway' },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					import { defineMessages } from 'react-intl';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  State mapping.
 | 
				
			||||||
 | 
					function mapStateToProps (state) {
 | 
				
			||||||
 | 
					  const spoilersAlwaysOn = state.getIn(['local_settings', 'always_show_spoilers_field']);
 | 
				
			||||||
 | 
					  const inReplyTo = state.getIn(['compose', 'in_reply_to']);
 | 
				
			||||||
 | 
					  const replyPrivacy = inReplyTo ? state.getIn(['statuses', inReplyTo, 'visibility']) : null;
 | 
				
			||||||
 | 
					  const sideArmBasePrivacy = state.getIn(['local_settings', 'side_arm']);
 | 
				
			||||||
 | 
					  const sideArmRestrictedPrivacy = replyPrivacy ? privacyPreference(replyPrivacy, sideArmBasePrivacy) : null;
 | 
				
			||||||
 | 
					  let sideArmPrivacy = null;
 | 
				
			||||||
 | 
					  switch (state.getIn(['local_settings', 'side_arm_reply_mode'])) {
 | 
				
			||||||
 | 
					    case 'copy':
 | 
				
			||||||
 | 
					      sideArmPrivacy = replyPrivacy;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					    case 'restrict':
 | 
				
			||||||
 | 
					      sideArmPrivacy = sideArmRestrictedPrivacy;
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  sideArmPrivacy = sideArmPrivacy || sideArmBasePrivacy;
 | 
				
			||||||
 | 
					  return {
 | 
				
			||||||
 | 
					    acceptContentTypes: state.getIn(['media_attachments', 'accept_content_types']).toArray().join(','),
 | 
				
			||||||
 | 
					    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']),
 | 
				
			||||||
 | 
					    isChangingUpload: state.getIn(['compose', 'is_changing_upload']),
 | 
				
			||||||
 | 
					    isUploading: state.getIn(['compose', 'is_uploading']),
 | 
				
			||||||
 | 
					    layout: state.getIn(['local_settings', 'layout']),
 | 
				
			||||||
 | 
					    media: state.getIn(['compose', 'media_attachments']),
 | 
				
			||||||
 | 
					    preselectDate: state.getIn(['compose', 'preselectDate']),
 | 
				
			||||||
 | 
					    privacy: state.getIn(['compose', 'privacy']),
 | 
				
			||||||
 | 
					    progress: state.getIn(['compose', 'progress']),
 | 
				
			||||||
 | 
					    inReplyTo: inReplyTo ? state.getIn(['statuses', inReplyTo]) : null,
 | 
				
			||||||
 | 
					    replyAccount: inReplyTo ? state.getIn(['statuses', inReplyTo, 'account']) : null,
 | 
				
			||||||
 | 
					    replyContent: inReplyTo ? state.getIn(['statuses', inReplyTo, 'contentHtml']) : null,
 | 
				
			||||||
 | 
					    resetFileKey: state.getIn(['compose', 'resetFileKey']),
 | 
				
			||||||
 | 
					    sideArm: sideArmPrivacy,
 | 
				
			||||||
 | 
					    sensitive: state.getIn(['compose', 'sensitive']),
 | 
				
			||||||
 | 
					    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,
 | 
				
			||||||
 | 
					    poll: state.getIn(['compose', 'poll']),
 | 
				
			||||||
 | 
					    spoilersAlwaysOn: spoilersAlwaysOn,
 | 
				
			||||||
 | 
					    mediaDescriptionConfirmation: state.getIn(['local_settings', 'confirm_missing_media_description']),
 | 
				
			||||||
 | 
					    preselectOnReply: state.getIn(['local_settings', 'preselect_on_reply']),
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//  Dispatch mapping.
 | 
				
			||||||
 | 
					const mapDispatchToProps = (dispatch, { intl }) => ({
 | 
				
			||||||
 | 
					  onCancelReply() {
 | 
				
			||||||
 | 
					    dispatch(cancelReplyCompose());
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onChangeAdvancedOption(option, value) {
 | 
				
			||||||
 | 
					    dispatch(changeComposeAdvancedOption(option, value));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onChangeDescription(id, description) {
 | 
				
			||||||
 | 
					    dispatch(changeUploadCompose(id, { description }));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onChangeSensitivity() {
 | 
				
			||||||
 | 
					    dispatch(changeComposeSensitivity());
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onChangeSpoilerText(text) {
 | 
				
			||||||
 | 
					    dispatch(changeComposeSpoilerText(text));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onChangeSpoilerness() {
 | 
				
			||||||
 | 
					    dispatch(changeComposeSpoilerness());
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onChangeText(text) {
 | 
				
			||||||
 | 
					    dispatch(changeCompose(text));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onChangeVisibility(value) {
 | 
				
			||||||
 | 
					    dispatch(changeComposeVisibility(value));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onTogglePoll() {
 | 
				
			||||||
 | 
					    dispatch((_, getState) => {
 | 
				
			||||||
 | 
					      if (getState().getIn(['compose', 'poll'])) {
 | 
				
			||||||
 | 
					        dispatch(removePoll());
 | 
				
			||||||
 | 
					      } else {
 | 
				
			||||||
 | 
					        dispatch(addPoll());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onClearSuggestions() {
 | 
				
			||||||
 | 
					    dispatch(clearComposeSuggestions());
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onCloseModal() {
 | 
				
			||||||
 | 
					    dispatch(closeModal());
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onFetchSuggestions(token) {
 | 
				
			||||||
 | 
					    dispatch(fetchComposeSuggestions(token));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onInsertEmoji(position, emoji) {
 | 
				
			||||||
 | 
					    dispatch(insertEmojiCompose(position, emoji));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onMount() {
 | 
				
			||||||
 | 
					    dispatch(mountCompose());
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onOpenActionsModal(props) {
 | 
				
			||||||
 | 
					    dispatch(openModal('ACTIONS', props));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onOpenDoodleModal() {
 | 
				
			||||||
 | 
					    dispatch(openModal('DOODLE', { noEsc: true }));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onOpenFocalPointModal(id) {
 | 
				
			||||||
 | 
					    dispatch(openModal('FOCAL_POINT', { id }));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onSelectSuggestion(position, token, suggestion) {
 | 
				
			||||||
 | 
					    dispatch(selectComposeSuggestion(position, token, suggestion));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onMediaDescriptionConfirm(routerHistory) {
 | 
				
			||||||
 | 
					    dispatch(openModal('CONFIRM', {
 | 
				
			||||||
 | 
					      message: intl.formatMessage(messages.missingDescriptionMessage),
 | 
				
			||||||
 | 
					      confirm: intl.formatMessage(messages.missingDescriptionConfirm),
 | 
				
			||||||
 | 
					      onConfirm: () => dispatch(submitCompose(routerHistory)),
 | 
				
			||||||
 | 
					      onDoNotAsk: () => dispatch(changeLocalSetting(['confirm_missing_media_description'], false)),
 | 
				
			||||||
 | 
					    }));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onSubmit(routerHistory) {
 | 
				
			||||||
 | 
					    dispatch(submitCompose(routerHistory));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onUndoUpload(id) {
 | 
				
			||||||
 | 
					    dispatch(undoUploadCompose(id));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onUnmount() {
 | 
				
			||||||
 | 
					    dispatch(unmountCompose());
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  onUpload(files) {
 | 
				
			||||||
 | 
					    dispatch(uploadCompose(files));
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default connect(mapStateToProps, mapDispatchToProps)(ComposeForm);
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ import classNames from 'classnames';
 | 
				
			||||||
import { cycleElefriendCompose } from 'flavours/glitch/actions/compose';
 | 
					import { cycleElefriendCompose } from 'flavours/glitch/actions/compose';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//  Components.
 | 
					//  Components.
 | 
				
			||||||
import Composer from 'flavours/glitch/features/composer';
 | 
					import ComposeFormContainer from './containers/compose_form_container';
 | 
				
			||||||
import HeaderContainer from './containers/header_container';
 | 
					import HeaderContainer from './containers/header_container';
 | 
				
			||||||
import SearchContainer from './containers/search_container';
 | 
					import SearchContainer from './containers/search_container';
 | 
				
			||||||
import SearchResultsContainer from './containers/search_results_container';
 | 
					import SearchResultsContainer from './containers/search_results_container';
 | 
				
			||||||
| 
						 | 
					@ -73,11 +73,13 @@ class Compose extends React.PureComponent {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div className={computedClass} role='region' aria-label={intl.formatMessage(messages.compose)}>
 | 
					      <div className={computedClass} role='region' aria-label={intl.formatMessage(messages.compose)}>
 | 
				
			||||||
        {multiColumn && <HeaderContainer />}
 | 
					        {multiColumn && <HeaderContainer />}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        {(multiColumn || isSearchPage) && <SearchContainer />}
 | 
					        {(multiColumn || isSearchPage) && <SearchContainer />}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div className='drawer__pager'>
 | 
					        <div className='drawer__pager'>
 | 
				
			||||||
          {!isSearchPage && <div className='drawer__inner'>
 | 
					          {!isSearchPage && <div className='drawer__inner'>
 | 
				
			||||||
            <NavigationContainer />
 | 
					            <NavigationContainer />
 | 
				
			||||||
            <Composer />
 | 
					            <ComposeFormContainer />
 | 
				
			||||||
            {multiColumn && (
 | 
					            {multiColumn && (
 | 
				
			||||||
              <div className='drawer__inner__mastodon'>
 | 
					              <div className='drawer__inner__mastodon'>
 | 
				
			||||||
                {mascot ? <img alt='' draggable='false' src={mascot} /> : <button className='mastodon' onClick={onClickElefriend} />}
 | 
					                {mascot ? <img alt='' draggable='false' src={mascot} /> : <button className='mastodon' onClick={onClickElefriend} />}
 | 
				
			||||||
| 
						 | 
					@ -96,4 +98,5 @@ class Compose extends React.PureComponent {
 | 
				
			||||||
      </div>
 | 
					      </div>
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,5 +1,5 @@
 | 
				
			||||||
import React from 'react';
 | 
					import React from 'react';
 | 
				
			||||||
import Composer from 'flavours/glitch/features/composer';
 | 
					import ComposeFormContainer from 'flavours/glitch/features/compose/containers/compose_form_container';
 | 
				
			||||||
import NotificationsContainer from 'flavours/glitch/features/ui/containers/notifications_container';
 | 
					import NotificationsContainer from 'flavours/glitch/features/ui/containers/notifications_container';
 | 
				
			||||||
import LoadingBarContainer from 'flavours/glitch/features/ui/containers/loading_bar_container';
 | 
					import LoadingBarContainer from 'flavours/glitch/features/ui/containers/loading_bar_container';
 | 
				
			||||||
import ModalContainer from 'flavours/glitch/features/ui/containers/modal_container';
 | 
					import ModalContainer from 'flavours/glitch/features/ui/containers/modal_container';
 | 
				
			||||||
| 
						 | 
					@ -9,7 +9,7 @@ export default class Compose extends React.PureComponent {
 | 
				
			||||||
  render () {
 | 
					  render () {
 | 
				
			||||||
    return (
 | 
					    return (
 | 
				
			||||||
      <div>
 | 
					      <div>
 | 
				
			||||||
        <Composer />
 | 
					        <ComposeFormContainer />
 | 
				
			||||||
        <NotificationsContainer />
 | 
					        <NotificationsContainer />
 | 
				
			||||||
        <ModalContainer />
 | 
					        <ModalContainer />
 | 
				
			||||||
        <LoadingBarContainer className='loading-bar' />
 | 
					        <LoadingBarContainer className='loading-bar' />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
				
			||||||
import ReactSwipeableViews from 'react-swipeable-views';
 | 
					import ReactSwipeableViews from 'react-swipeable-views';
 | 
				
			||||||
import classNames from 'classnames';
 | 
					import classNames from 'classnames';
 | 
				
			||||||
import Permalink from 'flavours/glitch/components/permalink';
 | 
					import Permalink from 'flavours/glitch/components/permalink';
 | 
				
			||||||
import { WrappedComponent as RawComposer } from 'flavours/glitch/features/composer';
 | 
					import { ComposeForm } from 'flavours/glitch/features/compose/components/compose_form';
 | 
				
			||||||
import DrawerAccount from 'flavours/glitch/features/compose/components/navigation_bar';
 | 
					import DrawerAccount from 'flavours/glitch/features/compose/components/navigation_bar';
 | 
				
			||||||
import Search from 'flavours/glitch/features/compose/components/search';
 | 
					import Search from 'flavours/glitch/features/compose/components/search';
 | 
				
			||||||
import ColumnHeader from './column_header';
 | 
					import ColumnHeader from './column_header';
 | 
				
			||||||
| 
						 | 
					@ -45,8 +45,7 @@ const PageTwo = ({ intl, myAccount }) => (
 | 
				
			||||||
    <div className='figure non-interactive'>
 | 
					    <div className='figure non-interactive'>
 | 
				
			||||||
      <div className='pseudo-drawer'>
 | 
					      <div className='pseudo-drawer'>
 | 
				
			||||||
        <DrawerAccount account={myAccount} />
 | 
					        <DrawerAccount account={myAccount} />
 | 
				
			||||||
        <RawComposer
 | 
					        <ComposeForm
 | 
				
			||||||
          intl={intl}
 | 
					 | 
				
			||||||
          privacy='public'
 | 
					          privacy='public'
 | 
				
			||||||
          text='Awoo! #introductions'
 | 
					          text='Awoo! #introductions'
 | 
				
			||||||
        />
 | 
					        />
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue