0
0
Fork 0

Grouped Notifications UI (#30440)

Co-authored-by: Eugen Rochko <eugen@zeonfederated.com>
Co-authored-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
Renaud Chaput 2024-07-18 16:36:09 +02:00 committed by GitHub
parent 7d090b2ab6
commit f587ff643f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
65 changed files with 3329 additions and 131 deletions

View file

@ -53,6 +53,7 @@ class ColumnSettings extends PureComponent {
const filterAdvancedStr = <FormattedMessage id='notifications.column_settings.filter_bar.advanced' defaultMessage='Display all categories' />;
const unreadMarkersShowStr = <FormattedMessage id='notifications.column_settings.unread_notifications.highlight' defaultMessage='Highlight unread notifications' />;
const groupingShowStr = <FormattedMessage id='notifications.column_settings.beta.grouping' defaultMessage='Group notifications' />;
const alertStr = <FormattedMessage id='notifications.column_settings.alert' defaultMessage='Desktop notifications' />;
const showStr = <FormattedMessage id='notifications.column_settings.show' defaultMessage='Show in column' />;
const soundStr = <FormattedMessage id='notifications.column_settings.sound' defaultMessage='Play sound' />;
@ -104,6 +105,16 @@ class ColumnSettings extends PureComponent {
</div>
</section>
<section role='group' aria-labelledby='notifications-beta'>
<h3 id='notifications-beta'>
<FormattedMessage id='notifications.column_settings.beta.category' defaultMessage='Experimental features' />
</h3>
<div className='column-settings__row'>
<SettingToggle id='unread-notification-markers' prefix='notifications' settings={settings} settingPath={['groupingBeta']} onChange={onChange} label={groupingShowStr} />
</div>
</section>
<section role='group' aria-labelledby='notifications-unread-markers'>
<h3 id='notifications-unread-markers'>
<FormattedMessage id='notifications.column_settings.unread_notifications.category' defaultMessage='Unread notifications' />

View file

@ -35,7 +35,9 @@ export const FilteredNotificationsBanner: React.FC = () => {
className='filtered-notifications-banner'
to='/notifications/requests'
>
<Icon icon={InventoryIcon} id='filtered-notifications' />
<div className='notification-group__icon'>
<Icon icon={InventoryIcon} id='filtered-notifications' />
</div>
<div className='filtered-notifications-banner__text'>
<strong>

View file

@ -1,7 +1,10 @@
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import classNames from 'classnames';
import GavelIcon from '@/material-icons/400-24px/gavel.svg?react';
import { Icon } from 'mastodon/components/icon';
import type { AccountWarningAction } from 'mastodon/models/notification_group';
// This needs to be kept in sync with app/models/account_warning.rb
const messages = defineMessages({
@ -36,19 +39,18 @@ const messages = defineMessages({
});
interface Props {
action:
| 'none'
| 'disable'
| 'mark_statuses_as_sensitive'
| 'delete_statuses'
| 'sensitive'
| 'silence'
| 'suspend';
action: AccountWarningAction;
id: string;
hidden: boolean;
hidden?: boolean;
unread?: boolean;
}
export const ModerationWarning: React.FC<Props> = ({ action, id, hidden }) => {
export const ModerationWarning: React.FC<Props> = ({
action,
id,
hidden,
unread,
}) => {
const intl = useIntl();
if (hidden) {
@ -56,23 +58,32 @@ export const ModerationWarning: React.FC<Props> = ({ action, id, hidden }) => {
}
return (
<a
href={`/disputes/strikes/${id}`}
target='_blank'
rel='noopener noreferrer'
className='notification__moderation-warning'
<div
role='button'
className={classNames(
'notification-group notification-group--link notification-group--moderation-warning focusable',
{ 'notification-group--unread': unread },
)}
tabIndex={0}
>
<Icon id='warning' icon={GavelIcon} />
<div className='notification-group__icon'>
<Icon id='warning' icon={GavelIcon} />
</div>
<div className='notification__moderation-warning__content'>
<div className='notification-group__main'>
<p>{intl.formatMessage(messages[action])}</p>
<span className='link-button'>
<a
href={`/disputes/strikes/${id}`}
target='_blank'
rel='noopener noreferrer'
className='link-button'
>
<FormattedMessage
id='notification.moderation-warning.learn_more'
defaultMessage='Learn more'
/>
</span>
</a>
</div>
</a>
</div>
);
};

View file

@ -34,7 +34,7 @@ const messages = defineMessages({
favourite: { id: 'notification.favourite', defaultMessage: '{name} favorited your status' },
follow: { id: 'notification.follow', defaultMessage: '{name} followed you' },
ownPoll: { id: 'notification.own_poll', defaultMessage: 'Your poll has ended' },
poll: { id: 'notification.poll', defaultMessage: 'A poll you have voted in has ended' },
poll: { id: 'notification.poll', defaultMessage: 'A poll you voted in has ended' },
reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your status' },
status: { id: 'notification.status', defaultMessage: '{name} just posted' },
update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
@ -340,7 +340,7 @@ class Notification extends ImmutablePureComponent {
{ownPoll ? (
<FormattedMessage id='notification.own_poll' defaultMessage='Your poll has ended' />
) : (
<FormattedMessage id='notification.poll' defaultMessage='A poll you have voted in has ended' />
<FormattedMessage id='notification.poll' defaultMessage='A poll you voted in has ended' />
)}
</span>
</div>

View file

@ -2,6 +2,8 @@ import PropTypes from 'prop-types';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import classNames from 'classnames';
import HeartBrokenIcon from '@/material-icons/400-24px/heart_broken-fill.svg?react';
import { Icon } from 'mastodon/components/icon';
import { domain } from 'mastodon/initial_state';
@ -13,7 +15,7 @@ const messages = defineMessages({
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.' },
});
export const RelationshipsSeveranceEvent = ({ type, target, followingCount, followersCount, hidden }) => {
export const RelationshipsSeveranceEvent = ({ type, target, followingCount, followersCount, hidden, unread }) => {
const intl = useIntl();
if (hidden) {
@ -21,14 +23,14 @@ export const RelationshipsSeveranceEvent = ({ type, target, followingCount, foll
}
return (
<a href='/severed_relationships' target='_blank' rel='noopener noreferrer' className='notification__relationships-severance-event'>
<Icon id='heart_broken' icon={HeartBrokenIcon} />
<div role='button' className={classNames('notification-group notification-group--link notification-group--relationships-severance-event focusable', { 'notification-group--unread': unread })} tabIndex='0'>
<div className='notification-group__icon'><Icon id='heart_broken' icon={HeartBrokenIcon} /></div>
<div className='notification__relationships-severance-event__content'>
<div className='notification-group__main'>
<p>{intl.formatMessage(messages[type], { from: <strong>{domain}</strong>, target: <strong>{target}</strong>, followingCount, followersCount })}</p>
<span className='link-button'><FormattedMessage id='notification.relationships_severance_event.learn_more' defaultMessage='Learn more' /></span>
<a href='/severed_relationships' target='_blank' rel='noopener noreferrer' className='link-button'><FormattedMessage id='notification.relationships_severance_event.learn_more' defaultMessage='Learn more' /></a>
</div>
</a>
</div>
);
};
@ -42,4 +44,5 @@ RelationshipsSeveranceEvent.propTypes = {
followersCount: PropTypes.number.isRequired,
followingCount: PropTypes.number.isRequired,
hidden: PropTypes.bool,
unread: PropTypes.bool,
};