mirror of
https://github.com/mastodon/mastodon.git
synced 2025-09-05 17:31:12 +00:00
Add quoted_update
notification type (#35820)
This commit is contained in:
parent
7aba79ade9
commit
f3a932d8a1
|
@ -31,7 +31,8 @@ export type NotificationWithStatusType =
|
||||||
| 'mention'
|
| 'mention'
|
||||||
| 'quote'
|
| 'quote'
|
||||||
| 'poll'
|
| 'poll'
|
||||||
| 'update';
|
| 'update'
|
||||||
|
| 'quoted_update';
|
||||||
|
|
||||||
export type NotificationType =
|
export type NotificationType =
|
||||||
| NotificationWithStatusType
|
| NotificationWithStatusType
|
||||||
|
|
|
@ -38,6 +38,7 @@ const messages = defineMessages({
|
||||||
reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your post' },
|
reblog: { id: 'notification.reblog', defaultMessage: '{name} boosted your post' },
|
||||||
status: { id: 'notification.status', defaultMessage: '{name} just posted' },
|
status: { id: 'notification.status', defaultMessage: '{name} just posted' },
|
||||||
update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
|
update: { id: 'notification.update', defaultMessage: '{name} edited a post' },
|
||||||
|
quoted_update: { id: 'notification.quoted_update', defaultMessage: '{name} edited a post you have quoted' },
|
||||||
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}' },
|
||||||
|
@ -336,6 +337,41 @@ class Notification extends ImmutablePureComponent {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderQuotedUpdate (notification, link) {
|
||||||
|
const { intl, unread, status } = this.props;
|
||||||
|
|
||||||
|
if (!status) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Hotkeys handlers={this.getHandlers()}>
|
||||||
|
<div className={classNames('notification notification-update focusable', { unread })} tabIndex={0} aria-label={notificationForScreenReader(intl, intl.formatMessage(messages.update, { name: notification.getIn(['account', 'acct']) }), notification.get('created_at'))}>
|
||||||
|
<div className='notification__message'>
|
||||||
|
<Icon id='pencil' icon={EditIcon} />
|
||||||
|
|
||||||
|
<span title={notification.get('created_at')}>
|
||||||
|
<FormattedMessage id='notification.quoted_update' defaultMessage='{name} edited a post you have quoted' values={{ name: link }} />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<StatusQuoteManager
|
||||||
|
id={notification.get('status')}
|
||||||
|
account={notification.get('account')}
|
||||||
|
contextType='notifications'
|
||||||
|
muted
|
||||||
|
withDismiss
|
||||||
|
hidden={this.props.hidden}
|
||||||
|
getScrollPosition={this.props.getScrollPosition}
|
||||||
|
updateScrollBottom={this.props.updateScrollBottom}
|
||||||
|
cachedMediaWidth={this.props.cachedMediaWidth}
|
||||||
|
cacheMediaWidth={this.props.cacheMediaWidth}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Hotkeys>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
renderPoll (notification, account) {
|
renderPoll (notification, account) {
|
||||||
const { intl, unread, status } = this.props;
|
const { intl, unread, status } = this.props;
|
||||||
const ownPoll = me === account.get('id');
|
const ownPoll = me === account.get('id');
|
||||||
|
@ -492,6 +528,8 @@ class Notification extends ImmutablePureComponent {
|
||||||
return this.renderStatus(notification, link);
|
return this.renderStatus(notification, link);
|
||||||
case 'update':
|
case 'update':
|
||||||
return this.renderUpdate(notification, link);
|
return this.renderUpdate(notification, link);
|
||||||
|
case 'quoted_update':
|
||||||
|
return this.renderQuotedUpdate(notification, link);
|
||||||
case 'poll':
|
case 'poll':
|
||||||
return this.renderPoll(notification, account);
|
return this.renderPoll(notification, account);
|
||||||
case 'severed_relationships':
|
case 'severed_relationships':
|
||||||
|
|
|
@ -16,6 +16,7 @@ import { NotificationMention } from './notification_mention';
|
||||||
import { NotificationModerationWarning } from './notification_moderation_warning';
|
import { NotificationModerationWarning } from './notification_moderation_warning';
|
||||||
import { NotificationPoll } from './notification_poll';
|
import { NotificationPoll } from './notification_poll';
|
||||||
import { NotificationQuote } from './notification_quote';
|
import { NotificationQuote } from './notification_quote';
|
||||||
|
import { NotificationQuotedUpdate } from './notification_quoted_update';
|
||||||
import { NotificationReblog } from './notification_reblog';
|
import { NotificationReblog } from './notification_reblog';
|
||||||
import { NotificationSeveredRelationships } from './notification_severed_relationships';
|
import { NotificationSeveredRelationships } from './notification_severed_relationships';
|
||||||
import { NotificationStatus } from './notification_status';
|
import { NotificationStatus } from './notification_status';
|
||||||
|
@ -115,6 +116,14 @@ export const NotificationGroup: React.FC<{
|
||||||
<NotificationUpdate unread={unread} notification={notificationGroup} />
|
<NotificationUpdate unread={unread} notification={notificationGroup} />
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case 'quoted_update':
|
||||||
|
content = (
|
||||||
|
<NotificationQuotedUpdate
|
||||||
|
unread={unread}
|
||||||
|
notification={notificationGroup}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
case 'admin.sign_up':
|
case 'admin.sign_up':
|
||||||
content = (
|
content = (
|
||||||
<NotificationAdminSignUp
|
<NotificationAdminSignUp
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import EditIcon from '@/material-icons/400-24px/edit.svg?react';
|
||||||
|
import type { NotificationGroupQuotedUpdate } from 'mastodon/models/notification_group';
|
||||||
|
|
||||||
|
import type { LabelRenderer } from './notification_group_with_status';
|
||||||
|
import { NotificationWithStatus } from './notification_with_status';
|
||||||
|
|
||||||
|
const labelRenderer: LabelRenderer = (displayedName) => (
|
||||||
|
<FormattedMessage
|
||||||
|
id='notification.quoted_update'
|
||||||
|
defaultMessage='{name} edited a post you have quoted'
|
||||||
|
values={{ name: displayedName }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
export const NotificationQuotedUpdate: React.FC<{
|
||||||
|
notification: NotificationGroupQuotedUpdate;
|
||||||
|
unread: boolean;
|
||||||
|
}> = ({ notification, unread }) => (
|
||||||
|
<NotificationWithStatus
|
||||||
|
type='update'
|
||||||
|
icon={EditIcon}
|
||||||
|
iconId='edit'
|
||||||
|
accountIds={notification.sampleAccountIds}
|
||||||
|
count={notification.notifications_count}
|
||||||
|
statusId={notification.statusId}
|
||||||
|
labelRenderer={labelRenderer}
|
||||||
|
unread={unread}
|
||||||
|
/>
|
||||||
|
);
|
|
@ -620,6 +620,7 @@
|
||||||
"notification.moderation_warning.action_suspend": "Your account has been suspended.",
|
"notification.moderation_warning.action_suspend": "Your account has been suspended.",
|
||||||
"notification.own_poll": "Your poll has ended",
|
"notification.own_poll": "Your poll has ended",
|
||||||
"notification.poll": "A poll you voted in has ended",
|
"notification.poll": "A poll you voted in has ended",
|
||||||
|
"notification.quoted_update": "{name} edited a post you have quoted",
|
||||||
"notification.reblog": "{name} boosted your post",
|
"notification.reblog": "{name} boosted your post",
|
||||||
"notification.reblog.name_and_others_with_link": "{name} and <a>{count, plural, one {# other} other {# others}}</a> boosted your post",
|
"notification.reblog.name_and_others_with_link": "{name} and <a>{count, plural, one {# other} other {# others}}</a> boosted your post",
|
||||||
"notification.relationships_severance_event": "Lost connections with {name}",
|
"notification.relationships_severance_event": "Lost connections with {name}",
|
||||||
|
|
|
@ -39,6 +39,8 @@ export type NotificationGroupMention = BaseNotificationWithStatus<'mention'>;
|
||||||
export type NotificationGroupQuote = BaseNotificationWithStatus<'quote'>;
|
export type NotificationGroupQuote = BaseNotificationWithStatus<'quote'>;
|
||||||
export type NotificationGroupPoll = BaseNotificationWithStatus<'poll'>;
|
export type NotificationGroupPoll = BaseNotificationWithStatus<'poll'>;
|
||||||
export type NotificationGroupUpdate = BaseNotificationWithStatus<'update'>;
|
export type NotificationGroupUpdate = BaseNotificationWithStatus<'update'>;
|
||||||
|
export type NotificationGroupQuotedUpdate =
|
||||||
|
BaseNotificationWithStatus<'quoted_update'>;
|
||||||
export type NotificationGroupFollow = BaseNotification<'follow'>;
|
export type NotificationGroupFollow = BaseNotification<'follow'>;
|
||||||
export type NotificationGroupFollowRequest = BaseNotification<'follow_request'>;
|
export type NotificationGroupFollowRequest = BaseNotification<'follow_request'>;
|
||||||
export type NotificationGroupAdminSignUp = BaseNotification<'admin.sign_up'>;
|
export type NotificationGroupAdminSignUp = BaseNotification<'admin.sign_up'>;
|
||||||
|
@ -91,6 +93,7 @@ export type NotificationGroup =
|
||||||
| NotificationGroupQuote
|
| NotificationGroupQuote
|
||||||
| NotificationGroupPoll
|
| NotificationGroupPoll
|
||||||
| NotificationGroupUpdate
|
| NotificationGroupUpdate
|
||||||
|
| NotificationGroupQuotedUpdate
|
||||||
| NotificationGroupFollow
|
| NotificationGroupFollow
|
||||||
| NotificationGroupFollowRequest
|
| NotificationGroupFollowRequest
|
||||||
| NotificationGroupModerationWarning
|
| NotificationGroupModerationWarning
|
||||||
|
@ -141,7 +144,8 @@ export function createNotificationGroupFromJSON(
|
||||||
case 'mention':
|
case 'mention':
|
||||||
case 'quote':
|
case 'quote':
|
||||||
case 'poll':
|
case 'poll':
|
||||||
case 'update': {
|
case 'update':
|
||||||
|
case 'quoted_update': {
|
||||||
const { status_id: statusId, ...groupWithoutStatus } = group;
|
const { status_id: statusId, ...groupWithoutStatus } = group;
|
||||||
return {
|
return {
|
||||||
statusId: statusId ?? undefined,
|
statusId: statusId ?? undefined,
|
||||||
|
@ -215,6 +219,7 @@ export function createNotificationGroupFromNotificationJSON(
|
||||||
case 'quote':
|
case 'quote':
|
||||||
case 'poll':
|
case 'poll':
|
||||||
case 'update':
|
case 'update':
|
||||||
|
case 'quoted_update':
|
||||||
return {
|
return {
|
||||||
...group,
|
...group,
|
||||||
type: notification.type,
|
type: notification.type,
|
||||||
|
|
|
@ -77,6 +77,9 @@ class Notification < ApplicationRecord
|
||||||
quote: {
|
quote: {
|
||||||
filterable: true,
|
filterable: true,
|
||||||
}.freeze,
|
}.freeze,
|
||||||
|
quoted_update: {
|
||||||
|
filterable: false,
|
||||||
|
}.freeze,
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
TYPES = PROPERTIES.keys.freeze
|
TYPES = PROPERTIES.keys.freeze
|
||||||
|
@ -89,6 +92,7 @@ class Notification < ApplicationRecord
|
||||||
favourite: [favourite: :status],
|
favourite: [favourite: :status],
|
||||||
poll: [poll: :status],
|
poll: [poll: :status],
|
||||||
update: :status,
|
update: :status,
|
||||||
|
quoted_update: :status,
|
||||||
'admin.report': [report: :target_account],
|
'admin.report': [report: :target_account],
|
||||||
}.freeze
|
}.freeze
|
||||||
|
|
||||||
|
@ -120,7 +124,7 @@ class Notification < ApplicationRecord
|
||||||
|
|
||||||
def target_status
|
def target_status
|
||||||
case type
|
case type
|
||||||
when :status, :update
|
when :status, :update, :quoted_update
|
||||||
status
|
status
|
||||||
when :reblog
|
when :reblog
|
||||||
status&.reblog
|
status&.reblog
|
||||||
|
@ -172,7 +176,7 @@ class Notification < ApplicationRecord
|
||||||
cached_status = cached_statuses_by_id[notification.target_status.id]
|
cached_status = cached_statuses_by_id[notification.target_status.id]
|
||||||
|
|
||||||
case notification.type
|
case notification.type
|
||||||
when :status, :update
|
when :status, :update, :quoted_update
|
||||||
notification.status = cached_status
|
notification.status = cached_status
|
||||||
when :reblog
|
when :reblog
|
||||||
notification.status.reblog = cached_status
|
notification.status.reblog = cached_status
|
||||||
|
@ -202,7 +206,9 @@ class Notification < ApplicationRecord
|
||||||
return unless new_record?
|
return unless new_record?
|
||||||
|
|
||||||
case activity_type
|
case activity_type
|
||||||
when 'Status', 'Follow', 'Favourite', 'FollowRequest', 'Poll', 'Report', 'Quote'
|
when 'Status'
|
||||||
|
self.from_account_id = type == :quoted_update ? activity&.quote&.quoted_account_id : activity&.account_id
|
||||||
|
when 'Follow', 'Favourite', 'FollowRequest', 'Poll', 'Report', 'Quote'
|
||||||
self.from_account_id = activity&.account_id
|
self.from_account_id = activity&.account_id
|
||||||
when 'Mention'
|
when 'Mention'
|
||||||
self.from_account_id = activity&.status&.account_id
|
self.from_account_id = activity&.status&.account_id
|
||||||
|
|
|
@ -24,7 +24,7 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def status_type?
|
def status_type?
|
||||||
[:favourite, :reblog, :status, :mention, :poll, :update, :quote].include?(object.type)
|
[:favourite, :reblog, :status, :mention, :poll, :update, :quote, :quoted_update].include?(object.type)
|
||||||
end
|
end
|
||||||
|
|
||||||
def report_type?
|
def report_type?
|
||||||
|
|
|
@ -99,6 +99,12 @@ class FanOutOnWriteService < BaseService
|
||||||
[account.id, @status.id, 'Status', 'update']
|
[account.id, @status.id, 'Status', 'update']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@status.quotes.accepted.find_in_batches do |quotes|
|
||||||
|
LocalNotificationWorker.push_bulk(quotes) do |quote|
|
||||||
|
[quote.account_id, quote.status_id, 'Status', 'quoted_update']
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def deliver_to_all_followers!
|
def deliver_to_all_followers!
|
||||||
|
|
|
@ -8,6 +8,7 @@ class NotifyService < BaseService
|
||||||
admin.report
|
admin.report
|
||||||
admin.sign_up
|
admin.sign_up
|
||||||
update
|
update
|
||||||
|
quoted_update
|
||||||
poll
|
poll
|
||||||
status
|
status
|
||||||
moderation_warning
|
moderation_warning
|
||||||
|
|
|
@ -17,6 +17,8 @@ class LocalNotificationWorker
|
||||||
# should replace the previous ones.
|
# should replace the previous ones.
|
||||||
if type == 'update'
|
if type == 'update'
|
||||||
Notification.where(account: receiver, activity: activity, type: 'update').in_batches.delete_all
|
Notification.where(account: receiver, activity: activity, type: 'update').in_batches.delete_all
|
||||||
|
elsif type == 'quoted_update'
|
||||||
|
Notification.where(account: receiver, activity: activity, type: 'quoted_update').in_batches.delete_all
|
||||||
elsif Notification.where(account: receiver, activity: activity, type: type).any?
|
elsif Notification.where(account: receiver, activity: activity, type: type).any?
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,6 +69,17 @@ RSpec.describe Notification do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when the notification is a quoted post update notification' do
|
||||||
|
it 'sets the notification from_account correctly' do
|
||||||
|
status = Fabricate(:status)
|
||||||
|
quote = Fabricate(:quote, quoted_status: status)
|
||||||
|
|
||||||
|
notification = Fabricate.build(:notification, activity_type: 'Status', type: 'quoted_update', activity: quote.status)
|
||||||
|
|
||||||
|
expect(notification.from_account).to eq(status.account)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context 'when activity_type is a Follow' do
|
context 'when activity_type is a Follow' do
|
||||||
it 'sets the notification from_account correctly' do
|
it 'sets the notification from_account correctly' do
|
||||||
follow = Fabricate(:follow)
|
follow = Fabricate(:follow)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user