Merge branch 'just-messing-around' into 'develop'

Add headers to confirmation modals

See merge request soapbox-pub/soapbox-fe!942
strip-front-mentions
marcin mikołajczak 2022-01-06 17:09:08 +00:00
commit 831a3418f9
15 zmienionych plików z 108 dodań i 5 usunięć

Wyświetl plik

@ -8,18 +8,24 @@ import AccountContainer from 'soapbox/containers/account_container';
import { isLocal } from 'soapbox/utils/accounts';
const messages = defineMessages({
deactivateUserHeading: { id: 'confirmations.admin.deactivate_user.heading', defaultMessage: 'Deactivate @{acct}' },
deactivateUserPrompt: { id: 'confirmations.admin.deactivate_user.message', defaultMessage: 'You are about to deactivate @{acct}. Deactivating a user is a reversible action.' },
deactivateUserConfirm: { id: 'confirmations.admin.deactivate_user.confirm', defaultMessage: 'Deactivate @{name}' },
userDeactivated: { id: 'admin.users.user_deactivated_message', defaultMessage: '@{acct} was deactivated' },
deleteUserHeading: { id: 'confirmations.admin.delete_user.heading', defaultMessage: 'Delete @{acct}' },
deleteUserPrompt: { id: 'confirmations.admin.delete_user.message', defaultMessage: 'You are about to delete @{acct}. THIS IS A DESTRUCTIVE ACTION THAT CANNOT BE UNDONE.' },
deleteUserConfirm: { id: 'confirmations.admin.delete_user.confirm', defaultMessage: 'Delete @{name}' },
deleteLocalUserCheckbox: { id: 'confirmations.admin.delete_local_user.checkbox', defaultMessage: 'I understand that I am about to delete a local user.' },
userDeleted: { id: 'admin.users.user_deleted_message', defaultMessage: '@{acct} was deleted' },
deleteStatusHeading: { id: 'confirmations.admin.delete_status.heading', defaultMessage: 'Delete post' },
deleteStatusPrompt: { id: 'confirmations.admin.delete_status.message', defaultMessage: 'You are about to delete a post by @{acct}. This action cannot be undone.' },
deleteStatusConfirm: { id: 'confirmations.admin.delete_status.confirm', defaultMessage: 'Delete post' },
rejectUserHeading: { id: 'confirmations.admin.reject_user.heading', defaultMessage: 'Reject @{acct}' },
rejectUserPrompt: { id: 'confirmations.admin.reject_user.message', defaultMessage: 'You are about to reject @{acct} registration request. This action cannot be undone.' },
rejectUserConfirm: { id: 'confirmations.admin.reject_user.confirm', defaultMessage: 'Reject @{name}' },
statusDeleted: { id: 'admin.statuses.status_deleted_message', defaultMessage: 'Post by @{acct} was deleted' },
markStatusSensitiveHeading: { id: 'confirmations.admin.mark_status_sensitive.heading', defaultMessage: 'Mark post sensitive' },
markStatusNotSensitiveHeading: { id: 'confirmations.admin.mark_status_not_sensitive.heading', defaultMessage: 'Mark post not sensitive.' },
markStatusSensitivePrompt: { id: 'confirmations.admin.mark_status_sensitive.message', defaultMessage: 'You are about to mark a post by @{acct} sensitive.' },
markStatusNotSensitivePrompt: { id: 'confirmations.admin.mark_status_not_sensitive.message', defaultMessage: 'You are about to mark a post by @{acct} not sensitive.' },
markStatusSensitiveConfirm: { id: 'confirmations.admin.mark_status_sensitive.confirm', defaultMessage: 'Mark post sensitive' },
@ -35,6 +41,8 @@ export function deactivateUserModal(intl, accountId, afterConfirm = () => {}) {
const name = state.getIn(['accounts', accountId, 'username']);
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/user-off.svg'),
heading: intl.formatMessage(messages.deactivateUserHeading, { acct }),
message: intl.formatMessage(messages.deactivateUserPrompt, { acct }),
confirm: intl.formatMessage(messages.deactivateUserConfirm, { name }),
onConfirm: () => {
@ -72,6 +80,8 @@ export function deleteUserModal(intl, accountId, afterConfirm = () => {}) {
const checkbox = local ? intl.formatMessage(messages.deleteLocalUserCheckbox) : false;
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/user-minus.svg'),
heading: intl.formatMessage(messages.deleteUserHeading, { acct }),
message,
confirm,
checkbox,
@ -94,6 +104,8 @@ export function rejectUserModal(intl, accountId, afterConfirm = () => {}) {
const name = state.getIn(['accounts', accountId, 'username']);
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/user-off.svg'),
heading: intl.formatMessage(messages.rejectUserHeading, { acct }),
message: intl.formatMessage(messages.rejectUserPrompt, { acct }),
confirm: intl.formatMessage(messages.rejectUserConfirm, { name }),
onConfirm: () => {
@ -114,6 +126,8 @@ export function toggleStatusSensitivityModal(intl, statusId, sensitive, afterCon
const acct = state.getIn(['accounts', accountId, 'acct']);
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/alert-triangle.svg'),
heading: intl.formatMessage(sensitive === false ? messages.markStatusSensitiveHeading : messages.markStatusNotSensitiveHeading),
message: intl.formatMessage(sensitive === false ? messages.markStatusSensitivePrompt : messages.markStatusNotSensitivePrompt, { acct }),
confirm: intl.formatMessage(sensitive === false ? messages.markStatusSensitiveConfirm : messages.markStatusNotSensitiveConfirm),
onConfirm: () => {
@ -134,6 +148,8 @@ export function deleteStatusModal(intl, statusId, afterConfirm = () => {}) {
const acct = state.getIn(['accounts', accountId, 'acct']);
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/trash.svg'),
heading: intl.formatMessage(messages.deleteStatusHeading),
message: intl.formatMessage(messages.deleteStatusPrompt, { acct }),
confirm: intl.formatMessage(messages.deleteStatusConfirm),
onConfirm: () => {

Wyświetl plik

@ -63,6 +63,8 @@ class ModalRoot extends React.PureComponent {
if (hasComposeContent && type === 'COMPOSE') {
onOpenModal('CONFIRM', {
icon: require('@tabler/icons/icons/trash.svg'),
heading: <FormattedMessage id='confirmations.delete.heading' defaultMessage='Delete post' />,
message: <FormattedMessage id='confirmations.delete.message' defaultMessage='Are you sure you want to delete this post?' />,
confirm: intl.formatMessage(messages.confirm),
onConfirm: () => onCancelReplyCompose(),

Wyświetl plik

@ -37,6 +37,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
if (account.getIn(['relationship', 'following']) || account.getIn(['relationship', 'requested'])) {
if (unfollowModal) {
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/minus.svg'),
heading: <FormattedMessage id='confirmations.unfollow.heading' defaultMessage='Unfollow {name}' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
message: <FormattedMessage id='confirmations.unfollow.message' defaultMessage='Are you sure you want to unfollow {name}?' values={{ name: <strong>@{account.get('acct')}</strong> }} />,
confirm: intl.formatMessage(messages.unfollowConfirm),
onConfirm: () => dispatch(unfollowAccount(account.get('id'))),

Wyświetl plik

@ -18,6 +18,8 @@ const makeMapStateToProps = () => {
const mapDispatchToProps = (dispatch, { intl }) => ({
onBlockDomain(domain) {
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/ban.svg'),
heading: <FormattedMessage id='confirmations.domain_block.heading' defaultMessage='Block {domain}' values={{ domain }} />,
message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable.' values={{ domain: <strong>{domain}</strong> }} />,
confirm: intl.formatMessage(messages.blockDomainConfirm),
onConfirm: () => dispatch(blockDomain(domain)),

Wyświetl plik

@ -41,11 +41,13 @@ import { launchChat } from 'soapbox/actions/chats';
const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
deleteHeading: { id: 'confirmations.delete.heading', defaultMessage: 'Delete post' },
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this post?' },
redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this post and re-draft it? Favorites and reposts 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' },
redraftHeading: { id: 'confirmations.redraft.heading', defaultMessage: 'Delete & redraft' },
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' },
});
@ -142,6 +144,8 @@ const mapDispatchToProps = (dispatch, { intl }) => {
dispatch(deleteStatus(status.get('id'), history, withRedraft));
} else {
dispatch(openModal('CONFIRM', {
icon: withRedraft ? require('@tabler/icons/icons/edit.svg') : require('@tabler/icons/icons/trash.svg'),
heading: intl.formatMessage(withRedraft ? messages.redraftHeading : messages.deleteHeading),
message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)),
@ -177,6 +181,8 @@ const mapDispatchToProps = (dispatch, { intl }) => {
onBlock(status) {
const account = status.get('account');
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/ban.svg'),
heading: <FormattedMessage id='confirmations.block.heading' defaultMessage='Block @{name}' values={{ name: account.get('acct') }} />,
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'))),

Wyświetl plik

@ -90,6 +90,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(unblockAccount(account.get('id')));
} else {
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/ban.svg'),
heading: <FormattedMessage id='confirmations.block.heading' defaultMessage='Block @{name}' values={{ name: account.get('acct') }} />,
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'))),
@ -148,6 +150,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
onBlockDomain(domain) {
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/ban.svg'),
heading: <FormattedMessage id='confirmations.domain_block.heading' defaultMessage='Block {domain}' values={{ domain }} />,
message: <FormattedMessage id='confirmations.domain_block.message' defaultMessage='Are you really, really sure you want to block the entire {domain}? In most cases a few targeted blocks or mutes are sufficient and preferable. You will not see content from that domain in any public timelines or your notifications.' values={{ domain: <strong>{domain}</strong> }} />,
confirm: intl.formatMessage(messages.blockDomainConfirm),
onConfirm: () => dispatch(blockDomain(domain)),

Wyświetl plik

@ -34,6 +34,8 @@ const messages = defineMessages({
tos: { id: 'registration.tos', defaultMessage: 'Terms of Service' },
close: { id: 'registration.confirmation_modal.close', defaultMessage: 'Close' },
newsletter: { id: 'registration.newsletter', defaultMessage: 'Subscribe to newsletter.' },
needsConfirmationHeader: { id: 'confirmations.register.needs_confirmation.header', defaultMessage: 'Confirmation needed' },
needsApprovalHeader: { id: 'confirmations.register.needs_approval.header', defaultMessage: 'Approval needed' },
});
const mapStateToProps = (state, props) => ({
@ -144,6 +146,12 @@ class RegistrationForm extends ImmutablePureComponent {
</>);
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/check.svg'),
heading: needsConfirmation
? intl.formatMessage(messages.needsConfirmationHeader)
: needsApproval
? intl.formatMessage(messages.needsApprovalHeader)
: undefined,
message,
confirm: intl.formatMessage(messages.close),
}));

Wyświetl plik

@ -14,6 +14,7 @@ import LoadingIndicator from '../../components/loading_indicator';
import Button from 'soapbox/components/button';
const messages = defineMessages({
deleteHeading: { id: 'confirmations.delete_list.heading', defaultMessage: 'Delete list' },
deleteMessage: { id: 'confirmations.delete_list.message', defaultMessage: 'Are you sure you want to permanently delete this list?' },
deleteConfirm: { id: 'confirmations.delete_list.confirm', defaultMessage: 'Delete' },
});
@ -84,6 +85,8 @@ class ListTimeline extends React.PureComponent {
const { id } = this.props.params;
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/trash.svg'),
heading: intl.formatMessage(messages.deleteHeading),
message: intl.formatMessage(messages.deleteMessage),
confirm: intl.formatMessage(messages.deleteConfirm),
onConfirm: () => {

Wyświetl plik

@ -9,6 +9,7 @@ import { openModal } from '../../../actions/modal';
import { getFeatures } from 'soapbox/utils/features';
const messages = defineMessages({
clearHeading: { id: 'notifications.clear_heading', defaultMessage: 'Clear notifications' },
clearMessage: { id: 'notifications.clear_confirmation', defaultMessage: 'Are you sure you want to permanently clear all your notifications?' },
clearConfirm: { id: 'notifications.clear', defaultMessage: 'Clear notifications' },
});
@ -39,6 +40,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
onClear() {
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/eraser.svg'),
heading: intl.formatMessage(messages.clearHeading),
message: intl.formatMessage(messages.clearMessage),
confirm: intl.formatMessage(messages.clearConfirm),
onConfirm: () => dispatch(clearNotifications()),

Wyświetl plik

@ -36,8 +36,10 @@ import { launchChat } from 'soapbox/actions/chats';
const messages = defineMessages({
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
deleteHeading: { id: 'confirmations.delete.heading', defaultMessage: 'Delete post' },
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this post?' },
redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
redraftHeading: { id: 'confirmations.redraft.heading', defaultMessage: 'Delete & redraft' },
redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this post and re-draft it? Favorites and reposts 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' },
@ -130,6 +132,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
dispatch(deleteStatus(status.get('id'), history, withRedraft));
} else {
dispatch(openModal('CONFIRM', {
icon: withRedraft ? require('@tabler/icons/icons/edit.svg') : require('@tabler/icons/icons/trash.svg'),
heading: intl.formatMessage(withRedraft ? messages.redraftHeading : messages.deleteHeading),
message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)),
@ -161,6 +165,8 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
onBlock(status) {
const account = status.get('account');
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/ban.svg'),
heading: <FormattedMessage id='confirmations.block.heading' defaultMessage='Block @{name}' values={{ name: account.get('acct') }} />,
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'))),

Wyświetl plik

@ -58,8 +58,10 @@ const messages = defineMessages({
title: { id: 'status.title', defaultMessage: 'Post' },
titleDirect: { id: 'status.title_direct', defaultMessage: 'Direct message' },
deleteConfirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' },
deleteHeading: { id: 'confirmations.delete.heading', defaultMessage: 'Delete post' },
deleteMessage: { id: 'confirmations.delete.message', defaultMessage: 'Are you sure you want to delete this post?' },
redraftConfirm: { id: 'confirmations.redraft.confirm', defaultMessage: 'Delete & redraft' },
redraftHeading: { id: 'confirmations.redraft.heading', defaultMessage: 'Delete & redraft' },
redraftMessage: { id: 'confirmations.redraft.message', defaultMessage: 'Are you sure you want to delete this post and re-draft it? Favorites and reposts 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' },
@ -259,6 +261,8 @@ class Status extends ImmutablePureComponent {
dispatch(deleteStatus(status.get('id'), history, withRedraft));
} else {
dispatch(openModal('CONFIRM', {
icon: withRedraft ? require('@tabler/icons/icons/edit.svg') : require('@tabler/icons/icons/trash.svg'),
heading: intl.formatMessage(withRedraft ? messages.redraftHeading : messages.deleteHeading),
message: intl.formatMessage(withRedraft ? messages.redraftMessage : messages.deleteMessage),
confirm: intl.formatMessage(withRedraft ? messages.redraftConfirm : messages.deleteConfirm),
onConfirm: () => dispatch(deleteStatus(status.get('id'), history, withRedraft)),
@ -338,6 +342,8 @@ class Status extends ImmutablePureComponent {
const account = status.get('account');
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/ban.svg'),
heading: <FormattedMessage id='confirmations.block.heading' defaultMessage='Block @{name}' values={{ name: account.get('acct') }} />,
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'))),

Wyświetl plik

@ -41,6 +41,8 @@ class ComposeModal extends ImmutablePureComponent {
if (composeText) {
dispatch(openModal('CONFIRM', {
icon: require('@tabler/icons/icons/trash.svg'),
heading: <FormattedMessage id='confirmations.delete.heading' defaultMessage='Delete post' />,
message: <FormattedMessage id='confirmations.delete.message' defaultMessage='Are you sure you want to delete this post?' />,
confirm: intl.formatMessage(messages.confirm),
onConfirm: () => dispatch(cancelReplyCompose()),

Wyświetl plik

@ -3,11 +3,14 @@ import PropTypes from 'prop-types';
import { injectIntl, FormattedMessage } from 'react-intl';
import Button from '../../../components/button';
import { SimpleForm, FieldsGroup, Checkbox } from 'soapbox/features/forms';
import Icon from '../../../components/icon';
export default @injectIntl
class ConfirmationModal extends React.PureComponent {
static propTypes = {
heading: PropTypes.node,
icon: PropTypes.node,
message: PropTypes.node.isRequired,
confirm: PropTypes.node.isRequired,
onClose: PropTypes.func.isRequired,
@ -52,11 +55,18 @@ class ConfirmationModal extends React.PureComponent {
}
render() {
const { message, confirm, secondary, checkbox } = this.props;
const { heading, icon, message, confirm, secondary, checkbox } = this.props;
const { checked } = this.state;
return (
<div className='modal-root__modal confirmation-modal'>
{heading && (
<div className='confirmation-modal__header'>
{icon && <Icon src={icon} />}
{heading}
</div>
)}
<div className='confirmation-modal__container'>
{message}
</div>

Wyświetl plik

@ -3,10 +3,11 @@ import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import { injectIntl, FormattedMessage } from 'react-intl';
import Toggle from 'react-toggle';
import Button from '../../../components/button';
import { closeModal } from '../../../actions/modal';
import { muteAccount } from '../../../actions/accounts';
import { toggleHideNotifications } from '../../../actions/mutes';
import Button from 'soapbox/components/button';
import Icon from 'soapbox/components/icon';
import { closeModal } from 'soapbox/actions/modal';
import { muteAccount } from 'soapbox/actions/accounts';
import { toggleHideNotifications } from 'soapbox/actions/mutes';
const mapStateToProps = state => {
@ -73,6 +74,14 @@ class MuteModal extends React.PureComponent {
return (
<div className='modal-root__modal mute-modal'>
<div className='mute-modal__header'>
<Icon src={require('@tabler/icons/icons/circle-x.svg')} />
<FormattedMessage
id='confirmations.mute.heading'
defaultMessage='Mute @{name}'
values={{ name: account.get('acct') }}
/>
</div>
<div className='mute-modal__container'>
<p>
<FormattedMessage

Wyświetl plik

@ -1052,3 +1052,27 @@
margin-bottom: 0;
}
}
.confirmation-modal,
.mute-modal {
&__header {
display: flex;
align-items: center;
column-gap: 6px;
padding: 20px;
padding-bottom: 0;
font-size: 22px;
.svg-icon {
height: 24px;
width: 24px;
color: var(--primary-text-color);
opacity: 0.6;
}
}
&__container {
padding: 20px;
text-align: left;
}
}