Add fallback attributes to notifications for new and infrequent notifications (#38832)
This commit is contained in:
parent
afeb63d287
commit
5b395774c0
@ -16,7 +16,7 @@ class Api::V1::NotificationsController < Api::BaseController
|
||||
@relationships = StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id)
|
||||
end
|
||||
|
||||
render json: @notifications, each_serializer: REST::NotificationSerializer, relationships: @relationships
|
||||
render json: @notifications, each_serializer: REST::NotificationSerializer, relationships: @relationships, supported_notification_types: params[:supported_types]
|
||||
end
|
||||
|
||||
def unread_count
|
||||
@ -29,7 +29,7 @@ class Api::V1::NotificationsController < Api::BaseController
|
||||
|
||||
def show
|
||||
@notification = current_account.notifications.without_suspended.find(params[:id])
|
||||
render json: @notification, serializer: REST::NotificationSerializer
|
||||
render json: @notification, serializer: REST::NotificationSerializer, supported_notification_types: params[:supported_types]
|
||||
end
|
||||
|
||||
def clear
|
||||
@ -89,6 +89,8 @@ class Api::V1::NotificationsController < Api::BaseController
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit, :account_id, :types, :exclude_types, :include_filtered).permit(:limit, :account_id, :include_filtered, types: [], exclude_types: []).merge(core_params)
|
||||
params.slice(:limit, :account_id, :types, :exclude_types, :include_filtered, :supported_types)
|
||||
.permit(:limit, :account_id, :include_filtered, types: [], exclude_types: [], supported_types: [])
|
||||
.merge(core_params)
|
||||
end
|
||||
end
|
||||
|
||||
@ -33,7 +33,7 @@ class Api::V2::NotificationsController < Api::BaseController
|
||||
'app.notification_grouping.expand_accounts_param' => expand_accounts_param
|
||||
)
|
||||
|
||||
render json: @presenter, serializer: REST::DedupNotificationGroupSerializer, relationships: @relationships, expand_accounts: expand_accounts_param
|
||||
render json: @presenter, serializer: REST::DedupNotificationGroupSerializer, relationships: @relationships, expand_accounts: expand_accounts_param, supported_notification_types: params[:supported_types]
|
||||
end
|
||||
end
|
||||
|
||||
@ -48,7 +48,7 @@ class Api::V2::NotificationsController < Api::BaseController
|
||||
def show
|
||||
@notification = current_account.notifications.without_suspended.by_group_key(params[:group_key]).take!
|
||||
presenter = GroupedNotificationsPresenter.new(NotificationGroup.from_notifications([@notification]))
|
||||
render json: presenter, serializer: REST::DedupNotificationGroupSerializer
|
||||
render json: presenter, serializer: REST::DedupNotificationGroupSerializer, supported_notification_types: params[:supported_types]
|
||||
end
|
||||
|
||||
def clear
|
||||
@ -138,7 +138,9 @@ class Api::V2::NotificationsController < Api::BaseController
|
||||
end
|
||||
|
||||
def pagination_params(core_params)
|
||||
params.slice(:limit, :include_filtered, :types, :exclude_types, :grouped_types).permit(:limit, :include_filtered, types: [], exclude_types: [], grouped_types: []).merge(core_params)
|
||||
params.slice(:limit, :include_filtered, :types, :exclude_types, :grouped_types, :supported_types)
|
||||
.permit(:limit, :include_filtered, types: [], exclude_types: [], grouped_types: [], supported_types: [])
|
||||
.merge(core_params)
|
||||
end
|
||||
|
||||
def expand_accounts_param
|
||||
|
||||
@ -76,6 +76,15 @@ class TextFormatter
|
||||
rescue Addressable::URI::InvalidURIError, IDN::Idna::IdnaError
|
||||
h(url)
|
||||
end
|
||||
|
||||
def link_to_mention(account, with_domain: false)
|
||||
url = ActivityPub::TagManager.instance.url_for(account)
|
||||
display_username = with_domain ? account.pretty_acct : account.username
|
||||
|
||||
<<~HTML.squish
|
||||
<span class="h-card" translate="no"><a href="#{h(url)}" class="u-url mention">@<span>#{h(display_username)}</span></a></span>
|
||||
HTML
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
@ -136,12 +145,7 @@ class TextFormatter
|
||||
|
||||
return "@#{h(entity[:screen_name])}" if account.nil?
|
||||
|
||||
url = ActivityPub::TagManager.instance.url_for(account)
|
||||
display_username = same_username_hits&.positive? || with_domains? ? account.pretty_acct : account.username
|
||||
|
||||
<<~HTML.squish
|
||||
<span class="h-card" translate="no"><a href="#{h(url)}" class="u-url mention">@<span>#{h(display_username)}</span></a></span>
|
||||
HTML
|
||||
TextFormatter.link_to_mention(account, with_domain: same_username_hits&.positive? || with_domains?)
|
||||
end
|
||||
|
||||
def entity_cache
|
||||
|
||||
@ -37,54 +37,71 @@ class Notification < ApplicationRecord
|
||||
PROPERTIES = {
|
||||
mention: {
|
||||
filterable: true,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
status: {
|
||||
filterable: false,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
reblog: {
|
||||
filterable: true,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
follow: {
|
||||
filterable: true,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
follow_request: {
|
||||
filterable: true,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
favourite: {
|
||||
filterable: true,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
poll: {
|
||||
filterable: false,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
update: {
|
||||
filterable: false,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
severed_relationships: {
|
||||
filterable: false,
|
||||
baseline: false,
|
||||
}.freeze,
|
||||
moderation_warning: {
|
||||
filterable: false,
|
||||
baseline: false,
|
||||
}.freeze,
|
||||
annual_report: {
|
||||
filterable: false,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
'admin.sign_up': {
|
||||
filterable: false,
|
||||
baseline: false,
|
||||
}.freeze,
|
||||
'admin.report': {
|
||||
filterable: false,
|
||||
baseline: false,
|
||||
}.freeze,
|
||||
quote: {
|
||||
filterable: true,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
quoted_update: {
|
||||
filterable: false,
|
||||
baseline: true,
|
||||
}.freeze,
|
||||
added_to_collection: {
|
||||
filterable: true,
|
||||
baseline: false,
|
||||
}.freeze,
|
||||
collection_update: {
|
||||
filterable: false,
|
||||
baseline: false,
|
||||
}.freeze,
|
||||
}.freeze
|
||||
|
||||
|
||||
96
app/serializers/concerns/notification_fallback_concern.rb
Normal file
96
app/serializers/concerns/notification_fallback_concern.rb
Normal file
@ -0,0 +1,96 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module NotificationFallbackConcern
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def fallback
|
||||
{
|
||||
title: fallback_title,
|
||||
summary: fallback_summary,
|
||||
description: nil,
|
||||
}
|
||||
end
|
||||
|
||||
def needs_fallback?
|
||||
return false if instance_options[:supported_notification_types].nil?
|
||||
return false if Notification::PROPERTIES.dig(object.type, :baseline) || instance_options[:supported_notification_types].include?(object.type.to_s)
|
||||
|
||||
# In rare cases, a notification might be missing its activity, in which case we can't do much
|
||||
case object.type
|
||||
when :severed_relationships
|
||||
object.account_relationship_severance_event.present?
|
||||
when :'admin.report'
|
||||
object.report.present?
|
||||
when :added_to_collection, :collection_update
|
||||
object.target_collection.present?
|
||||
else
|
||||
true
|
||||
end
|
||||
end
|
||||
|
||||
def fallback_title
|
||||
account = object.is_a?(NotificationGroup) ? object.sample_accounts.first : object.from_account
|
||||
|
||||
case object.type
|
||||
when :severed_relationships
|
||||
I18n.t(
|
||||
'notification_fallbacks.severed_relationships.title',
|
||||
name: object.account_relationship_severance_event.target_name
|
||||
)
|
||||
when :moderation_warning
|
||||
I18n.t('notification_fallbacks.moderation_warning.title')
|
||||
when :'admin.sign_up'
|
||||
count = object.is_a?(NotificationGroup) ? object.sample_accounts.count : 1
|
||||
if count > 1
|
||||
I18n.t(
|
||||
'notification_fallbacks.admin_sign_up.title_and_others_html',
|
||||
name: TextFormatter.link_to_mention(account),
|
||||
count: count - 1
|
||||
)
|
||||
else
|
||||
I18n.t(
|
||||
'notification_fallbacks.admin_sign_up.title_html',
|
||||
name: TextFormatter.link_to_mention(account)
|
||||
)
|
||||
end
|
||||
when :'admin.report'
|
||||
I18n.t(
|
||||
'notification_fallbacks.admin_report.title_html',
|
||||
name: account.remote? ? account.domain : TextFormatter.link_to_mention(account),
|
||||
target: TextFormatter.link_to_mention(object.report.target_account)
|
||||
)
|
||||
when :added_to_collection
|
||||
I18n.t(
|
||||
'notification_fallbacks.added_to_collection.title_html',
|
||||
name: TextFormatter.link_to_mention(account)
|
||||
)
|
||||
when :collection_update
|
||||
I18n.t(
|
||||
'notification_fallbacks.collection_update.title_html',
|
||||
name: account
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
def fallback_summary
|
||||
case object.type
|
||||
when :severed_relationships
|
||||
I18n.t(
|
||||
'notification_fallbacks.severed_relationships.summary_html',
|
||||
from: Rails.configuration.x.local_domain,
|
||||
target: object.account_relationship_severance_event.target_name,
|
||||
link: link_to(I18n.t('notification_fallbacks.generic.sign_in'), severed_relationships_url)
|
||||
)
|
||||
when :moderation_warning
|
||||
I18n.t(
|
||||
'notification_fallbacks.moderation_warning.summary_html',
|
||||
link: link_to(I18n.t('notification_fallbacks.generic.sign_in'), disputes_strike_url(object.account_warning.id))
|
||||
)
|
||||
when :'admin.sign_up', :'admin.report', :added_to_collection, :collection_update
|
||||
I18n.t(
|
||||
'notification_fallbacks.generic.summary_html',
|
||||
link: link_to(I18n.t('notification_fallbacks.generic.sign_in'), root_url)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -1,6 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class REST::NotificationGroupSerializer < ActiveModel::Serializer
|
||||
include RoutingHelper
|
||||
include ActionView::Helpers::UrlHelper
|
||||
include NotificationFallbackConcern
|
||||
|
||||
# Please update app/javascript/mastodon/api_types/notifications.ts when making changes to the attributes
|
||||
attributes :group_key, :notifications_count, :type, :most_recent_notification_id
|
||||
|
||||
@ -8,6 +12,8 @@ class REST::NotificationGroupSerializer < ActiveModel::Serializer
|
||||
attribute :page_max_id, if: :paginated?
|
||||
attribute :latest_page_notification_at, if: :paginated?
|
||||
|
||||
attribute :fallback, if: :needs_fallback?
|
||||
|
||||
attribute :sample_account_ids
|
||||
attribute :status_id, if: :status_type?
|
||||
belongs_to :report, if: :report_type?, serializer: REST::ReportSerializer
|
||||
|
||||
@ -1,11 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class REST::NotificationSerializer < ActiveModel::Serializer
|
||||
include RoutingHelper
|
||||
include ActionView::Helpers::UrlHelper
|
||||
include NotificationFallbackConcern
|
||||
|
||||
# Please update app/javascript/mastodon/api_types/notifications.ts when making changes to the attributes
|
||||
attributes :id, :type, :created_at, :group_key
|
||||
|
||||
attribute :filtered, if: :filtered?
|
||||
|
||||
attribute :fallback, if: :needs_fallback?
|
||||
|
||||
belongs_to :from_account, key: :account, serializer: REST::AccountSerializer
|
||||
belongs_to :target_status, key: :status, if: :status_type?, serializer: REST::StatusSerializer
|
||||
belongs_to :report, if: :report_type?, serializer: REST::ReportSerializer
|
||||
|
||||
@ -1731,6 +1731,27 @@ en:
|
||||
copy_account_note_text: 'This user moved from %{acct}, here were your previous notes about them:'
|
||||
navigation:
|
||||
toggle_menu: Toggle menu
|
||||
notification_fallbacks:
|
||||
added_to_collection:
|
||||
title_html: "%{name} added you to a collection"
|
||||
admin_report:
|
||||
title_html: "%{name} reported %{target}"
|
||||
admin_sign_up:
|
||||
title_and_others_html:
|
||||
one: "%{name} and one other signed up"
|
||||
other: "%{name} and %{count} others signed up"
|
||||
title_html: "%{name} signed up"
|
||||
collection_update:
|
||||
title_html: "%{name} updated a collection you are in"
|
||||
generic:
|
||||
sign_in: Sign in to the Mastodon web app
|
||||
summary_html: You're on an app that does not support the most recent version of Mastodon. %link for full functionality.
|
||||
moderation_warning:
|
||||
summary_html: You're on an app that does not support the most recent version of Mastodon. %link
|
||||
title: You have received a moderation warning.
|
||||
severed_relationships:
|
||||
summary_html: An admin from %{from} has suspended %{target}, which means you can no longer receive updates from them or interact with them. %{link} to retrieve a list of the lost relationships.
|
||||
title: Lost connections with %{name}
|
||||
notification_mailer:
|
||||
admin:
|
||||
report:
|
||||
|
||||
@ -6,10 +6,16 @@ RSpec.describe REST::NotificationGroupSerializer do
|
||||
subject do
|
||||
serialized_record_json(
|
||||
notification_group,
|
||||
described_class
|
||||
described_class,
|
||||
options: {
|
||||
scope: current_user,
|
||||
scope_name: :current_user,
|
||||
supported_notification_types: [],
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
let(:current_user) { Fabricate(:user) }
|
||||
let(:notification_group) { NotificationGroup.new pagination_data: { latest_notification_at: 3.days.ago }, notification: Fabricate(:notification), sample_accounts: [] }
|
||||
|
||||
context 'when latest_page_notification_at is populated' do
|
||||
@ -20,4 +26,28 @@ RSpec.describe REST::NotificationGroupSerializer do
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'with fallback notifications' do |type, fabricators|
|
||||
let(:activities) { fabricators.map { |fabricator| Fabricate(fabricator) } }
|
||||
let(:notifications) { activities.map { |activity| Fabricate(:notification, type:, activity:, account: current_user.account) } }
|
||||
let(:notification_group) { NotificationGroup.new(notification: notifications.last, sample_accounts: notifications.map(&:from_account)) }
|
||||
|
||||
it 'renders correctly' do
|
||||
expect(subject)
|
||||
.to include(
|
||||
'type' => type,
|
||||
'fallback' => include(
|
||||
'title' => anything,
|
||||
'summary' => anything
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'with fallback notifications', 'severed_relationships', [:account_relationship_severance_event]
|
||||
it_behaves_like 'with fallback notifications', 'moderation_warning', [:account_warning]
|
||||
it_behaves_like 'with fallback notifications', 'admin.report', [:report]
|
||||
it_behaves_like 'with fallback notifications', 'admin.report', [:report, :report]
|
||||
it_behaves_like 'with fallback notifications', 'added_to_collection', [:collection_item]
|
||||
it_behaves_like 'with fallback notifications', 'collection_update', [:collection]
|
||||
end
|
||||
|
||||
@ -6,10 +6,16 @@ RSpec.describe REST::NotificationSerializer do
|
||||
subject do
|
||||
serialized_record_json(
|
||||
notification,
|
||||
described_class
|
||||
described_class,
|
||||
options: {
|
||||
scope: current_user,
|
||||
scope_name: :current_user,
|
||||
supported_notification_types: [],
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
let(:current_user) { Fabricate(:user) }
|
||||
let(:notification) { Fabricate :notification }
|
||||
|
||||
context 'when created_at is populated' do
|
||||
@ -20,4 +26,25 @@ RSpec.describe REST::NotificationSerializer do
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'with fallback notifications' do |type, fabricator|
|
||||
let(:notification) { Fabricate(:notification, type:, activity: Fabricate(fabricator), account: current_user.account) }
|
||||
|
||||
it 'renders correctly' do
|
||||
expect(subject)
|
||||
.to include(
|
||||
'type' => type,
|
||||
'fallback' => include(
|
||||
'title' => anything,
|
||||
'summary' => anything
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'with fallback notifications', 'severed_relationships', :account_relationship_severance_event
|
||||
it_behaves_like 'with fallback notifications', 'moderation_warning', :account_warning
|
||||
it_behaves_like 'with fallback notifications', 'admin.report', :report
|
||||
it_behaves_like 'with fallback notifications', 'added_to_collection', :collection_item
|
||||
it_behaves_like 'with fallback notifications', 'collection_update', :collection
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user