Merge remote-tracking branch 'parent/main' into upstream-20240326
This commit is contained in:
commit
6c9b221cb2
263 changed files with 4628 additions and 1518 deletions
|
@ -60,6 +60,7 @@ export default class ColumnSettings extends PureComponent {
|
|||
render () {
|
||||
const { settings, pushSettings, onChange, onClear, alertsEnabled, browserSupport, browserPermission, onRequestNotificationPermission, notificationPolicy } = this.props;
|
||||
|
||||
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 alertStr = <FormattedMessage id='notifications.column_settings.alert' defaultMessage='Desktop notifications' />;
|
||||
const showStr = <FormattedMessage id='notifications.column_settings.show' defaultMessage='Show in column' />;
|
||||
|
@ -74,16 +75,18 @@ export default class ColumnSettings extends PureComponent {
|
|||
<span className='warning-hint'><FormattedMessage id='notifications.permission_denied' defaultMessage='Desktop notifications are unavailable due to previously denied browser permissions request' /></span>
|
||||
)}
|
||||
|
||||
{alertsEnabled && browserSupport && browserPermission === 'default' && (
|
||||
<span className='warning-hint'>
|
||||
<FormattedMessage id='notifications.permission_required' defaultMessage='Desktop notifications are unavailable because the required permission has not been granted.' /> <GrantPermissionButton onClick={onRequestNotificationPermission} />
|
||||
</span>
|
||||
)}
|
||||
|
||||
<section>
|
||||
<ClearColumnButton onClick={onClear} />
|
||||
</section>
|
||||
|
||||
{alertsEnabled && browserSupport && browserPermission === 'default' && (
|
||||
<section>
|
||||
<span className='warning-hint'>
|
||||
<FormattedMessage id='notifications.permission_required' defaultMessage='Desktop notifications are unavailable because the required permission has not been granted.' /> <GrantPermissionButton onClick={onRequestNotificationPermission} />
|
||||
</span>
|
||||
</section>
|
||||
)}
|
||||
|
||||
<section>
|
||||
<h3><FormattedMessage id='notifications.policy.title' defaultMessage='Filter out notifications from…' /></h3>
|
||||
|
||||
|
@ -120,6 +123,16 @@ export default class ColumnSettings extends PureComponent {
|
|||
</div>
|
||||
</section>
|
||||
|
||||
<section role='group' aria-labelledby='notifications-filter-bar'>
|
||||
<h3 id='notifications-filter-bar'>
|
||||
<FormattedMessage id='notifications.column_settings.filter_bar.category' defaultMessage='Quick filter bar' />
|
||||
</h3>
|
||||
|
||||
<div className='column-settings__row'>
|
||||
<SettingToggle id='advanced-filter-bar' prefix='notifications' settings={settings} settingPath={['quickFilter', 'advanced']} onChange={onChange} label={filterAdvancedStr} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section role='group' aria-labelledby='notifications-follow'>
|
||||
<h3 id='notifications-follow'><FormattedMessage id='notifications.column_settings.follow' defaultMessage='New followers:' /></h3>
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@ import { Link } from 'react-router-dom';
|
|||
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
|
||||
|
||||
import ArchiveIcon from '@/material-icons/400-24px/archive.svg?react';
|
||||
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
|
||||
import { fetchNotificationPolicy } from 'mastodon/actions/notifications';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { toCappedNumber } from 'mastodon/utils/numbers';
|
||||
|
@ -34,7 +33,7 @@ export const FilteredNotificationsBanner = () => {
|
|||
|
||||
return (
|
||||
<Link className='filtered-notifications-banner' to='/notifications/requests'>
|
||||
<Icon icon={ArchiveIcon} />
|
||||
<Icon icon={InventoryIcon} />
|
||||
|
||||
<div className='filtered-notifications-banner__text'>
|
||||
<strong><FormattedMessage id='filtered_notifications_banner.title' defaultMessage='Filtered notifications' /></strong>
|
||||
|
@ -42,7 +41,8 @@ export const FilteredNotificationsBanner = () => {
|
|||
</div>
|
||||
|
||||
<div className='filtered-notifications-banner__badge'>
|
||||
{toCappedNumber(policy.getIn(['summary', 'pending_notifications_count']))}
|
||||
<div className='filtered-notifications-banner__badge__badge'>{toCappedNumber(policy.getIn(['summary', 'pending_notifications_count']))}</div>
|
||||
<FormattedMessage id='filtered_notifications_banner.private_mentions' defaultMessage='{count, plural, one {private mention} other {private mentions}}' values={{ count: policy.getIn(['summary', 'pending_notifications_count']) }} />
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
|
|
|
@ -29,6 +29,7 @@ import { WithRouterPropTypes } from 'mastodon/utils/react_router';
|
|||
|
||||
import FollowRequestContainer from '../containers/follow_request_container';
|
||||
|
||||
import { RelationshipsSeveranceEvent } from './relationships_severance_event';
|
||||
import Report from './report';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
@ -45,6 +46,7 @@ const messages = defineMessages({
|
|||
warning: { id: 'notification.warning', defaultMessage: 'You have been warned and "{action}" has been executed. Check your mailbox' },
|
||||
adminSignUp: { id: 'notification.admin.sign_up', defaultMessage: '{name} signed up' },
|
||||
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) => {
|
||||
|
@ -495,6 +497,29 @@ class Notification extends ImmutablePureComponent {
|
|||
</HotKeys>
|
||||
);
|
||||
}
|
||||
|
||||
renderRelationshipsSevered (notification) {
|
||||
const { intl, unread, hidden } = this.props;
|
||||
const event = notification.get('event');
|
||||
|
||||
if (!event) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<HotKeys handlers={this.getHandlers()}>
|
||||
<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'))}>
|
||||
<RelationshipsSeveranceEvent
|
||||
type={event.get('type')}
|
||||
target={event.get('target_name')}
|
||||
followersCount={event.get('followers_count')}
|
||||
followingCount={event.get('following_count')}
|
||||
hidden={hidden}
|
||||
/>
|
||||
</div>
|
||||
</HotKeys>
|
||||
);
|
||||
}
|
||||
|
||||
renderAdminSignUp (notification, account, link) {
|
||||
const { intl, unread } = this.props;
|
||||
|
@ -577,6 +602,8 @@ class Notification extends ImmutablePureComponent {
|
|||
return this.renderPoll(notification, account);
|
||||
case 'warning':
|
||||
return this.renderWarning(notification);
|
||||
case 'severed_relationships':
|
||||
return this.renderRelationshipsSevered(notification);
|
||||
case 'admin.sign_up':
|
||||
return this.renderAdminSignUp(notification, account, link);
|
||||
case 'admin.report':
|
||||
|
|
|
@ -7,8 +7,8 @@ import { Link } from 'react-router-dom';
|
|||
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
|
||||
import DeleteIcon from '@/material-icons/400-24px/delete.svg?react';
|
||||
import DoneIcon from '@/material-icons/400-24px/done.svg?react';
|
||||
import VolumeOffIcon from '@/material-icons/400-24px/volume_off.svg?react';
|
||||
import { acceptNotificationRequest, dismissNotificationRequest } from 'mastodon/actions/notifications';
|
||||
import { Avatar } from 'mastodon/components/avatar';
|
||||
import { IconButton } from 'mastodon/components/icon_button';
|
||||
|
@ -51,7 +51,7 @@ export const NotificationRequest = ({ id, accountId, notificationsCount }) => {
|
|||
</Link>
|
||||
|
||||
<div className='notification-request__actions'>
|
||||
<IconButton iconComponent={VolumeOffIcon} onClick={handleDismiss} title={intl.formatMessage(messages.dismiss)} />
|
||||
<IconButton iconComponent={DeleteIcon} onClick={handleDismiss} title={intl.formatMessage(messages.dismiss)} />
|
||||
<IconButton iconComponent={DoneIcon} onClick={handleAccept} title={intl.formatMessage(messages.accept)} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,8 +5,8 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
|||
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
import SettingsIcon from '@/material-icons/400-20px/settings.svg?react';
|
||||
import CloseIcon from '@/material-icons/400-24px/close.svg?react';
|
||||
import TuneIcon from '@/material-icons/400-24px/tune.svg?react';
|
||||
import { requestBrowserPermission } from 'mastodon/actions/notifications';
|
||||
import { changeSetting } from 'mastodon/actions/settings';
|
||||
import { Button } from 'mastodon/components/button';
|
||||
|
@ -42,7 +42,7 @@ class NotificationsPermissionBanner extends PureComponent {
|
|||
</div>
|
||||
|
||||
<h2><FormattedMessage id='notifications_permission_banner.title' defaultMessage='Never miss a thing' /></h2>
|
||||
<p><FormattedMessage id='notifications_permission_banner.how_to_control' defaultMessage="To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled." values={{ icon: <Icon id='sliders' icon={TuneIcon} /> }} /></p>
|
||||
<p><FormattedMessage id='notifications_permission_banner.how_to_control' defaultMessage="To receive notifications when Mastodon isn't open, enable desktop notifications. You can control precisely which types of interactions generate desktop notifications through the {icon} button above once they're enabled." values={{ icon: <Icon id='sliders' icon={SettingsIcon} /> }} /></p>
|
||||
<Button onClick={this.handleClick}><FormattedMessage id='notifications_permission_banner.enable' defaultMessage='Enable desktop notifications' /></Button>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
import PropTypes from 'prop-types';
|
||||
|
||||
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
||||
|
||||
import HeartBrokenIcon from '@/material-icons/400-24px/heart_broken-fill.svg?react';
|
||||
import { Icon } from 'mastodon/components/icon';
|
||||
import { domain } from 'mastodon/initial_state';
|
||||
|
||||
// This needs to be kept in sync with app/models/relationships_severance_event.rb
|
||||
const messages = defineMessages({
|
||||
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: '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: '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 }) => {
|
||||
const intl = useIntl();
|
||||
|
||||
if (hidden) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<a href='/severed_relationships' target='_blank' rel='noopener noreferrer' className='notification__relationships-severance-event'>
|
||||
<Icon id='heart_broken' icon={HeartBrokenIcon} />
|
||||
|
||||
<div className='notification__relationships-severance-event__content'>
|
||||
<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>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
RelationshipsSeveranceEvent.propTypes = {
|
||||
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,
|
||||
};
|
|
@ -5,7 +5,7 @@ import FilterBar from '../components/filter_bar';
|
|||
|
||||
const makeMapStateToProps = state => ({
|
||||
selectedFilter: state.getIn(['settings', 'notifications', 'quickFilter', 'active']),
|
||||
advancedMode: false,
|
||||
advancedMode: state.getIn(['settings', 'notifications', 'quickFilter', 'advanced']),
|
||||
});
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
|
|
@ -7,8 +7,8 @@ import { Helmet } from 'react-helmet';
|
|||
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
|
||||
import ArchiveIcon from '@/material-icons/400-24px/archive.svg?react';
|
||||
import DoneIcon from '@/material-icons/400-24px/done.svg?react';
|
||||
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
|
||||
import VolumeOffIcon from '@/material-icons/400-24px/volume_off.svg?react';
|
||||
import { fetchNotificationRequest, fetchNotificationsForRequest, expandNotificationsForRequest, acceptNotificationRequest, dismissNotificationRequest } from 'mastodon/actions/notifications';
|
||||
import Column from 'mastodon/components/column';
|
||||
|
@ -94,7 +94,7 @@ export const NotificationRequest = ({ multiColumn, params: { id } }) => {
|
|||
<Column bindToDocument={!multiColumn} ref={columnRef} label={columnTitle}>
|
||||
<ColumnHeader
|
||||
icon='archive'
|
||||
iconComponent={ArchiveIcon}
|
||||
iconComponent={InventoryIcon}
|
||||
title={columnTitle}
|
||||
onClick={handleHeaderClick}
|
||||
multiColumn={multiColumn}
|
||||
|
|
|
@ -7,7 +7,7 @@ import { Helmet } from 'react-helmet';
|
|||
|
||||
import { useSelector, useDispatch } from 'react-redux';
|
||||
|
||||
import ArchiveIcon from '@/material-icons/400-24px/archive.svg?react';
|
||||
import InventoryIcon from '@/material-icons/400-24px/inventory_2.svg?react';
|
||||
import { fetchNotificationRequests, expandNotificationRequests } from 'mastodon/actions/notifications';
|
||||
import Column from 'mastodon/components/column';
|
||||
import ColumnHeader from 'mastodon/components/column_header';
|
||||
|
@ -43,7 +43,7 @@ export const NotificationRequests = ({ multiColumn }) => {
|
|||
<Column bindToDocument={!multiColumn} ref={columnRef} label={intl.formatMessage(messages.title)}>
|
||||
<ColumnHeader
|
||||
icon='archive'
|
||||
iconComponent={ArchiveIcon}
|
||||
iconComponent={InventoryIcon}
|
||||
title={intl.formatMessage(messages.title)}
|
||||
onClick={handleHeaderClick}
|
||||
multiColumn={multiColumn}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue