parent
f0acd992c5
commit
c37aba43f9
7 changed files with 110 additions and 6 deletions
11
app/javascript/mastodon/api_types/dummy_types.ts
Normal file
11
app/javascript/mastodon/api_types/dummy_types.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
// A similar definition will eventually be added in the main house. These definitions will replace it.
|
||||
|
||||
export interface ApiListJSON_KmyDummy {
|
||||
id: string;
|
||||
title: string;
|
||||
exclusive: boolean;
|
||||
notify: boolean;
|
||||
|
||||
// replies_policy
|
||||
// antennas
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
import type { AccountWarningAction } from 'mastodon/models/notification_group';
|
||||
|
||||
import type { ApiAccountJSON } from './accounts';
|
||||
import type { ApiListJSON_KmyDummy } from './dummy_types';
|
||||
import type { ApiReportJSON } from './reports';
|
||||
import type { ApiStatusJSON } from './statuses';
|
||||
|
||||
|
@ -17,6 +18,7 @@ export const allNotificationTypes = [
|
|||
'status_reference',
|
||||
'poll',
|
||||
'status',
|
||||
'list_status',
|
||||
'update',
|
||||
'admin.sign_up',
|
||||
'admin.report',
|
||||
|
@ -29,6 +31,7 @@ export type NotificationWithStatusType =
|
|||
| 'emoji_reaction'
|
||||
| 'reblog'
|
||||
| 'status'
|
||||
| 'list_status'
|
||||
| 'mention'
|
||||
| 'status_reference'
|
||||
| 'poll'
|
||||
|
@ -78,6 +81,7 @@ export interface BaseNotificationGroupJSON {
|
|||
page_min_id?: string;
|
||||
page_max_id?: string;
|
||||
emoji_reaction_groups?: NotificationEmojiReactionGroupJSON[];
|
||||
list?: ApiListJSON_KmyDummy;
|
||||
}
|
||||
|
||||
interface NotificationGroupWithStatusJSON extends BaseNotificationGroupJSON {
|
||||
|
|
|
@ -13,6 +13,7 @@ import { NotificationEmojiReaction } from './notification_emoji_reaction';
|
|||
import { NotificationFavourite } from './notification_favourite';
|
||||
import { NotificationFollow } from './notification_follow';
|
||||
import { NotificationFollowRequest } from './notification_follow_request';
|
||||
import { NotificationListStatus } from './notification_list_status';
|
||||
import { NotificationMention } from './notification_mention';
|
||||
import { NotificationModerationWarning } from './notification_moderation_warning';
|
||||
import { NotificationPoll } from './notification_poll';
|
||||
|
@ -132,6 +133,14 @@ export const NotificationGroup: React.FC<{
|
|||
<NotificationStatus unread={unread} notification={notificationGroup} />
|
||||
);
|
||||
break;
|
||||
case 'list_status':
|
||||
content = (
|
||||
<NotificationListStatus
|
||||
unread={unread}
|
||||
notification={notificationGroup}
|
||||
/>
|
||||
);
|
||||
break;
|
||||
case 'update':
|
||||
content = (
|
||||
<NotificationUpdate unread={unread} notification={notificationGroup} />
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import NotificationsActiveIcon from '@/material-icons/400-24px/notifications_active-fill.svg?react';
|
||||
import type { NotificationGroupListStatus } from 'mastodon/models/notification_group';
|
||||
|
||||
import type { LabelRenderer } from './notification_group_with_status';
|
||||
import { NotificationWithStatus } from './notification_with_status';
|
||||
|
||||
const createLabelRenderer = (
|
||||
notification: NotificationGroupListStatus,
|
||||
): LabelRenderer => {
|
||||
const renderer: LabelRenderer = (values) => {
|
||||
const list = notification.list;
|
||||
if (list) {
|
||||
const listLink = (
|
||||
<bdi>
|
||||
<Link
|
||||
className='notification__display-name'
|
||||
href={`/lists/${list.id}`}
|
||||
title={list.title}
|
||||
to={`/lists/${list.id}`}
|
||||
>
|
||||
{list.title}
|
||||
</Link>
|
||||
</bdi>
|
||||
);
|
||||
values.listName = listLink;
|
||||
}
|
||||
|
||||
return (
|
||||
<FormattedMessage
|
||||
id='notification.list_status'
|
||||
defaultMessage='{name} post is added to {listName}'
|
||||
values={values}
|
||||
/>
|
||||
);
|
||||
};
|
||||
return renderer;
|
||||
};
|
||||
|
||||
export const NotificationListStatus: React.FC<{
|
||||
notification: NotificationGroupListStatus;
|
||||
unread: boolean;
|
||||
}> = ({ notification, unread }) => (
|
||||
<NotificationWithStatus
|
||||
type='list_status'
|
||||
icon={NotificationsActiveIcon}
|
||||
iconId='notifications-active'
|
||||
accountIds={notification.sampleAccountIds}
|
||||
count={notification.notifications_count}
|
||||
statusId={notification.statusId}
|
||||
labelRenderer={createLabelRenderer(notification)}
|
||||
unread={unread}
|
||||
muted
|
||||
/>
|
||||
);
|
|
@ -54,6 +54,8 @@ export type NotificationGroupEmojiReaction =
|
|||
BaseNotificationWithStatus<'emoji_reaction'>;
|
||||
export type NotificationGroupReblog = BaseNotificationWithStatus<'reblog'>;
|
||||
export type NotificationGroupStatus = BaseNotificationWithStatus<'status'>;
|
||||
export type NotificationGroupListStatus =
|
||||
BaseNotificationWithStatus<'list_status'>;
|
||||
export type NotificationGroupMention = BaseNotificationWithStatus<'mention'>;
|
||||
export type NotificationGroupStatusReference =
|
||||
BaseNotificationWithStatus<'status_reference'>;
|
||||
|
@ -103,6 +105,7 @@ export type NotificationGroup =
|
|||
| NotificationGroupEmojiReaction
|
||||
| NotificationGroupReblog
|
||||
| NotificationGroupStatus
|
||||
| NotificationGroupListStatus
|
||||
| NotificationGroupMention
|
||||
| NotificationGroupStatusReference
|
||||
| NotificationGroupPoll
|
||||
|
@ -161,6 +164,7 @@ export function createNotificationGroupFromJSON(
|
|||
case 'favourite':
|
||||
case 'reblog':
|
||||
case 'status':
|
||||
case 'list_status':
|
||||
case 'mention':
|
||||
case 'status_reference':
|
||||
case 'poll':
|
||||
|
@ -244,6 +248,7 @@ export function createNotificationGroupFromNotificationJSON(
|
|||
case 'favourite':
|
||||
case 'reblog':
|
||||
case 'status':
|
||||
case 'list_status':
|
||||
case 'mention':
|
||||
case 'status_reference':
|
||||
case 'poll':
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class NotificationGroup < ActiveModelSerializers::Model
|
||||
attributes :group_key, :sample_accounts, :notifications_count, :notification, :most_recent_notification_id, :emoji_reaction_groups
|
||||
attributes :group_key, :sample_accounts, :notifications_count, :notification, :most_recent_notification_id, :emoji_reaction_groups, :list
|
||||
|
||||
# Try to keep this consistent with `app/javascript/mastodon/models/notification_group.ts`
|
||||
SAMPLE_ACCOUNTS_SIZE = 8
|
||||
|
@ -18,17 +18,19 @@ class NotificationGroup < ActiveModelSerializers::Model
|
|||
scope = scope.where(id: ..max_id) if max_id.present?
|
||||
|
||||
# Ideally, we would not load accounts for each notification group
|
||||
most_recent_notifications = scope.order(id: :desc).includes(:from_account).take(SAMPLE_ACCOUNTS_SIZE)
|
||||
most_recent_notifications = scope.order(id: :desc).includes(:from_account, :list_status).take(SAMPLE_ACCOUNTS_SIZE)
|
||||
most_recent_id = most_recent_notifications.first.id
|
||||
sample_accounts = most_recent_notifications.map(&:from_account)
|
||||
emoji_reaction_groups = extract_emoji_reaction_pair(
|
||||
scope.order(id: :desc).includes(emoji_reaction: :account).take(SAMPLE_ACCOUNTS_SIZE_FOR_EMOJI_REACTION)
|
||||
)
|
||||
list = pick_list(most_recent_notifications)
|
||||
notifications_count = scope.count
|
||||
else
|
||||
most_recent_id = notification.id
|
||||
sample_accounts = [notification.from_account]
|
||||
emoji_reaction_groups = extract_emoji_reaction_pair([notification])
|
||||
list = pick_list([notification])
|
||||
notifications_count = 1
|
||||
end
|
||||
|
||||
|
@ -37,6 +39,7 @@ class NotificationGroup < ActiveModelSerializers::Model
|
|||
group_key: notification.group_key || "ungrouped-#{notification.id}",
|
||||
sample_accounts: sample_accounts,
|
||||
emoji_reaction_groups: emoji_reaction_groups,
|
||||
list: list,
|
||||
notifications_count: notifications_count,
|
||||
most_recent_notification_id: most_recent_id
|
||||
)
|
||||
|
@ -50,14 +53,23 @@ class NotificationGroup < ActiveModelSerializers::Model
|
|||
to: :notification, prefix: false
|
||||
|
||||
def self.extract_emoji_reaction_pair(scope)
|
||||
scope = scope.filter { |g| g.emoji_reaction.present? }
|
||||
|
||||
return [] if scope.empty?
|
||||
return [] unless scope.first.type == :emoji_reaction
|
||||
|
||||
scope = scope.filter { |g| g.emoji_reaction.present? }
|
||||
return [] if scope.empty?
|
||||
|
||||
scope
|
||||
.each_with_object({}) { |e, h| h[e.emoji_reaction.name] = (h[e.emoji_reaction.name] || []).push(e.emoji_reaction) }
|
||||
.to_a
|
||||
.map { |pair| NotificationEmojiReactionGroup.new(emoji_reaction: pair[1].first, sample_accounts: pair[1].take(SAMPLE_ACCOUNTS_SIZE).map(&:account)) }
|
||||
end
|
||||
|
||||
def self.pick_list(scope)
|
||||
return [] unless scope.first.type == :list_status
|
||||
|
||||
scope = scope.filter { |g| g.list_status.present? }
|
||||
return [] if scope.empty?
|
||||
|
||||
scope.first.list_status.list
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,7 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer
|
|||
belongs_to :report, if: :report_type?, serializer: REST::ReportSerializer
|
||||
belongs_to :account_relationship_severance_event, key: :event, if: :relationship_severance_event?, serializer: REST::AccountRelationshipSeveranceEventSerializer
|
||||
belongs_to :account_warning, key: :moderation_warning, if: :moderation_warning_event?, serializer: REST::AccountWarningSerializer
|
||||
has_one :list, if: :list_status_type?, serializer: REST::ListSerializer
|
||||
|
||||
def sample_account_ids
|
||||
object.sample_accounts.pluck(:id).map(&:to_s)
|
||||
|
@ -23,7 +24,7 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer
|
|||
end
|
||||
|
||||
def status_type?
|
||||
[:favourite, :emoji_reaction, :reblog, :status, :mention, :status_reference, :poll, :update].include?(object.type)
|
||||
[:favourite, :emoji_reaction, :reblog, :status, :mention, :status_reference, :poll, :update, :list_status].include?(object.type)
|
||||
end
|
||||
|
||||
def report_type?
|
||||
|
@ -34,6 +35,10 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer
|
|||
object.type == :emoji_reaction
|
||||
end
|
||||
|
||||
def list_status_type?
|
||||
object.type == :list_status
|
||||
end
|
||||
|
||||
def relationship_severance_event?
|
||||
object.type == :severed_relationships
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue