mirror of
https://github.com/mastodon/mastodon.git
synced 2025-09-05 17:31:12 +00:00
Add quote notifications to WebUI (#35653)
Some checks failed
Check i18n / check-i18n (push) Waiting to run
Chromatic / Run Chromatic (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (ruby) (push) Waiting to run
Crowdin / Upload translations / upload-translations (push) Waiting to run
Check formatting / lint (push) Waiting to run
Haml Linting / lint (push) Waiting to run
JavaScript Linting / lint (push) Waiting to run
Ruby Linting / lint (push) Waiting to run
JavaScript Testing / test (push) Waiting to run
Historical data migration test / test (14-alpine) (push) Waiting to run
Historical data migration test / test (15-alpine) (push) Waiting to run
Historical data migration test / test (16-alpine) (push) Waiting to run
Historical data migration test / test (17-alpine) (push) Waiting to run
Ruby Testing / build (production) (push) Waiting to run
Ruby Testing / build (test) (push) Waiting to run
Ruby Testing / test (.ruby-version) (push) Blocked by required conditions
Ruby Testing / test (3.2) (push) Blocked by required conditions
Ruby Testing / test (3.3) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (.ruby-version) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.2) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.3) (push) Blocked by required conditions
Ruby Testing / End to End testing (.ruby-version) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.2) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.3) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.10.2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.2, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
CSS Linting / lint (push) Has been cancelled
Some checks failed
Check i18n / check-i18n (push) Waiting to run
Chromatic / Run Chromatic (push) Waiting to run
CodeQL / Analyze (javascript) (push) Waiting to run
CodeQL / Analyze (ruby) (push) Waiting to run
Crowdin / Upload translations / upload-translations (push) Waiting to run
Check formatting / lint (push) Waiting to run
Haml Linting / lint (push) Waiting to run
JavaScript Linting / lint (push) Waiting to run
Ruby Linting / lint (push) Waiting to run
JavaScript Testing / test (push) Waiting to run
Historical data migration test / test (14-alpine) (push) Waiting to run
Historical data migration test / test (15-alpine) (push) Waiting to run
Historical data migration test / test (16-alpine) (push) Waiting to run
Historical data migration test / test (17-alpine) (push) Waiting to run
Ruby Testing / build (production) (push) Waiting to run
Ruby Testing / build (test) (push) Waiting to run
Ruby Testing / test (.ruby-version) (push) Blocked by required conditions
Ruby Testing / test (3.2) (push) Blocked by required conditions
Ruby Testing / test (3.3) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (.ruby-version) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.2) (push) Blocked by required conditions
Ruby Testing / ImageMagick tests (3.3) (push) Blocked by required conditions
Ruby Testing / End to End testing (.ruby-version) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.2) (push) Blocked by required conditions
Ruby Testing / End to End testing (3.3) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, docker.elastic.co/elasticsearch/elasticsearch:8.10.2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (.ruby-version, opensearchproject/opensearch:2) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.2, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
Ruby Testing / Elastic Search integration testing (3.3, docker.elastic.co/elasticsearch/elasticsearch:7.17.13) (push) Blocked by required conditions
CSS Linting / lint (push) Has been cancelled
This commit is contained in:
parent
570c9d16be
commit
081d38679f
|
@ -13,6 +13,7 @@ export const allNotificationTypes = [
|
|||
'favourite',
|
||||
'reblog',
|
||||
'mention',
|
||||
'quote',
|
||||
'poll',
|
||||
'status',
|
||||
'update',
|
||||
|
@ -28,6 +29,7 @@ export type NotificationWithStatusType =
|
|||
| 'reblog'
|
||||
| 'status'
|
||||
| 'mention'
|
||||
| 'quote'
|
||||
| 'poll'
|
||||
| 'update';
|
||||
|
||||
|
|
|
@ -8,9 +8,9 @@ import { Link, withRouter } from 'react-router-dom';
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
|
||||
import EditIcon from '@/material-icons/400-24px/edit.svg?react';
|
||||
import FlagIcon from '@/material-icons/400-24px/flag-fill.svg?react';
|
||||
import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.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 PersonIcon from '@/material-icons/400-24px/person-fill.svg?react';
|
||||
|
@ -42,6 +42,7 @@ const messages = defineMessages({
|
|||
adminReport: { id: 'notification.admin.report', defaultMessage: '{name} reported {target}' },
|
||||
relationshipsSevered: { id: 'notification.relationships_severance_event', defaultMessage: 'Lost connections with {name}' },
|
||||
moderationWarning: { id: 'notification.moderation_warning', defaultMessage: 'You have received a moderation warning' },
|
||||
quote: { id: 'notification.label.quote', defaultMessage: '{name} quoted your post'}
|
||||
});
|
||||
|
||||
const notificationForScreenReader = (intl, message, timestamp) => {
|
||||
|
@ -251,6 +252,36 @@ class Notification extends ImmutablePureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
renderQuote (notification, link) {
|
||||
const { intl, unread } = this.props;
|
||||
|
||||
return (
|
||||
<Hotkeys handlers={this.getHandlers()}>
|
||||
<div className={classNames('notification notification-quote focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.quote, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
|
||||
<div className='notification__message'>
|
||||
<Icon id='quote' icon={FormatQuoteIcon} />
|
||||
|
||||
<span title={notification.get('created_at')}>
|
||||
<FormattedMessage id='notification.label.quote' defaultMessage='{name} quoted your post' values={{ name: link }} />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<StatusQuoteManager
|
||||
id={notification.get('status')}
|
||||
account={notification.get('account')}
|
||||
muted
|
||||
withDismiss
|
||||
hidden={this.props.hidden}
|
||||
getScrollPosition={this.props.getScrollPosition}
|
||||
updateScrollBottom={this.props.updateScrollBottom}
|
||||
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||
/>
|
||||
</div>
|
||||
</Hotkeys>
|
||||
);
|
||||
}
|
||||
|
||||
renderStatus (notification, link) {
|
||||
const { intl, unread, status } = this.props;
|
||||
|
||||
|
@ -467,6 +498,8 @@ class Notification extends ImmutablePureComponent {
|
|||
return this.renderFollowRequest(notification, account, link);
|
||||
case 'mention':
|
||||
return this.renderMention(notification);
|
||||
case 'quote':
|
||||
return this.renderQuote(notification);
|
||||
case 'favourite':
|
||||
return this.renderFavourite(notification, link);
|
||||
case 'reblog':
|
||||
|
|
|
@ -15,6 +15,7 @@ import { NotificationFollowRequest } from './notification_follow_request';
|
|||
import { NotificationMention } from './notification_mention';
|
||||
import { NotificationModerationWarning } from './notification_moderation_warning';
|
||||
import { NotificationPoll } from './notification_poll';
|
||||
import { NotificationQuote } from './notification_quote';
|
||||
import { NotificationReblog } from './notification_reblog';
|
||||
import { NotificationSeveredRelationships } from './notification_severed_relationships';
|
||||
import { NotificationStatus } from './notification_status';
|
||||
|
@ -91,6 +92,11 @@ export const NotificationGroup: React.FC<{
|
|||
<NotificationMention unread={unread} notification={notificationGroup} />
|
||||
);
|
||||
break;
|
||||
case 'quote':
|
||||
content = (
|
||||
<NotificationQuote unread={unread} notification={notificationGroup} />
|
||||
);
|
||||
break;
|
||||
case 'follow':
|
||||
content = (
|
||||
<NotificationFollow unread={unread} notification={notificationGroup} />
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import FormatQuoteIcon from '@/material-icons/400-24px/format_quote.svg?react';
|
||||
import type { NotificationGroupQuote } from 'mastodon/models/notification_group';
|
||||
|
||||
import type { LabelRenderer } from './notification_group_with_status';
|
||||
import { NotificationWithStatus } from './notification_with_status';
|
||||
|
||||
const quoteLabelRenderer: LabelRenderer = (displayName) => (
|
||||
<FormattedMessage
|
||||
id='notification.label.quote'
|
||||
defaultMessage='{name} quoted your post'
|
||||
values={{ name: displayName }}
|
||||
/>
|
||||
);
|
||||
|
||||
export const NotificationQuote: React.FC<{
|
||||
notification: NotificationGroupQuote;
|
||||
unread: boolean;
|
||||
}> = ({ notification, unread }) => {
|
||||
return (
|
||||
<NotificationWithStatus
|
||||
type='quote'
|
||||
icon={FormatQuoteIcon}
|
||||
iconId='quote'
|
||||
accountIds={notification.sampleAccountIds}
|
||||
count={notification.notifications_count}
|
||||
statusId={notification.statusId}
|
||||
labelRenderer={quoteLabelRenderer}
|
||||
unread={unread}
|
||||
/>
|
||||
);
|
||||
};
|
|
@ -600,6 +600,7 @@
|
|||
"notification.label.mention": "Mention",
|
||||
"notification.label.private_mention": "Private mention",
|
||||
"notification.label.private_reply": "Private reply",
|
||||
"notification.label.quote": "{name} quoted your post",
|
||||
"notification.label.reply": "Reply",
|
||||
"notification.mention": "Mention",
|
||||
"notification.mentioned_you": "{name} mentioned you",
|
||||
|
|
|
@ -36,6 +36,7 @@ export type NotificationGroupFavourite =
|
|||
export type NotificationGroupReblog = BaseNotificationWithStatus<'reblog'>;
|
||||
export type NotificationGroupStatus = BaseNotificationWithStatus<'status'>;
|
||||
export type NotificationGroupMention = BaseNotificationWithStatus<'mention'>;
|
||||
export type NotificationGroupQuote = BaseNotificationWithStatus<'quote'>;
|
||||
export type NotificationGroupPoll = BaseNotificationWithStatus<'poll'>;
|
||||
export type NotificationGroupUpdate = BaseNotificationWithStatus<'update'>;
|
||||
export type NotificationGroupFollow = BaseNotification<'follow'>;
|
||||
|
@ -87,6 +88,7 @@ export type NotificationGroup =
|
|||
| NotificationGroupReblog
|
||||
| NotificationGroupStatus
|
||||
| NotificationGroupMention
|
||||
| NotificationGroupQuote
|
||||
| NotificationGroupPoll
|
||||
| NotificationGroupUpdate
|
||||
| NotificationGroupFollow
|
||||
|
@ -137,6 +139,7 @@ export function createNotificationGroupFromJSON(
|
|||
case 'reblog':
|
||||
case 'status':
|
||||
case 'mention':
|
||||
case 'quote':
|
||||
case 'poll':
|
||||
case 'update': {
|
||||
const { status_id: statusId, ...groupWithoutStatus } = group;
|
||||
|
@ -209,6 +212,7 @@ export function createNotificationGroupFromNotificationJSON(
|
|||
case 'reblog':
|
||||
case 'status':
|
||||
case 'mention':
|
||||
case 'quote':
|
||||
case 'poll':
|
||||
case 'update':
|
||||
return {
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m228-240 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T458-480L320-240h-92Zm360 0 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T818-480L680-240h-92Z"/></svg>
|
After Width: | Height: | Size: 322 B |
1
app/javascript/material-icons/400-24px/format_quote.svg
Normal file
1
app/javascript/material-icons/400-24px/format_quote.svg
Normal file
|
@ -0,0 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="m228-240 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T458-480L320-240h-92Zm360 0 92-160q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 23-5.5 42.5T818-480L680-240h-92ZM320-500q25 0 42.5-17.5T380-560q0-25-17.5-42.5T320-620q-25 0-42.5 17.5T260-560q0 25 17.5 42.5T320-500Zm360 0q25 0 42.5-17.5T740-560q0-25-17.5-42.5T680-620q-25 0-42.5 17.5T620-560q0 25 17.5 42.5T680-500Zm0-60Zm-360 0Z"/></svg>
|
After Width: | Height: | Size: 538 B |
Loading…
Reference in New Issue
Block a user