diff --git a/app/soapbox/actions/moderation.js b/app/soapbox/actions/moderation.js index 52652978b..cda6f3b23 100644 --- a/app/soapbox/actions/moderation.js +++ b/app/soapbox/actions/moderation.js @@ -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: () => { diff --git a/app/soapbox/components/modal_root.js b/app/soapbox/components/modal_root.js index a8e8fe746..d23ef9677 100644 --- a/app/soapbox/components/modal_root.js +++ b/app/soapbox/components/modal_root.js @@ -63,6 +63,8 @@ class ModalRoot extends React.PureComponent { if (hasComposeContent && type === 'COMPOSE') { onOpenModal('CONFIRM', { + icon: require('@tabler/icons/icons/trash.svg'), + heading: , message: , confirm: intl.formatMessage(messages.confirm), onConfirm: () => onCancelReplyCompose(), diff --git a/app/soapbox/containers/account_container.js b/app/soapbox/containers/account_container.js index 1e890a7e2..06fced242 100644 --- a/app/soapbox/containers/account_container.js +++ b/app/soapbox/containers/account_container.js @@ -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: @{account.get('acct')} }} />, message: @{account.get('acct')} }} />, confirm: intl.formatMessage(messages.unfollowConfirm), onConfirm: () => dispatch(unfollowAccount(account.get('id'))), diff --git a/app/soapbox/containers/domain_container.js b/app/soapbox/containers/domain_container.js index 7a472c17c..a9887b546 100644 --- a/app/soapbox/containers/domain_container.js +++ b/app/soapbox/containers/domain_container.js @@ -18,6 +18,8 @@ const makeMapStateToProps = () => { const mapDispatchToProps = (dispatch, { intl }) => ({ onBlockDomain(domain) { dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/ban.svg'), + heading: , message: {domain} }} />, confirm: intl.formatMessage(messages.blockDomainConfirm), onConfirm: () => dispatch(blockDomain(domain)), diff --git a/app/soapbox/containers/status_container.js b/app/soapbox/containers/status_container.js index d81734485..0b812e033 100644 --- a/app/soapbox/containers/status_container.js +++ b/app/soapbox/containers/status_container.js @@ -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: , message: @{account.get('acct')} }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), diff --git a/app/soapbox/features/account_timeline/containers/header_container.js b/app/soapbox/features/account_timeline/containers/header_container.js index 7513232cd..8694420f6 100644 --- a/app/soapbox/features/account_timeline/containers/header_container.js +++ b/app/soapbox/features/account_timeline/containers/header_container.js @@ -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: , message: @{account.get('acct')} }} />, 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: , message: {domain} }} />, confirm: intl.formatMessage(messages.blockDomainConfirm), onConfirm: () => dispatch(blockDomain(domain)), diff --git a/app/soapbox/features/auth_login/components/registration_form.js b/app/soapbox/features/auth_login/components/registration_form.js index 99baa6cde..0f11a3a9e 100644 --- a/app/soapbox/features/auth_login/components/registration_form.js +++ b/app/soapbox/features/auth_login/components/registration_form.js @@ -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), })); diff --git a/app/soapbox/features/list_timeline/index.js b/app/soapbox/features/list_timeline/index.js index e45bcbcd6..b1fa3c16b 100644 --- a/app/soapbox/features/list_timeline/index.js +++ b/app/soapbox/features/list_timeline/index.js @@ -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: () => { diff --git a/app/soapbox/features/notifications/containers/column_settings_container.js b/app/soapbox/features/notifications/containers/column_settings_container.js index b108d8b99..7d44486c2 100644 --- a/app/soapbox/features/notifications/containers/column_settings_container.js +++ b/app/soapbox/features/notifications/containers/column_settings_container.js @@ -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()), diff --git a/app/soapbox/features/status/containers/detailed_status_container.js b/app/soapbox/features/status/containers/detailed_status_container.js index cf4555cd1..3e01fdb81 100644 --- a/app/soapbox/features/status/containers/detailed_status_container.js +++ b/app/soapbox/features/status/containers/detailed_status_container.js @@ -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: , message: @{account.get('acct')} }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), diff --git a/app/soapbox/features/status/index.js b/app/soapbox/features/status/index.js index 3fdf66d72..a74a2ee7e 100644 --- a/app/soapbox/features/status/index.js +++ b/app/soapbox/features/status/index.js @@ -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: , message: @{account.get('acct')} }} />, confirm: intl.formatMessage(messages.blockConfirm), onConfirm: () => dispatch(blockAccount(account.get('id'))), diff --git a/app/soapbox/features/ui/components/compose_modal.js b/app/soapbox/features/ui/components/compose_modal.js index 658398626..ad119a628 100644 --- a/app/soapbox/features/ui/components/compose_modal.js +++ b/app/soapbox/features/ui/components/compose_modal.js @@ -41,6 +41,8 @@ class ComposeModal extends ImmutablePureComponent { if (composeText) { dispatch(openModal('CONFIRM', { + icon: require('@tabler/icons/icons/trash.svg'), + heading: , message: , confirm: intl.formatMessage(messages.confirm), onConfirm: () => dispatch(cancelReplyCompose()), diff --git a/app/soapbox/features/ui/components/confirmation_modal.js b/app/soapbox/features/ui/components/confirmation_modal.js index 4c7a91145..3df0939e9 100644 --- a/app/soapbox/features/ui/components/confirmation_modal.js +++ b/app/soapbox/features/ui/components/confirmation_modal.js @@ -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 (
+ {heading && ( +
+ {icon && } + {heading} +
+ )} +
{message}
diff --git a/app/soapbox/features/ui/components/mute_modal.js b/app/soapbox/features/ui/components/mute_modal.js index d998ac627..b6fca0418 100644 --- a/app/soapbox/features/ui/components/mute_modal.js +++ b/app/soapbox/features/ui/components/mute_modal.js @@ -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 (
+
+ + +