Change design of notification about lost connections in web UI (#29731)
parent
dd061291b1
commit
29f9dc742e
|
@ -12,7 +12,6 @@ import { HotKeys } from 'react-hotkeys';
|
||||||
|
|
||||||
import EditIcon from '@/material-icons/400-24px/edit.svg?react';
|
import EditIcon from '@/material-icons/400-24px/edit.svg?react';
|
||||||
import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react';
|
import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react';
|
||||||
import HeartBrokenIcon from '@/material-icons/400-24px/heart_broken-fill.svg?react';
|
|
||||||
import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react';
|
import HomeIcon from '@/material-icons/400-24px/home-fill.svg?react';
|
||||||
import InsertChartIcon from '@/material-icons/400-24px/insert_chart.svg?react';
|
import InsertChartIcon from '@/material-icons/400-24px/insert_chart.svg?react';
|
||||||
import PersonIcon from '@/material-icons/400-24px/person-fill.svg?react';
|
import PersonIcon from '@/material-icons/400-24px/person-fill.svg?react';
|
||||||
|
@ -27,7 +26,7 @@ import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
||||||
|
|
||||||
import FollowRequestContainer from '../containers/follow_request_container';
|
import FollowRequestContainer from '../containers/follow_request_container';
|
||||||
|
|
||||||
import RelationshipsSeveranceEvent from './relationships_severance_event';
|
import { RelationshipsSeveranceEvent } from './relationships_severance_event';
|
||||||
import Report from './report';
|
import Report from './report';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
|
@ -40,6 +39,7 @@ const messages = defineMessages({
|
||||||
update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
|
update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
|
||||||
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}' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const notificationForScreenReader = (intl, message, timestamp) => {
|
const notificationForScreenReader = (intl, message, timestamp) => {
|
||||||
|
@ -361,24 +361,23 @@ class Notification extends ImmutablePureComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
renderRelationshipsSevered (notification) {
|
renderRelationshipsSevered (notification) {
|
||||||
const { intl, unread } = this.props;
|
const { intl, unread, hidden } = this.props;
|
||||||
|
const event = notification.get('event');
|
||||||
|
|
||||||
if (!notification.get('event')) {
|
if (!event) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HotKeys handlers={this.getHandlers()}>
|
<HotKeys handlers={this.getHandlers()}>
|
||||||
<div className={classNames('notification notification-severed-relationships focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.adminReport, { name: notification.getIn(['event', 'target_name']) }), notification.get('created_at'))}>
|
<div className={classNames('notification notification-severed-relationships focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.relationshipsSevered, { name: notification.getIn(['event', 'target_name']) }), notification.get('created_at'))}>
|
||||||
<div className='notification__message'>
|
<RelationshipsSeveranceEvent
|
||||||
<Icon id='heart_broken' icon={HeartBrokenIcon} />
|
type={event.get('type')}
|
||||||
|
target={event.get('target_name')}
|
||||||
<span title={notification.get('created_at')}>
|
followersCount={event.get('followers_count')}
|
||||||
<FormattedMessage id='notification.severed_relationships' defaultMessage='Relationships with {name} severed' values={{ name: notification.getIn(['event', 'target_name']) }} />
|
followingCount={event.get('following_count')}
|
||||||
</span>
|
hidden={hidden}
|
||||||
</div>
|
/>
|
||||||
|
|
||||||
<RelationshipsSeveranceEvent event={notification.get('event')} />
|
|
||||||
</div>
|
</div>
|
||||||
</HotKeys>
|
</HotKeys>
|
||||||
);
|
);
|
||||||
|
|
|
@ -2,60 +2,44 @@ import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||||
|
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import HeartBrokenIcon from '@/material-icons/400-24px/heart_broken-fill.svg?react';
|
||||||
|
import { Icon } from 'mastodon/components/icon';
|
||||||
|
import { domain } from 'mastodon/initial_state';
|
||||||
|
|
||||||
import { RelativeTimestamp } from 'mastodon/components/relative_timestamp';
|
// This needs to be kept in sync with app/models/relationships_severance_event.rb
|
||||||
|
|
||||||
// This needs to be kept in sync with app/models/relationship_severance_event.rb
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
account_suspension: { id: 'relationship_severance_notification.types.account_suspension', defaultMessage: 'Account has been suspended' },
|
account_suspension: { id: 'notification.relationships_severance_event.account_suspension', defaultMessage: 'An admin from {from} has suspended {target}, which means you can no longer receive updates from them or interact with them.' },
|
||||||
domain_block: { id: 'relationship_severance_notification.types.domain_block', defaultMessage: 'Domain has been suspended' },
|
domain_block: { id: 'notification.relationships_severance_event.domain_block', defaultMessage: 'An admin from {from} has blocked {target}, including {followersCount} of your followers and {followingCount, plural, one {# account} other {# accounts}} you follow.' },
|
||||||
user_domain_block: { id: 'relationship_severance_notification.types.user_domain_block', defaultMessage: 'You blocked this domain' },
|
user_domain_block: { id: 'notification.relationships_severance_event.user_domain_block', defaultMessage: 'You have blocked {target}, removing {followersCount} of your followers and {followingCount, plural, one {# account} other {# accounts}} you follow.' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const RelationshipsSeveranceEvent = ({ event, hidden }) => {
|
export const RelationshipsSeveranceEvent = ({ type, target, followingCount, followersCount, hidden }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
if (hidden || !event) {
|
if (hidden) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='notification__report'>
|
<a href='/severed_relationships' target='_blank' rel='noopener noreferrer' className='notification__relationships-severance-event'>
|
||||||
<div className='notification__report__details'>
|
<Icon id='heart_broken' icon={HeartBrokenIcon} />
|
||||||
<div>
|
|
||||||
<RelativeTimestamp timestamp={event.get('created_at')} short={false} />
|
|
||||||
{' · '}
|
|
||||||
{ event.get('purged') ? (
|
|
||||||
<FormattedMessage
|
|
||||||
id='relationship_severance_notification.purged_data'
|
|
||||||
defaultMessage='purged by administrators'
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<FormattedMessage
|
|
||||||
id='relationship_severance_notification.relationships'
|
|
||||||
defaultMessage='{count, plural, one {# relationship} other {# relationships}}'
|
|
||||||
values={{ count: event.get('followers_count', 0) + event.get('following_count', 0) }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<br />
|
|
||||||
<strong>{intl.formatMessage(messages[event.get('type')])}</strong>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className='notification__report__actions'>
|
<div className='notification__relationships-severance-event__content'>
|
||||||
<a href='/severed_relationships' className='button' target='_blank' rel='noopener noreferrer'>
|
<p>{intl.formatMessage(messages[type], { from: <strong>{domain}</strong>, target: <strong>{target}</strong>, followingCount, followersCount })}</p>
|
||||||
<FormattedMessage id='relationship_severance_notification.view' defaultMessage='View' />
|
<span className='link-button'><FormattedMessage id='notification.relationships_severance_event.learn_more' defaultMessage='Learn more' /></span>
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</a>
|
||||||
);
|
);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RelationshipsSeveranceEvent.propTypes = {
|
RelationshipsSeveranceEvent.propTypes = {
|
||||||
event: ImmutablePropTypes.map.isRequired,
|
type: PropTypes.oneOf([
|
||||||
|
'account_suspension',
|
||||||
|
'domain_block',
|
||||||
|
'user_domain_block',
|
||||||
|
]).isRequired,
|
||||||
|
target: PropTypes.string.isRequired,
|
||||||
|
followersCount: PropTypes.number.isRequired,
|
||||||
|
followingCount: PropTypes.number.isRequired,
|
||||||
hidden: PropTypes.bool,
|
hidden: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RelationshipsSeveranceEvent;
|
|
||||||
|
|
|
@ -471,7 +471,11 @@
|
||||||
"notification.own_poll": "Your poll has ended",
|
"notification.own_poll": "Your poll has ended",
|
||||||
"notification.poll": "A poll you have voted in has ended",
|
"notification.poll": "A poll you have voted in has ended",
|
||||||
"notification.reblog": "{name} boosted your post",
|
"notification.reblog": "{name} boosted your post",
|
||||||
"notification.severed_relationships": "Relationships with {name} severed",
|
"notification.relationships_severance_event": "Lost connections with {name}",
|
||||||
|
"notification.relationships_severance_event.account_suspension": "An admin from {from} has suspended {target}, which means you can no longer receive updates from them or interact with them.",
|
||||||
|
"notification.relationships_severance_event.domain_block": "An admin from {from} has blocked {target}, including {followersCount} of your followers and {followingCount, plural, one {# account} other {# accounts}} you follow.",
|
||||||
|
"notification.relationships_severance_event.learn_more": "Learn more",
|
||||||
|
"notification.relationships_severance_event.user_domain_block": "You have blocked {target}, removing {followersCount} of your followers and {followingCount, plural, one {# account} other {# accounts}} you follow.",
|
||||||
"notification.status": "{name} just posted",
|
"notification.status": "{name} just posted",
|
||||||
"notification.update": "{name} edited a post",
|
"notification.update": "{name} edited a post",
|
||||||
"notification_requests.accept": "Accept",
|
"notification_requests.accept": "Accept",
|
||||||
|
@ -590,12 +594,6 @@
|
||||||
"refresh": "Refresh",
|
"refresh": "Refresh",
|
||||||
"regeneration_indicator.label": "Loading…",
|
"regeneration_indicator.label": "Loading…",
|
||||||
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
|
"regeneration_indicator.sublabel": "Your home feed is being prepared!",
|
||||||
"relationship_severance_notification.purged_data": "purged by administrators",
|
|
||||||
"relationship_severance_notification.relationships": "{count, plural, one {# relationship} other {# relationships}}",
|
|
||||||
"relationship_severance_notification.types.account_suspension": "Account has been suspended",
|
|
||||||
"relationship_severance_notification.types.domain_block": "Domain has been suspended",
|
|
||||||
"relationship_severance_notification.types.user_domain_block": "You blocked this domain",
|
|
||||||
"relationship_severance_notification.view": "View",
|
|
||||||
"relative_time.days": "{number}d",
|
"relative_time.days": "{number}d",
|
||||||
"relative_time.full.days": "{number, plural, one {# day} other {# days}} ago",
|
"relative_time.full.days": "{number, plural, one {# day} other {# days}} ago",
|
||||||
"relative_time.full.hours": "{number, plural, one {# hour} other {# hours}} ago",
|
"relative_time.full.hours": "{number, plural, one {# hour} other {# hours}} ago",
|
||||||
|
|
|
@ -2165,6 +2165,44 @@ a.account__display-name {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.notification__relationships-severance-event {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
color: $secondary-text-color;
|
||||||
|
text-decoration: none;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 16px 32px;
|
||||||
|
border-bottom: 1px solid var(--background-border-color);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
padding: 2px;
|
||||||
|
color: $highlight-text-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 8px;
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 24px;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-button {
|
||||||
|
font-size: inherit;
|
||||||
|
line-height: inherit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.notification__message {
|
.notification__message {
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
|
|
Loading…
Reference in New Issue