Add explanation to mute dialog, refactor and clean up mute/block UI (#11992)
* Add some explanation to the mute modal dialog * Remove `isSubmitting` from mute modal code, this wasn't used * Refactor block modal Signed-off-by: Thibaut Girka <thib@sitedethib.com> * Refactor SCSS a bit * Put mute modal toggle to the same side as in the report dialog for consistency * Reword mute explanation * Fix mute explanation styling * Left-align all text in mute confirmation modal
This commit is contained in:
		
							parent
							
								
									5f69eb89e2
								
							
						
					
					
						commit
						9027bfff0c
					
				
					 14 changed files with 222 additions and 88 deletions
				
			
		| 
						 | 
				
			
			@ -5,7 +5,6 @@ import Header from '../components/header';
 | 
			
		|||
import {
 | 
			
		||||
  followAccount,
 | 
			
		||||
  unfollowAccount,
 | 
			
		||||
  blockAccount,
 | 
			
		||||
  unblockAccount,
 | 
			
		||||
  unmuteAccount,
 | 
			
		||||
  pinAccount,
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +15,7 @@ import {
 | 
			
		|||
  directCompose,
 | 
			
		||||
} from '../../../actions/compose';
 | 
			
		||||
import { initMuteModal } from '../../../actions/mutes';
 | 
			
		||||
import { initBlockModal } from '../../../actions/blocks';
 | 
			
		||||
import { initReport } from '../../../actions/reports';
 | 
			
		||||
import { openModal } from '../../../actions/modal';
 | 
			
		||||
import { blockDomain, unblockDomain } from '../../../actions/domain_blocks';
 | 
			
		||||
| 
						 | 
				
			
			@ -25,9 +25,7 @@ import { List as ImmutableList } from 'immutable';
 | 
			
		|||
 | 
			
		||||
const messages = defineMessages({
 | 
			
		||||
  unfollowConfirm: { id: 'confirmations.unfollow.confirm', defaultMessage: 'Unfollow' },
 | 
			
		||||
  blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
 | 
			
		||||
  blockDomainConfirm: { id: 'confirmations.domain_block.confirm', defaultMessage: 'Hide entire domain' },
 | 
			
		||||
  blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const makeMapStateToProps = () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -64,16 +62,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
 | 
			
		|||
    if (account.getIn(['relationship', 'blocking'])) {
 | 
			
		||||
      dispatch(unblockAccount(account.get('id')));
 | 
			
		||||
    } else {
 | 
			
		||||
      dispatch(openModal('CONFIRM', {
 | 
			
		||||
        message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
 | 
			
		||||
        confirm: intl.formatMessage(messages.blockConfirm),
 | 
			
		||||
        onConfirm: () => dispatch(blockAccount(account.get('id'))),
 | 
			
		||||
        secondary: intl.formatMessage(messages.blockAndReport),
 | 
			
		||||
        onSecondary: () => {
 | 
			
		||||
          dispatch(blockAccount(account.get('id')));
 | 
			
		||||
          dispatch(initReport(account));
 | 
			
		||||
        },
 | 
			
		||||
      }));
 | 
			
		||||
      dispatch(initBlockModal(account));
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,3 @@
 | 
			
		|||
import React from 'react';
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
import DetailedStatus from '../components/detailed_status';
 | 
			
		||||
import { makeGetStatus } from '../../../selectors';
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +14,6 @@ import {
 | 
			
		|||
  pin,
 | 
			
		||||
  unpin,
 | 
			
		||||
} from '../../../actions/interactions';
 | 
			
		||||
import { blockAccount } from '../../../actions/accounts';
 | 
			
		||||
import {
 | 
			
		||||
  muteStatus,
 | 
			
		||||
  unmuteStatus,
 | 
			
		||||
| 
						 | 
				
			
			@ -24,9 +22,10 @@ import {
 | 
			
		|||
  revealStatus,
 | 
			
		||||
} from '../../../actions/statuses';
 | 
			
		||||
import { initMuteModal } from '../../../actions/mutes';
 | 
			
		||||
import { initBlockModal } from '../../../actions/blocks';
 | 
			
		||||
import { initReport } from '../../../actions/reports';
 | 
			
		||||
import { openModal } from '../../../actions/modal';
 | 
			
		||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
			
		||||
import { boostModal, deleteModal } from '../../../initial_state';
 | 
			
		||||
import { showAlertForError } from '../../../actions/alerts';
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -35,10 +34,8 @@ const messages = defineMessages({
 | 
			
		|||
  deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
 | 
			
		||||
  redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
 | 
			
		||||
  redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.' },
 | 
			
		||||
  blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
 | 
			
		||||
  replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
 | 
			
		||||
  replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
 | 
			
		||||
  blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const makeMapStateToProps = () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -138,16 +135,7 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
 | 
			
		|||
 | 
			
		||||
  onBlock (status) {
 | 
			
		||||
    const account = status.get('account');
 | 
			
		||||
    dispatch(openModal('CONFIRM', {
 | 
			
		||||
      message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
 | 
			
		||||
      confirm: intl.formatMessage(messages.blockConfirm),
 | 
			
		||||
      onConfirm: () => dispatch(blockAccount(account.get('id'))),
 | 
			
		||||
      secondary: intl.formatMessage(messages.blockAndReport),
 | 
			
		||||
      onSecondary: () => {
 | 
			
		||||
        dispatch(blockAccount(account.get('id')));
 | 
			
		||||
        dispatch(initReport(account, status));
 | 
			
		||||
      },
 | 
			
		||||
    }));
 | 
			
		||||
    dispatch(initBlockModal(account));
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  onReport (status) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,6 @@ import {
 | 
			
		|||
  mentionCompose,
 | 
			
		||||
  directCompose,
 | 
			
		||||
} from '../../actions/compose';
 | 
			
		||||
import { blockAccount } from '../../actions/accounts';
 | 
			
		||||
import {
 | 
			
		||||
  muteStatus,
 | 
			
		||||
  unmuteStatus,
 | 
			
		||||
| 
						 | 
				
			
			@ -32,6 +31,7 @@ import {
 | 
			
		|||
  revealStatus,
 | 
			
		||||
} from '../../actions/statuses';
 | 
			
		||||
import { initMuteModal } from '../../actions/mutes';
 | 
			
		||||
import { initBlockModal } from '../../actions/blocks';
 | 
			
		||||
import { initReport } from '../../actions/reports';
 | 
			
		||||
import { makeGetStatus } from '../../selectors';
 | 
			
		||||
import { ScrollContainer } from 'react-router-scroll-4';
 | 
			
		||||
| 
						 | 
				
			
			@ -39,7 +39,7 @@ import ColumnBackButton from '../../components/column_back_button';
 | 
			
		|||
import ColumnHeader from '../../components/column_header';
 | 
			
		||||
import StatusContainer from '../../containers/status_container';
 | 
			
		||||
import { openModal } from '../../actions/modal';
 | 
			
		||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
			
		||||
import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
			
		||||
import { HotKeys } from 'react-hotkeys';
 | 
			
		||||
import { boostModal, deleteModal } from '../../initial_state';
 | 
			
		||||
| 
						 | 
				
			
			@ -52,13 +52,11 @@ const messages = defineMessages({
 | 
			
		|||
  deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this status?' },
 | 
			
		||||
  redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
 | 
			
		||||
  redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this status and re-draft it? Favourites and boosts will be lost, and replies to the original post will be orphaned.' },
 | 
			
		||||
  blockConfirm: { id: 'confirmations.block.confirm', defaultMessage: 'Block' },
 | 
			
		||||
  revealAll: { id: 'status.show_more_all', defaultMessage: 'Show more for all' },
 | 
			
		||||
  hideAll: { id: 'status.show_less_all', defaultMessage: 'Show less for all' },
 | 
			
		||||
  detailedStatus: { id: 'status.detailed_status', defaultMessage: 'Detailed conversation view' },
 | 
			
		||||
  replyConfirm: { id: 'confirmations.reply.confirm', defaultMessage: 'Reply' },
 | 
			
		||||
  replyMessage: { id: 'confirmations.reply.message', defaultMessage: 'Replying now will overwrite the message you are currently composing. Are you sure you want to proceed?' },
 | 
			
		||||
  blockAndReport: { id: 'confirmations.block.block_and_report', defaultMessage: 'Block & Report' },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const makeMapStateToProps = () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -296,19 +294,9 @@ class Status extends ImmutablePureComponent {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  handleBlockClick = (status) => {
 | 
			
		||||
    const { dispatch, intl } = this.props;
 | 
			
		||||
    const { dispatch } = this.props;
 | 
			
		||||
    const account = status.get('account');
 | 
			
		||||
 | 
			
		||||
    dispatch(openModal('CONFIRM', {
 | 
			
		||||
      message: <FormattedMessage id='confirmations.block.message' defaultMessage='Are you sure you want to block {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
 | 
			
		||||
      confirm: intl.formatMessage(messages.blockConfirm),
 | 
			
		||||
      onConfirm: () => dispatch(blockAccount(account.get('id'))),
 | 
			
		||||
      secondary: intl.formatMessage(messages.blockAndReport),
 | 
			
		||||
      onSecondary: () => {
 | 
			
		||||
        dispatch(blockAccount(account.get('id')));
 | 
			
		||||
        dispatch(initReport(account, status));
 | 
			
		||||
      },
 | 
			
		||||
    }));
 | 
			
		||||
    dispatch(initBlockModal(account));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleReport = (status) => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										103
									
								
								app/javascript/mastodon/features/ui/components/block_modal.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								app/javascript/mastodon/features/ui/components/block_modal.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,103 @@
 | 
			
		|||
import React from 'react';
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
import { injectIntl, FormattedMessage } from 'react-intl';
 | 
			
		||||
import { makeGetAccount } from '../../../selectors';
 | 
			
		||||
import Button from '../../../components/button';
 | 
			
		||||
import { closeModal } from '../../../actions/modal';
 | 
			
		||||
import { blockAccount } from '../../../actions/accounts';
 | 
			
		||||
import { initReport } from '../../../actions/reports';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const makeMapStateToProps = () => {
 | 
			
		||||
  const getAccount = makeGetAccount();
 | 
			
		||||
 | 
			
		||||
  const mapStateToProps = state => ({
 | 
			
		||||
    account: getAccount(state, state.getIn(['blocks', 'new', 'account_id'])),
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  return mapStateToProps;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const mapDispatchToProps = dispatch => {
 | 
			
		||||
  return {
 | 
			
		||||
    onConfirm(account) {
 | 
			
		||||
      dispatch(blockAccount(account.get('id')));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onBlockAndReport(account) {
 | 
			
		||||
      dispatch(blockAccount(account.get('id')));
 | 
			
		||||
      dispatch(initReport(account));
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
    onClose() {
 | 
			
		||||
      dispatch(closeModal());
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default @connect(makeMapStateToProps, mapDispatchToProps)
 | 
			
		||||
@injectIntl
 | 
			
		||||
class BlockModal extends React.PureComponent {
 | 
			
		||||
 | 
			
		||||
  static propTypes = {
 | 
			
		||||
    account: PropTypes.object.isRequired,
 | 
			
		||||
    onClose: PropTypes.func.isRequired,
 | 
			
		||||
    onBlockAndReport: PropTypes.func.isRequired,
 | 
			
		||||
    onConfirm: PropTypes.func.isRequired,
 | 
			
		||||
    intl: PropTypes.object.isRequired,
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  componentDidMount() {
 | 
			
		||||
    this.button.focus();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleClick = () => {
 | 
			
		||||
    this.props.onClose();
 | 
			
		||||
    this.props.onConfirm(this.props.account);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleSecondary = () => {
 | 
			
		||||
    this.props.onClose();
 | 
			
		||||
    this.props.onBlockAndReport(this.props.account);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  handleCancel = () => {
 | 
			
		||||
    this.props.onClose();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setRef = (c) => {
 | 
			
		||||
    this.button = c;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  render () {
 | 
			
		||||
    const { account } = this.props;
 | 
			
		||||
 | 
			
		||||
    return (
 | 
			
		||||
      <div className='modal-root__modal block-modal'>
 | 
			
		||||
        <div className='block-modal__container'>
 | 
			
		||||
          <p>
 | 
			
		||||
            <FormattedMessage
 | 
			
		||||
              id='confirmations.block.message'
 | 
			
		||||
              defaultMessage='Are you sure you want to block {name}?'
 | 
			
		||||
              values={{ name: <strong>@{account.get('acct')}</strong> }}
 | 
			
		||||
            />
 | 
			
		||||
          </p>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div className='block-modal__action-bar'>
 | 
			
		||||
          <Button onClick={this.handleCancel} className='block-modal__cancel-button'>
 | 
			
		||||
            <FormattedMessage id='confirmation_modal.cancel' defaultMessage='Cancel' />
 | 
			
		||||
          </Button>
 | 
			
		||||
          <Button onClick={this.handleSecondary} className='confirmation-modal__secondary-button'>
 | 
			
		||||
            <FormattedMessage id='confirmations.block.block_and_report' defaultMessage='Block & Report' />
 | 
			
		||||
          </Button>
 | 
			
		||||
          <Button onClick={this.handleClick} ref={this.setRef}>
 | 
			
		||||
            <FormattedMessage id='confirmations.block.confirm' defaultMessage='Block' />
 | 
			
		||||
          </Button>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ import ConfirmationModal from './confirmation_modal';
 | 
			
		|||
import FocalPointModal from './focal_point_modal';
 | 
			
		||||
import {
 | 
			
		||||
  MuteModal,
 | 
			
		||||
  BlockModal,
 | 
			
		||||
  ReportModal,
 | 
			
		||||
  EmbedModal,
 | 
			
		||||
  ListEditor,
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +26,7 @@ const MODAL_COMPONENTS = {
 | 
			
		|||
  'BOOST': () => Promise.resolve({ default: BoostModal }),
 | 
			
		||||
  'CONFIRM': () => Promise.resolve({ default: ConfirmationModal }),
 | 
			
		||||
  'MUTE': MuteModal,
 | 
			
		||||
  'BLOCK': BlockModal,
 | 
			
		||||
  'REPORT': ReportModal,
 | 
			
		||||
  'ACTIONS': () => Promise.resolve({ default: ActionsModal }),
 | 
			
		||||
  'EMBED': EmbedModal,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,7 +11,6 @@ import { toggleHideNotifications } from '../../../actions/mutes';
 | 
			
		|||
 | 
			
		||||
const mapStateToProps = state => {
 | 
			
		||||
  return {
 | 
			
		||||
    isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
 | 
			
		||||
    account: state.getIn(['mutes', 'new', 'account']),
 | 
			
		||||
    notifications: state.getIn(['mutes', 'new', 'notifications']),
 | 
			
		||||
  };
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +37,6 @@ export default @connect(mapStateToProps, mapDispatchToProps)
 | 
			
		|||
class MuteModal extends React.PureComponent {
 | 
			
		||||
 | 
			
		||||
  static propTypes = {
 | 
			
		||||
    isSubmitting: PropTypes.bool.isRequired,
 | 
			
		||||
    account: PropTypes.object.isRequired,
 | 
			
		||||
    notifications: PropTypes.bool.isRequired,
 | 
			
		||||
    onClose: PropTypes.func.isRequired,
 | 
			
		||||
| 
						 | 
				
			
			@ -81,11 +79,16 @@ class MuteModal extends React.PureComponent {
 | 
			
		|||
              values={{ name: <strong>@{account.get('acct')}</strong> }}
 | 
			
		||||
            />
 | 
			
		||||
          </p>
 | 
			
		||||
          <div>
 | 
			
		||||
            <label htmlFor='mute-modal__hide-notifications-checkbox'>
 | 
			
		||||
          <p className='mute-modal__explanation'>
 | 
			
		||||
            <FormattedMessage
 | 
			
		||||
              id='confirmations.mute.explanation'
 | 
			
		||||
              defaultMessage='This will hide posts from them and posts mentioning them, but it will still allow them to see your posts follow you.'
 | 
			
		||||
            />
 | 
			
		||||
          </p>
 | 
			
		||||
          <div className='setting-toggle'>
 | 
			
		||||
            <Toggle id='mute-modal__hide-notifications-checkbox' checked={notifications} onChange={this.toggleNotifications} />
 | 
			
		||||
            <label className='setting-toggle__label' htmlFor='mute-modal__hide-notifications-checkbox'>
 | 
			
		||||
              <FormattedMessage id='mute_modal.hide_notifications' defaultMessage='Hide notifications from this user?' />
 | 
			
		||||
              {' '}
 | 
			
		||||
              <Toggle id='mute-modal__hide-notifications-checkbox' checked={notifications} onChange={this.toggleNotifications} />
 | 
			
		||||
            </label>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,6 +106,10 @@ export function MuteModal () {
 | 
			
		|||
  return import(/* webpackChunkName: "modals/mute_modal" */'../components/mute_modal');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function BlockModal () {
 | 
			
		||||
  return import(/* webpackChunkName: "modals/block_modal" */'../components/block_modal');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function ReportModal () {
 | 
			
		||||
  return import(/* webpackChunkName: "modals/report_modal" */'../components/report_modal');
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Reference in a new issue