Merge commit '9e04007020
' into upstream-20240725
This commit is contained in:
commit
a99f174d98
322 changed files with 8093 additions and 1586 deletions
|
@ -5,6 +5,14 @@ class Admin::ActionLogFilter
|
|||
action_type
|
||||
account_id
|
||||
target_account_id
|
||||
target_domain
|
||||
).freeze
|
||||
|
||||
INSTANCE_TARGET_TYPES = %w(
|
||||
DomainBlock
|
||||
DomainAllow
|
||||
Instance
|
||||
UnavailableDomain
|
||||
).freeze
|
||||
|
||||
ACTION_TYPE_MAP = {
|
||||
|
@ -99,6 +107,9 @@ class Admin::ActionLogFilter
|
|||
when 'target_account_id'
|
||||
account = Account.find_or_initialize_by(id: value)
|
||||
latest_action_logs.where(target: [account, account.user].compact)
|
||||
when 'target_domain'
|
||||
normalized_domain = TagManager.instance.normalize_domain(value)
|
||||
latest_action_logs.where(human_identifier: normalized_domain, target_type: INSTANCE_TARGET_TYPES)
|
||||
else
|
||||
raise Mastodon::InvalidParameterError, "Unknown filter: #{key}"
|
||||
end
|
||||
|
|
|
@ -34,6 +34,7 @@ class Notification < ApplicationRecord
|
|||
'AccountWarning' => :moderation_warning,
|
||||
}.freeze
|
||||
|
||||
# Please update app/javascript/api_types/notification.ts if you change this
|
||||
PROPERTIES = {
|
||||
mention: {
|
||||
filterable: true,
|
||||
|
@ -166,31 +167,51 @@ class Notification < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
def paginate_groups(limit, pagination_order)
|
||||
raise ArgumentError unless %i(asc desc).include?(pagination_order)
|
||||
|
||||
query = reorder(id: pagination_order)
|
||||
|
||||
unscoped
|
||||
.with_recursive(
|
||||
grouped_notifications: [
|
||||
# Base case: fetching one notification and annotating it with visited groups
|
||||
query
|
||||
.select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] AS groups")
|
||||
.limit(1),
|
||||
# Recursive case, always yielding at most one annotated notification
|
||||
unscoped
|
||||
.from(
|
||||
[
|
||||
# Expose the working table as `wt`, but quit early if we've reached the limit
|
||||
unscoped
|
||||
.select('id', 'groups')
|
||||
.from('grouped_notifications')
|
||||
.where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit)
|
||||
.arel.as('wt'),
|
||||
# Recursive query, using `LATERAL` so we can refer to `wt`
|
||||
query
|
||||
.where(pagination_order == :desc ? 'notifications.id < wt.id' : 'notifications.id > wt.id')
|
||||
.where.not("COALESCE(notifications.group_key, 'ungrouped-' || notifications.id) = ANY(wt.groups)")
|
||||
.limit(1)
|
||||
.arel.lateral('notifications'),
|
||||
]
|
||||
)
|
||||
.select('notifications.*', "array_append(wt.groups, COALESCE(notifications.group_key, 'ungrouped-' || notifications.id))"),
|
||||
]
|
||||
)
|
||||
.from('grouped_notifications AS notifications')
|
||||
.order(id: pagination_order)
|
||||
.limit(limit)
|
||||
end
|
||||
|
||||
# This returns notifications from the request page, but with at most one notification per group.
|
||||
# Notifications that have no `group_key` each count as a separate group.
|
||||
def paginate_groups_by_max_id(limit, max_id: nil, since_id: nil)
|
||||
query = reorder(id: :desc)
|
||||
query = query.where(id: ...max_id) if max_id.present?
|
||||
query = query.where(id: (since_id + 1)...) if since_id.present?
|
||||
|
||||
unscoped
|
||||
.with_recursive(
|
||||
grouped_notifications: [
|
||||
query
|
||||
.select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] groups")
|
||||
.limit(1),
|
||||
query
|
||||
.joins('CROSS JOIN grouped_notifications')
|
||||
.where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit)
|
||||
.where('notifications.id < grouped_notifications.id')
|
||||
.where.not("COALESCE(notifications.group_key, 'ungrouped-' || notifications.id) = ANY(grouped_notifications.groups)")
|
||||
.select('notifications.*', "array_append(grouped_notifications.groups, COALESCE(notifications.group_key, 'ungrouped-' || notifications.id))")
|
||||
.limit(1),
|
||||
]
|
||||
)
|
||||
.from('grouped_notifications AS notifications')
|
||||
.order(id: :desc)
|
||||
.limit(limit)
|
||||
query.paginate_groups(limit, :desc)
|
||||
end
|
||||
|
||||
# Differs from :paginate_groups_by_max_id in that it gives the results immediately following min_id,
|
||||
|
@ -200,25 +221,7 @@ class Notification < ApplicationRecord
|
|||
query = reorder(id: :asc)
|
||||
query = query.where(id: (min_id + 1)...) if min_id.present?
|
||||
query = query.where(id: ...max_id) if max_id.present?
|
||||
|
||||
unscoped
|
||||
.with_recursive(
|
||||
grouped_notifications: [
|
||||
query
|
||||
.select('notifications.*', "ARRAY[COALESCE(notifications.group_key, 'ungrouped-' || notifications.id)] groups")
|
||||
.limit(1),
|
||||
query
|
||||
.joins('CROSS JOIN grouped_notifications')
|
||||
.where('array_length(grouped_notifications.groups, 1) < :limit', limit: limit)
|
||||
.where('notifications.id > grouped_notifications.id')
|
||||
.where.not("COALESCE(notifications.group_key, 'ungrouped-' || notifications.id) = ANY(grouped_notifications.groups)")
|
||||
.select('notifications.*', "array_append(grouped_notifications.groups, COALESCE(notifications.group_key, 'ungrouped-' || notifications.id))")
|
||||
.limit(1),
|
||||
]
|
||||
)
|
||||
.from('grouped_notifications AS notifications')
|
||||
.order(id: :asc)
|
||||
.limit(limit)
|
||||
query.paginate_groups(limit, :asc)
|
||||
end
|
||||
|
||||
def to_a_grouped_paginated_by_id(limit, options = {})
|
||||
|
|
|
@ -3,13 +3,17 @@
|
|||
class NotificationGroup < ActiveModelSerializers::Model
|
||||
attributes :group_key, :sample_accounts, :notifications_count, :notification, :most_recent_notification_id
|
||||
|
||||
# Try to keep this consistent with `app/javascript/mastodon/models/notification_group.ts`
|
||||
SAMPLE_ACCOUNTS_SIZE = 8
|
||||
|
||||
def self.from_notification(notification, max_id: nil)
|
||||
if notification.group_key.present?
|
||||
# TODO: caching and preloading
|
||||
# TODO: caching, and, if caching, preloading
|
||||
scope = notification.account.notifications.where(group_key: notification.group_key)
|
||||
scope = scope.where(id: ..max_id) if max_id.present?
|
||||
|
||||
most_recent_notifications = scope.order(id: :desc).take(3)
|
||||
# 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_id = most_recent_notifications.first.id
|
||||
sample_accounts = most_recent_notifications.map(&:from_account)
|
||||
notifications_count = scope.count
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
# category :integer default("other"), not null
|
||||
# action_taken_at :datetime
|
||||
# rule_ids :bigint(8) is an Array
|
||||
# application_id :bigint(8)
|
||||
#
|
||||
|
||||
class Report < ApplicationRecord
|
||||
|
@ -31,6 +32,7 @@ class Report < ApplicationRecord
|
|||
rate_limit by: :account, family: :reports
|
||||
|
||||
belongs_to :account
|
||||
belongs_to :application, class_name: 'Doorkeeper::Application', optional: true
|
||||
|
||||
with_options class_name: 'Account' do
|
||||
belongs_to :target_account
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue