[Glitch] Add in-app notifications for moderation actions/warnings

Port 4ef0b48b95 to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
Claire 2024-04-25 19:26:05 +02:00
parent 8dbcf8a287
commit aac59a34ed
4 changed files with 106 additions and 1 deletions

View file

@ -0,0 +1,78 @@
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import WarningIcon from '@/material-icons/400-24px/warning-fill.svg?react';
import { Icon } from 'flavours/glitch/components/icon';
// This needs to be kept in sync with app/models/account_warning.rb
const messages = defineMessages({
none: {
id: 'notification.moderation_warning.action_none',
defaultMessage: 'Your account has received a moderation warning.',
},
disable: {
id: 'notification.moderation_warning.action_disable',
defaultMessage: 'Your account has been disabled.',
},
mark_statuses_as_sensitive: {
id: 'notification.moderation_warning.action_mark_statuses_as_sensitive',
defaultMessage: 'Some of your posts have been marked as sensitive.',
},
delete_statuses: {
id: 'notification.moderation_warning.action_delete_statuses',
defaultMessage: 'Some of your posts have been removed.',
},
sensitive: {
id: 'notification.moderation_warning.action_sensitive',
defaultMessage: 'Your posts will be marked as sensitive from now on.',
},
silence: {
id: 'notification.moderation_warning.action_silence',
defaultMessage: 'Your account has been limited.',
},
suspend: {
id: 'notification.moderation_warning.action_suspend',
defaultMessage: 'Your account has been suspended.',
},
});
interface Props {
action:
| 'none'
| 'disable'
| 'mark_statuses_as_sensitive'
| 'delete_statuses'
| 'sensitive'
| 'silence'
| 'suspend';
id: string;
hidden: boolean;
}
export const ModerationWarning: React.FC<Props> = ({ action, id, hidden }) => {
const intl = useIntl();
if (hidden) {
return null;
}
return (
<a
href={`/disputes/strikes/${id}`}
target='_blank'
rel='noopener noreferrer'
className='notification__moderation-warning'
>
<Icon id='warning' icon={WarningIcon} />
<div className='notification__moderation-warning__content'>
<p>{intl.formatMessage(messages[action])}</p>
<span className='link-button'>
<FormattedMessage
id='notification.moderation-warning.learn_more'
defaultMessage='Learn more'
/>
</span>
</div>
</a>
);
};

View file

@ -22,6 +22,7 @@ import { WithRouterPropTypes } from 'flavours/glitch/utils/react_router';
import FollowRequestContainer from '../containers/follow_request_container'; import FollowRequestContainer from '../containers/follow_request_container';
import NotificationOverlayContainer from '../containers/overlay_container'; import NotificationOverlayContainer from '../containers/overlay_container';
import { ModerationWarning } from './moderation_warning';
import { RelationshipsSeveranceEvent } from './relationships_severance_event'; import { RelationshipsSeveranceEvent } from './relationships_severance_event';
import Report from './report'; import Report from './report';
@ -30,6 +31,7 @@ const messages = defineMessages({
adminSignUp: { id: 'notification.admin.sign_up', defaultMessage: '{name} signed up' }, adminSignUp: { id: 'notification.admin.sign_up', defaultMessage: '{name} signed up' },
adminReport: { id: 'notification.admin.report', defaultMessage: '{name} reported {target}' }, adminReport: { id: 'notification.admin.report', defaultMessage: '{name} reported {target}' },
relationshipsSevered: { id: 'notification.relationships_severance_event', defaultMessage: 'Lost connections with {name}' }, relationshipsSevered: { id: 'notification.relationships_severance_event', defaultMessage: 'Lost connections with {name}' },
moderationWarning: { id: 'notification.moderation_warning', defaultMessage: 'Your have received a moderation warning' },
}); });
const notificationForScreenReader = (intl, message, timestamp) => { const notificationForScreenReader = (intl, message, timestamp) => {
@ -328,6 +330,27 @@ class Notification extends ImmutablePureComponent {
); );
} }
renderModerationWarning (notification) {
const { intl, unread, hidden } = this.props;
const warning = notification.get('moderation_warning');
if (!warning) {
return null;
}
return (
<HotKeys handlers={this.getHandlers()}>
<div className={classNames('notification notification-moderation-warning focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.moderationWarning), notification.get('created_at'))}>
<ModerationWarning
action={warning.get('action')}
id={warning.get('id')}
hidden={hidden}
/>
</div>
</HotKeys>
);
}
renderAdminSignUp (notification, account, link) { renderAdminSignUp (notification, account, link) {
const { intl, unread } = this.props; const { intl, unread } = this.props;
@ -423,6 +446,8 @@ class Notification extends ImmutablePureComponent {
return this.renderPoll(notification); return this.renderPoll(notification);
case 'severed_relationships': case 'severed_relationships':
return this.renderRelationshipsSevered(notification); return this.renderRelationshipsSevered(notification);
case 'moderation_warning':
return this.renderModerationWarning(notification);
case 'admin.sign_up': case 'admin.sign_up':
return this.renderAdminSignUp(notification, account, link); return this.renderAdminSignUp(notification, account, link);
case 'admin.report': case 'admin.report':

View file

@ -62,6 +62,7 @@ export const notificationToMap = (notification, markForDelete = false) => Immuta
status: notification.status ? notification.status.id : null, status: notification.status ? notification.status.id : null,
report: notification.report ? fromJS(notification.report) : null, report: notification.report ? fromJS(notification.report) : null,
event: notification.event ? fromJS(notification.event) : null, event: notification.event ? fromJS(notification.event) : null,
moderation_warning: notification.moderation_warning ? fromJS(notification.moderation_warning) : null,
}); });
const normalizeNotification = (state, notification, usePendingItems) => { const normalizeNotification = (state, notification, usePendingItems) => {

View file

@ -2394,7 +2394,8 @@ a.account__display-name {
} }
} }
.notification__relationships-severance-event { .notification__relationships-severance-event,
.notification__moderation-warning {
display: flex; display: flex;
gap: 16px; gap: 16px;
color: $secondary-text-color; color: $secondary-text-color;