Merge remote-tracking branch 'parent/main' into upstream-20240604

This commit is contained in:
KMY 2024-06-04 08:02:05 +09:00
commit 8927b1444b
89 changed files with 1132 additions and 458 deletions

View file

@ -60,8 +60,4 @@ class Api::V1::Accounts::FollowerAccountsController < Api::BaseController
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -60,8 +60,4 @@ class Api::V1::Accounts::FollowingAccountsController < Api::BaseController
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -16,8 +16,6 @@ class Api::V1::Admin::CanonicalEmailBlocksController < Api::BaseController
after_action :verify_authorized
after_action :insert_pagination_headers, only: :index
PAGINATION_PARAMS = %i(limit).freeze
def index
authorize :canonical_email_block, :index?
render json: @canonical_email_blocks, each_serializer: REST::Admin::CanonicalEmailBlockSerializer
@ -80,8 +78,4 @@ class Api::V1::Admin::CanonicalEmailBlocksController < Api::BaseController
def records_continue?
@canonical_email_blocks.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
end
end

View file

@ -14,8 +14,6 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController
after_action :verify_authorized
after_action :insert_pagination_headers, only: :index
PAGINATION_PARAMS = %i(limit).freeze
def index
authorize :domain_allow, :index?
render json: @domain_allows, each_serializer: REST::Admin::DomainAllowSerializer
@ -77,10 +75,6 @@ class Api::V1::Admin::DomainAllowsController < Api::BaseController
@domain_allows.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
end
def resource_params
params.permit(:domain)
end

View file

@ -14,8 +14,6 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
after_action :verify_authorized
after_action :insert_pagination_headers, only: :index
PAGINATION_PARAMS = %i(limit).freeze
def index
authorize :domain_block, :index?
render json: @domain_blocks, each_serializer: REST::Admin::DomainBlockSerializer
@ -94,10 +92,6 @@ class Api::V1::Admin::DomainBlocksController < Api::BaseController
@domain_blocks.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
end
def resource_params
params.permit(:domain, :severity, :reject_media, :reject_favourite, :reject_reply_exclude_followers, :reject_send_sensitive, :reject_hashtag, :reject_straight_follow,
:reject_new_follow, :reject_friend, :block_trends, :detect_invalid_subscription, :reject_reports, :private_comment, :public_comment, :obfuscate, :hidden)

View file

@ -14,10 +14,6 @@ class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController
after_action :verify_authorized
after_action :insert_pagination_headers, only: :index
PAGINATION_PARAMS = %i(
limit
).freeze
def index
authorize :email_domain_block, :index?
render json: @email_domain_blocks, each_serializer: REST::Admin::EmailDomainBlockSerializer
@ -73,8 +69,4 @@ class Api::V1::Admin::EmailDomainBlocksController < Api::BaseController
def records_continue?
@email_domain_blocks.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
end
end

View file

@ -14,10 +14,6 @@ class Api::V1::Admin::IpBlocksController < Api::BaseController
after_action :verify_authorized
after_action :insert_pagination_headers, only: :index
PAGINATION_PARAMS = %i(
limit
).freeze
def index
authorize :ip_block, :index?
render json: @ip_blocks, each_serializer: REST::Admin::IpBlockSerializer
@ -78,8 +74,4 @@ class Api::V1::Admin::IpBlocksController < Api::BaseController
def records_continue?
@ip_blocks.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
end
end

View file

@ -12,7 +12,6 @@ class Api::V1::Admin::TagsController < Api::BaseController
after_action :verify_authorized
LIMIT = 100
PAGINATION_PARAMS = %i(limit).freeze
def index
authorize :tag, :index?
@ -59,8 +58,4 @@ class Api::V1::Admin::TagsController < Api::BaseController
def records_continue?
@tags.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
end
end

View file

@ -12,8 +12,6 @@ class Api::V1::Admin::Trends::Links::PreviewCardProvidersController < Api::BaseC
after_action :verify_authorized
after_action :insert_pagination_headers, only: :index
PAGINATION_PARAMS = %i(limit).freeze
def index
authorize :preview_card_provider, :index?
@ -57,8 +55,4 @@ class Api::V1::Admin::Trends::Links::PreviewCardProvidersController < Api::BaseC
def records_continue?
@providers.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(*PAGINATION_PARAMS).permit(*PAGINATION_PARAMS).merge(core_params)
end
end

View file

@ -43,8 +43,4 @@ class Api::V1::BlocksController < Api::BaseController
def records_continue?
paginated_blocks.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -48,8 +48,4 @@ class Api::V1::BookmarksController < Api::BaseController
def records_continue?
results.size == limit_param(DEFAULT_STATUSES_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -72,8 +72,4 @@ class Api::V1::ConversationsController < Api::BaseController
def records_continue?
@conversations.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -44,8 +44,4 @@ class Api::V1::Crypto::EncryptedMessagesController < Api::BaseController
def records_continue?
@encrypted_messages.size == limit_param(LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -54,10 +54,6 @@ class Api::V1::DomainBlocksController < Api::BaseController
@blocks.size == limit_param(BLOCK_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def domain_block_params
params.permit(:domain)
end

View file

@ -48,10 +48,6 @@ class Api::V1::EndorsementsController < Api::BaseController
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def unlimited?
params[:limit] == '0'
end

View file

@ -48,8 +48,4 @@ class Api::V1::FavouritesController < Api::BaseController
def records_continue?
results.size == limit_param(DEFAULT_STATUSES_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -67,8 +67,4 @@ class Api::V1::FollowRequestsController < Api::BaseController
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -37,8 +37,4 @@ class Api::V1::FollowedTagsController < Api::BaseController
def records_continue?
@results.size == limit_param(TAGS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -5,7 +5,7 @@ class Api::V1::Instances::ExtendedDescriptionsController < Api::V1::Instances::B
before_action :set_extended_description
# Override `current_user` to avoid reading session cookies unless in whitelist mode
# Override `current_user` to avoid reading session cookies unless in limited federation mode
def current_user
super if limited_federation_mode?
end

View file

@ -5,7 +5,7 @@ class Api::V1::Instances::PeersController < Api::V1::Instances::BaseController
skip_around_action :set_locale
# Override `current_user` to avoid reading session cookies unless in whitelist mode
# Override `current_user` to avoid reading session cookies unless in limited federation mode
def current_user
super if limited_federation_mode?
end

View file

@ -5,7 +5,7 @@ class Api::V1::Instances::RulesController < Api::V1::Instances::BaseController
before_action :set_rules
# Override `current_user` to avoid reading session cookies unless in whitelist mode
# Override `current_user` to avoid reading session cookies unless in limited federation mode
def current_user
super if limited_federation_mode?
end

View file

@ -6,7 +6,7 @@ class Api::V1::InstancesController < Api::BaseController
vary_by ''
# Override `current_user` to avoid reading session cookies unless in whitelist mode
# Override `current_user` to avoid reading session cookies unless in limited federation mode
def current_user
super if limited_federation_mode?
end

View file

@ -75,10 +75,6 @@ class Api::V1::Lists::AccountsController < Api::BaseController
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def unlimited?
params[:limit] == '0'
end

View file

@ -43,8 +43,4 @@ class Api::V1::MutesController < Api::BaseController
def records_continue?
paginated_mutes.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -43,10 +43,6 @@ class Api::V1::ScheduledStatusesController < Api::BaseController
params.permit(:scheduled_at)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def next_path
api_v1_scheduled_statuses_url pagination_params(max_id: pagination_max_id) if records_continue?
end

View file

@ -53,8 +53,4 @@ class Api::V1::Statuses::FavouritedByAccountsController < Api::V1::Statuses::Bas
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -49,8 +49,4 @@ class Api::V1::Statuses::RebloggedByAccountsController < Api::V1::Statuses::Base
def records_continue?
@accounts.size == limit_param(DEFAULT_ACCOUNTS_LIMIT)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -207,8 +207,4 @@ class Api::V1::StatusesController < Api::BaseController
def serialized_accounts(accounts)
ActiveModel::Serializer::CollectionSerializer.new(accounts, serializer: REST::AccountSerializer)
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
end

View file

@ -34,10 +34,6 @@ class Api::V1::Trends::LinksController < Api::BaseController
scope
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def next_path
api_v1_trends_links_url pagination_params(offset: offset_param + limit_param(DEFAULT_LINKS_LIMIT)) if records_continue?
end

View file

@ -32,10 +32,6 @@ class Api::V1::Trends::StatusesController < Api::BaseController
scope
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def next_path
api_v1_trends_statuses_url pagination_params(offset: offset_param + limit_param(DEFAULT_STATUSES_LIMIT)) if records_continue?
end

View file

@ -30,10 +30,6 @@ class Api::V1::Trends::TagsController < Api::BaseController
Trends.tags.query.allowed
end
def pagination_params(core_params)
params.slice(:limit).permit(:limit).merge(core_params)
end
def next_path
api_v1_trends_tags_url pagination_params(offset: offset_param + limit_param(DEFAULT_TAGS_LIMIT)) if records_continue?
end

View file

@ -0,0 +1,91 @@
# frozen_string_literal: true
class Api::V2Alpha::NotificationsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, except: [:clear, :dismiss]
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, only: [:clear, :dismiss]
before_action :require_user!
after_action :insert_pagination_headers, only: :index
DEFAULT_NOTIFICATIONS_LIMIT = 40
def index
with_read_replica do
@notifications = load_notifications
@group_metadata = load_group_metadata
@relationships = StatusRelationshipsPresenter.new(target_statuses_from_notifications, current_user&.account_id)
end
render json: @notifications.map { |notification| NotificationGroup.from_notification(notification) }, each_serializer: REST::NotificationGroupSerializer, relationships: @relationships, group_metadata: @group_metadata
end
def show
@notification = current_account.notifications.without_suspended.find_by!(group_key: params[:id])
render json: NotificationGroup.from_notification(@notification), serializer: REST::NotificationGroupSerializer
end
def clear
current_account.notifications.delete_all
render_empty
end
def dismiss
current_account.notifications.where(group_key: params[:id]).destroy_all
render_empty
end
private
def load_notifications
notifications = browserable_account_notifications.includes(from_account: [:account_stat, :user]).to_a_grouped_paginated_by_id(
limit_param(DEFAULT_NOTIFICATIONS_LIMIT),
params_slice(:max_id, :since_id, :min_id)
)
Notification.preload_cache_collection_target_statuses(notifications) do |target_statuses|
preload_collection(target_statuses, Status)
end
end
def load_group_metadata
return {} if @notifications.empty?
browserable_account_notifications
.where(group_key: @notifications.filter_map(&:group_key))
.where(id: (@notifications.last.id)..(@notifications.first.id))
.group(:group_key)
.pluck(:group_key, 'min(notifications.id) as min_id', 'max(notifications.id) as max_id', 'max(notifications.created_at) as latest_notification_at')
.to_h { |group_key, min_id, max_id, latest_notification_at| [group_key, { min_id: min_id, max_id: max_id, latest_notification_at: latest_notification_at }] }
end
def browserable_account_notifications
current_account.notifications.without_suspended.browserable(
types: Array(browserable_params[:types]),
exclude_types: Array(browserable_params[:exclude_types]),
include_filtered: truthy_param?(:include_filtered)
)
end
def target_statuses_from_notifications
@notifications.filter_map(&:target_status)
end
def next_path
api_v2_alpha_notifications_url pagination_params(max_id: pagination_max_id) unless @notifications.empty?
end
def prev_path
api_v2_alpha_notifications_url pagination_params(min_id: pagination_since_id) unless @notifications.empty?
end
def pagination_collection
@notifications
end
def browserable_params
params.permit(:include_filtered, types: [], exclude_types: [])
end
def pagination_params(core_params)
params.slice(:limit, :types, :exclude_types, :include_filtered).permit(:limit, :include_filtered, types: [], exclude_types: []).merge(core_params)
end
end

View file

@ -3,6 +3,8 @@
module Api::Pagination
extend ActiveSupport::Concern
PAGINATION_PARAMS = %i(limit).freeze
protected
def pagination_max_id
@ -24,6 +26,13 @@ module Api::Pagination
render json: { error: 'Pagination values for `offset` and `limit` must be positive' }, status: 400 if pagination_options_invalid?
end
def pagination_params(core_params)
params
.slice(*PAGINATION_PARAMS)
.permit(*PAGINATION_PARAMS)
.merge(core_params)
end
private
def insert_pagination_headers

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Показване на профила въпреки това",
"limited_account_hint.title": "Този профил е бил скрит от модераторите на {domain}.",
"link_preview.author": "От {name}",
"link_preview.more_from_author": "Още от {name}",
"lists.account.add": "Добавяне към списък",
"lists.account.remove": "Премахване от списъка",
"lists.delete": "Изтриване на списъка",

View file

@ -221,6 +221,8 @@
"domain_pill.activitypub_like_language": "ActivityPub er \"sproget\", Mastodon taler med andre sociale netværk.",
"domain_pill.server": "Server",
"domain_pill.their_handle": "Vedkommendes handle:",
"domain_pill.their_server": "Det digitale hjem, hvor alle indlæggene findes.",
"domain_pill.their_username": "Entydig identifikator på denne server. Det er muligt at finde brugere med samme brugernavn på forskellige servere.",
"domain_pill.username": "Brugernavn",
"domain_pill.whats_in_a_handle": "Hvad er der i et handle (@brugernavn)?",
"domain_pill.who_they_are": "Da et handle fortæller, hvem nogen er, og hvor de er, kan man interagere med folk på tværs af det sociale net af <button>ActivityPub-drevne platforme</button>.",
@ -412,6 +414,7 @@
"limited_account_hint.action": "Vis profil alligevel",
"limited_account_hint.title": "Denne profil er blevet skjult af {domain}-moderatorerne.",
"link_preview.author": "Af {name}",
"link_preview.more_from_author": "Mere fra {name}",
"lists.account.add": "Føj til liste",
"lists.account.remove": "Fjern fra liste",
"lists.delete": "Slet liste",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Profil trotzdem anzeigen",
"limited_account_hint.title": "Dieses Profil wurde von den Moderator*innen von {domain} ausgeblendet.",
"link_preview.author": "Von {name}",
"link_preview.more_from_author": "Mehr von {name}",
"lists.account.add": "Zur Liste hinzufügen",
"lists.account.remove": "Von der Liste entfernen",
"lists.delete": "Liste löschen",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Mostrar perfil de todos modos",
"limited_account_hint.title": "Este perfil ha sido ocultado por los moderadores de {domain}.",
"link_preview.author": "Por {name}",
"link_preview.more_from_author": "Más de {name}",
"lists.account.add": "Añadir a lista",
"lists.account.remove": "Quitar de lista",
"lists.delete": "Borrar lista",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Mostrar perfil de todos modos",
"limited_account_hint.title": "Este perfil ha sido ocultado por los moderadores de {domain}.",
"link_preview.author": "Por {name}",
"link_preview.more_from_author": "Más de {name}",
"lists.account.add": "Añadir a lista",
"lists.account.remove": "Quitar de lista",
"lists.delete": "Borrar lista",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Vís vangamynd kortini",
"limited_account_hint.title": "Hesin vangin er fjaldur av kjakleiðarunum á {domain}.",
"link_preview.author": "Av {name}",
"link_preview.more_from_author": "Meira frá {name}",
"lists.account.add": "Legg afturat lista",
"lists.account.remove": "Tak av lista",
"lists.delete": "Strika lista",

View file

@ -89,9 +89,12 @@
"announcement.announcement": "Oankundiging",
"attachments_list.unprocessed": "(net ferwurke)",
"audio.hide": "Audio ferstopje",
"block_modal.remote_users_caveat": "Wy freegje de server {domain} om jo beslút te respektearjen. It neilibben hjirfan is echter net garandearre, omdat guon servers blokkaden oars ynterpretearje kinne. Iepenbiere berjochten binne mooglik noch hieltyd sichtber foar net-oanmelde brûkers.",
"block_modal.show_less": "Minder toane",
"block_modal.show_more": "Mear toane",
"block_modal.they_cant_mention": "Sy kinne jo net fermelde of folgje.",
"block_modal.they_cant_see_posts": "De persoan kin jo berjochten net sjen en jo ek net harren berjochten.",
"block_modal.they_will_know": "De persoan kin sjen dat dy blokkearre wurdt.",
"block_modal.title": "Brûker blokkearje?",
"block_modal.you_wont_see_mentions": "Jo sjogge gjin berjochten mear dyt dizze account fermelde.",
"boost_modal.combo": "Jo kinne op {combo} drukke om dit de folgjende kear oer te slaan",
@ -214,11 +217,15 @@
"domain_block_modal.title": "Domein blokkearje?",
"domain_block_modal.you_will_lose_followers": "Al jo folgers fan dizze server wurde ûntfolge.",
"domain_block_modal.you_wont_see_posts": "Jo sjogge gjin berjochten of meldingen mear fan brûkers op dizze server.",
"domain_pill.activitypub_lets_connect": "It soarget derfoar dat jo net allinnich mar ferbine en kommunisearje kinne mei minsken op Mastodon, mar ek mei oare sosjale apps.",
"domain_pill.activitypub_like_language": "ActivityPub is de taal dyt Mastodon mei oare sosjale netwurken sprekt.",
"domain_pill.server": "Server",
"domain_pill.their_handle": "Harren fediverse-adres:",
"domain_pill.their_server": "Harren digitale thús, wert al harren berjochten binne.",
"domain_pill.their_username": "Harren unike identifikaasje-adres op harren server. It is mooglik dat der brûkers mei deselde brûkersnamme op ferskate servers te finen binne.",
"domain_pill.username": "Brûkersnamme",
"domain_pill.whats_in_a_handle": "Wat is in fediverse-adres?",
"domain_pill.who_they_are": "Omdat jo oan in fediverse-adres sjen kinne hoet ien hjit en op hokker server dy sit, kinne jo mei minsken op it troch <button>ActivityPub oandreaune</button> sosjale web (fediverse) kommunisearje.",
"domain_pill.your_handle": "Jo fediverse-adres:",
"embed.instructions": "Embed this status on your website by copying the code below.",
"embed.preview": "Sa komt it der út te sjen:",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "הצג חשבון בכל זאת",
"limited_account_hint.title": "פרופיל המשתמש הזה הוסתר על ידי המנחים של {domain}.",
"link_preview.author": "מאת {name}",
"link_preview.more_from_author": "עוד מאת {name}",
"lists.account.add": "הוסף לרשימה",
"lists.account.remove": "הסר מרשימה",
"lists.delete": "מחיקת רשימה",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Profil megjelenítése mindenképpen",
"limited_account_hint.title": "Ezt a profilt {domain} moderátorai elrejtették.",
"link_preview.author": "{name} szerint",
"link_preview.more_from_author": "Több tőle: {name}",
"lists.account.add": "Hozzáadás a listához",
"lists.account.remove": "Eltávolítás a listából",
"lists.delete": "Lista törlése",

View file

@ -215,8 +215,8 @@
"domain_block_modal.they_cant_follow": "Necuno de iste servitor pote sequer te.",
"domain_block_modal.they_wont_know": "Ille non sapera que ille ha essite blocate.",
"domain_block_modal.title": "Blocar dominio?",
"domain_block_modal.you_will_lose_followers": "Omne sequitores ab iste servitor essera removite.",
"domain_block_modal.you_wont_see_posts": "Tu non videra messages e notificationes ab usatores sur iste servitor.",
"domain_block_modal.you_will_lose_followers": "Tote tu sequitores de iste servitor essera removite.",
"domain_block_modal.you_wont_see_posts": "Tu non videra messages e notificationes de usatores sur iste servitor.",
"domain_pill.activitypub_lets_connect": "Illo te permitte connecter e interager con personas non solmente sur Mastodon, ma tamben sur altere applicationes social.",
"domain_pill.activitypub_like_language": "ActivityPub es como le linguage commun que Mastodon parla con altere retes social.",
"domain_pill.server": "Servitor",
@ -389,7 +389,7 @@
"keyboard_shortcuts.hotkey": "Clave accelerator",
"keyboard_shortcuts.legend": "Monstrar iste legenda",
"keyboard_shortcuts.local": "Aperir le chronologia local",
"keyboard_shortcuts.mention": "Mentionar le author",
"keyboard_shortcuts.mention": "Mentionar le autor",
"keyboard_shortcuts.muted": "Aperir lista de usatores silentiate",
"keyboard_shortcuts.my_profile": "Aperir tu profilo",
"keyboard_shortcuts.notifications": "Aperir columna de notificationes",
@ -414,6 +414,7 @@
"limited_account_hint.action": "Monstrar profilo in omne caso",
"limited_account_hint.title": "Iste profilo ha essite celate per le moderatores de {domain}.",
"link_preview.author": "Per {name}",
"link_preview.more_from_author": "Plus de {name}",
"lists.account.add": "Adder al lista",
"lists.account.remove": "Remover del lista",
"lists.delete": "Deler lista",
@ -474,7 +475,7 @@
"notification.follow_request": "{name} ha requestate de sequer te",
"notification.mention": "{name} te ha mentionate",
"notification.moderation-warning.learn_more": "Apprender plus",
"notification.moderation_warning": "Tu ha recepite un aviso de moderation",
"notification.moderation_warning": "Tu ha recipite un advertimento de moderation",
"notification.moderation_warning.action_delete_statuses": "Alcunes de tu messages ha essite removite.",
"notification.moderation_warning.action_disable": "Tu conto ha essite disactivate.",
"notification.moderation_warning.action_mark_statuses_as_sensitive": "Alcunes de tu messages ha essite marcate como sensibile.",
@ -493,7 +494,7 @@
"notification.status": "{name} ha justo ora publicate",
"notification.update": "{name} ha modificate un message",
"notification_requests.accept": "Acceptar",
"notification_requests.dismiss": "Dimitter",
"notification_requests.dismiss": "Clauder",
"notification_requests.notifications_from": "Notificationes de {name}",
"notification_requests.title": "Notificationes filtrate",
"notifications.clear": "Rader notificationes",
@ -621,7 +622,7 @@
"relative_time.today": "hodie",
"reply_indicator.attachments": "{count, plural, one {# annexo} other {# annexos}}",
"reply_indicator.cancel": "Cancellar",
"reply_indicator.poll": "Inquesta",
"reply_indicator.poll": "Sondage",
"report.block": "Blocar",
"report.block_explanation": "Tu non videra le messages de iste persona. Ille non potera vider tu messages o sequer te. Ille potera saper de esser blocate.",
"report.categories.legal": "Juridic",
@ -677,7 +678,7 @@
"search.quick_action.status_search": "Messages correspondente a {x}",
"search.search_or_paste": "Cerca o colla un URL",
"search_popout.full_text_search_disabled_message": "Non disponibile sur {domain}.",
"search_popout.full_text_search_logged_out_message": "Solmente disponibile al initiar le session.",
"search_popout.full_text_search_logged_out_message": "Solmente disponibile post aperir session.",
"search_popout.language_code": "Codice de lingua ISO",
"search_popout.options": "Optiones de recerca",
"search_popout.quick_actions": "Actiones rapide",
@ -757,7 +758,7 @@
"status.show_original": "Monstrar original",
"status.title.with_attachments": "{user} ha publicate {attachmentCount, plural, one {un annexo} other {{attachmentCount} annexos}}",
"status.translate": "Traducer",
"status.translated_from_with": "Traducite ab {lang} usante {provider}",
"status.translated_from_with": "Traducite de {lang} usante {provider}",
"status.uncached_media_warning": "Previsualisation non disponibile",
"status.unmute_conversation": "Non plus silentiar conversation",
"status.unpin": "Disfixar del profilo",
@ -796,7 +797,7 @@
"upload_modal.choose_image": "Seliger un imagine",
"upload_modal.description_placeholder": "Cinque expertos del zoo jam bibeva whisky frigide",
"upload_modal.detect_text": "Deteger texto de un imagine",
"upload_modal.edit_media": "Modificar le medio",
"upload_modal.edit_media": "Modificar multimedia",
"upload_modal.hint": "Clicca o trahe le circulo sur le previsualisation pro eliger le puncto focal que essera sempre visibile sur tote le miniaturas.",
"upload_modal.preparing_ocr": "Preparation del OCR…",
"upload_modal.preview_label": "Previsualisation ({ratio})",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Birta notandasniðið samt",
"limited_account_hint.title": "Þetta notandasnið hefur verið falið af umsjónarmönnum {domain}.",
"link_preview.author": "Eftir {name}",
"link_preview.more_from_author": "Meira frá {name}",
"lists.account.add": "Bæta á lista",
"lists.account.remove": "Fjarlægja af lista",
"lists.delete": "Eyða lista",

View file

@ -398,6 +398,7 @@
"limited_account_hint.action": "Amostra el profil entanto",
"limited_account_hint.title": "Este profil fue eskondido por los moderadores de {domain}.",
"link_preview.author": "Publikasyon de {name}",
"link_preview.more_from_author": "Mas de {name}",
"lists.account.add": "Adjusta a lista",
"lists.account.remove": "Kita de lista",
"lists.delete": "Efasa lista",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Vis tiek rodyti profilį",
"limited_account_hint.title": "Šį profilį paslėpė {domain} prižiūrėtojai.",
"link_preview.author": "Sukūrė {name}",
"link_preview.more_from_author": "Daugiau iš {name}",
"lists.account.add": "Pridėti į sąrašą",
"lists.account.remove": "Pašalinti iš sąrašo",
"lists.delete": "Ištrinti sąrašą",
@ -561,7 +562,7 @@
"onboarding.steps.setup_profile.title": "Suasmenink savo profilį",
"onboarding.steps.share_profile.body": "Leisk draugams sužinoti, kaip tave rasti Mastodon.",
"onboarding.steps.share_profile.title": "Bendrink savo Mastodon profilį",
"onboarding.tips.2fa": "<strong>Ar žinojai?</strong> Savo paskyrą gali apsaugoti nustatęs (-usi) dviejų veiksnių tapatybės nustatymą paskyros nustatymuose. Jis veikia su bet kuria pasirinkta TOTP programėle, telefono numeris nebūtinas.",
"onboarding.tips.2fa": "<strong>Ar žinojai?</strong> Savo paskyrą gali apsaugoti nustatant dviejų veiksnių tapatybės nustatymą paskyros nustatymuose. Jis veikia su bet kuria pasirinkta TOTP programėle, telefono numeris nebūtinas.",
"onboarding.tips.accounts_from_other_servers": "<strong>Ar žinojai?</strong> Kadangi Mastodon decentralizuotas, kai kurie profiliai, su kuriais susidursi, bus talpinami ne tavo, o kituose serveriuose. Ir vis tiek galėsi su jais sklandžiai bendrauti! Jų serveris yra antroje naudotojo vardo pusėje.",
"onboarding.tips.migration": "<strong>Ar žinojai?</strong> Jei manai, kad {domain} serveris ateityje tau netiks, gali persikelti į kitą Mastodon serverį neprarandant savo sekėjų. Gali net talpinti savo paties serverį.",
"onboarding.tips.verification": "<strong>Ar žinojai?</strong> Savo paskyrą gali patvirtinti pateikęs (-usi) nuorodą į Mastodon profilį savo interneto svetainėje ir pridėjęs (-usi) svetainę prie savo profilio. Nereikia jokių mokesčių ar dokumentų.",
@ -632,7 +633,7 @@
"report.reasons.legal_description": "Manai, kad tai pažeidžia tavo arba serverio šalies įstatymus",
"report.reasons.other": "Tai kažkas kita",
"report.reasons.other_description": "Problema netinka kitoms kategorijoms",
"report.reasons.spam": "Tai šlamštas",
"report.reasons.spam": "Tai šlamštas",
"report.reasons.spam_description": "Kenkėjiškos nuorodos, netikras įsitraukimas arba pasikartojantys atsakymai",
"report.reasons.violation": "Tai pažeidžia serverio taisykles",
"report.reasons.violation_description": "Žinai, kad tai pažeidžia konkrečias taisykles",

View file

@ -92,6 +92,8 @@
"block_modal.remote_users_caveat": "Mēs vaicāsim serverim {domain} ņemt vērā Tavu lēmumu. Tomēr atbilstība nav nodrošināta, jo atsevišķi serveri var apstrādāt bloķēšanu citādi. Publiski ieraksti joprojām var būt redzami lietotājiem, kuri nav pieteikušies.",
"block_modal.show_less": "Rādīt mazāk",
"block_modal.show_more": "Parādīt mazāk",
"block_modal.they_cant_mention": "Nevar Tevi pieminēt vai sekot Tev.",
"block_modal.they_cant_see_posts": "Nevar redzēt Tavus ierakstus, un Tu neredzēsi lietotāja.",
"boost_modal.combo": "Nospied {combo}, lai nākamreiz šo izlaistu",
"bundle_column_error.copy_stacktrace": "Kopēt kļūdu ziņojumu",
"bundle_column_error.error.body": "Pieprasīto lapu nevarēja atveidot. Tas varētu būt saistīts ar kļūdu mūsu kodā, vai tā ir pārlūkprogrammas saderības problēma.",
@ -173,7 +175,7 @@
"confirmations.discard_edit_media.message": "Ir nesaglabātas izmaiņas informācijas nesēja aprakstā vai priekšskatījumā. Vēlies tās atmest tik un tā?",
"confirmations.domain_block.message": "Vai tu tiešām vēlies bloķēt visu domēnu {domain}? Parasti pietiek, ja nobloķē vai apklusini kādu. Tu neredzēsi saturu vai paziņojumus no šī domēna nevienā laika līnijā. Tavi sekotāji no šī domēna tiks noņemti.",
"confirmations.edit.confirm": "Labot",
"confirmations.edit.message": "Rediģējot, tiks pārrakstīts ziņojums, kuru tu šobrīd raksti. Vai tiešām vēlies turpināt?",
"confirmations.edit.message": "Labošana pārrakstīs ziņojumu, kas šobrīd tiek sastādīts. Vai tiešām turpināt?",
"confirmations.logout.confirm": "Iziet",
"confirmations.logout.message": "Vai tiešām vēlies izrakstīties?",
"confirmations.mute.confirm": "Apklusināt",
@ -377,6 +379,7 @@
"limited_account_hint.action": "Tik un tā rādīt profilu",
"limited_account_hint.title": "{domain} moderatori ir paslēpuši šo profilu.",
"link_preview.author": "Pēc {name}",
"link_preview.more_from_author": "Vairāk no {name}",
"lists.account.add": "Pievienot sarakstam",
"lists.account.remove": "Noņemt no saraksta",
"lists.delete": "Izdzēst sarakstu",
@ -444,16 +447,19 @@
"notification.relationships_severance_event": "Zaudēti savienojumi ar {name}",
"notification.relationships_severance_event.learn_more": "Uzzināt vairāk",
"notification.status": "{name} tikko publicēja",
"notification.update": "{name} rediģēja ierakstu",
"notification.update": "{name} laboja ierakstu",
"notification_requests.accept": "Pieņemt",
"notification_requests.dismiss": "Noraidīt",
"notification_requests.notifications_from": "Paziņojumi no {name}",
"notification_requests.title": "Atlasītie paziņojumi",
"notifications.clear": "Notīrīt paziņojumus",
"notifications.clear_confirmation": "Vai tiešām vēlies neatgriezeniski notīrīt visus savus paziņojumus?",
"notifications.column_settings.admin.report": "Jauni ziņojumi:",
"notifications.column_settings.admin.sign_up": "Jaunas pierakstīšanās:",
"notifications.column_settings.alert": "Darbvirsmas paziņojumi",
"notifications.column_settings.favourite": "Izlase:",
"notifications.column_settings.filter_bar.advanced": "Attēlot visas kategorijas",
"notifications.column_settings.filter_bar.category": "Atrās atlasīšanas josla",
"notifications.column_settings.follow": "Jauni sekotāji:",
"notifications.column_settings.follow_request": "Jauni sekošanas pieprasījumi:",
"notifications.column_settings.mention": "Pieminēšanas:",
@ -481,7 +487,9 @@
"notifications.permission_required": "Darbvirsmas paziņojumi nav pieejami, jo nav piešķirta nepieciešamā atļauja.",
"notifications.policy.filter_new_accounts_title": "Jauni konti",
"notifications.policy.filter_not_followers_title": "Cilvēki, kuri Tev neseko",
"notifications.policy.filter_not_following_hint": "Līdz tos pašrocīgi apstiprināsi",
"notifications.policy.filter_not_following_title": "Cilvēki, kuriem Tu neseko",
"notifications.policy.title": "Atlasīt paziņojumus no…",
"notifications_permission_banner.enable": "Iespējot darbvirsmas paziņojumus",
"notifications_permission_banner.how_to_control": "Lai saņemtu paziņojumus, kad Mastodon nav atvērts, iespējo darbvirsmas paziņojumus. Vari precīzi kontrolēt, kāda veida mijiedarbības rada darbvirsmas paziņojumus, izmantojot augstāk redzamo pogu {icon}, kad tie būs iespējoti.",
"notifications_permission_banner.title": "Nekad nepalaid neko garām",
@ -539,7 +547,9 @@
"privacy.direct.short": "Noteikti cilvēki",
"privacy.private.long": "Tikai Tavi sekotāji",
"privacy.private.short": "Sekotāji",
"privacy.public.long": "Jebkurš Mastodon un ārpus tā",
"privacy.public.short": "Publiska",
"privacy.unlisted.long": "Mazāk algoritmisku fanfaru",
"privacy_policy.last_updated": "Pēdējo reizi atjaunināta {date}",
"privacy_policy.title": "Privātuma politika",
"recommended": "Ieteicams",
@ -557,6 +567,7 @@
"relative_time.minutes": "{number}m",
"relative_time.seconds": "{number}s",
"relative_time.today": "šodien",
"reply_indicator.attachments": "{count, plural, zero{# pielikumu} one {# pielikums} other {# pielikumi}}",
"reply_indicator.cancel": "Atcelt",
"reply_indicator.poll": "Aptauja",
"report.block": "Bloķēt",
@ -630,7 +641,7 @@
"search_results.title": "Meklēt {q}",
"server_banner.about_active_users": "Cilvēki, kas izmantojuši šo serveri pēdējo 30 dienu laikā (aktīvie lietotāji mēnesī)",
"server_banner.active_users": "aktīvi lietotāji",
"server_banner.administered_by": "Administrē:",
"server_banner.administered_by": "Pārvalda:",
"server_banner.introduction": "{domain} ir daļa no decentralizētā sociālā tīkla, ko nodrošina {mastodon}.",
"server_banner.learn_more": "Uzzināt vairāk",
"server_banner.server_stats": "Servera statistika:",
@ -652,9 +663,10 @@
"status.direct_indicator": "Pieminēts privāti",
"status.edit": "Labot",
"status.edited": "Pēdējoreiz labots {date}",
"status.edited_x_times": "Labots {count, plural, one {{count} reizi} other {{count} reizes}}",
"status.edited_x_times": "Labots {count, plural, zero {{count} reižu} one {{count} reizi} other {{count} reizes}}",
"status.embed": "Iegult",
"status.favourite": "Izlasē",
"status.favourites": "{count, plural, zero {izlasēs} one {izlasē} other {izlasēs}}",
"status.filter": "Filtrē šo ziņu",
"status.filtered": "Filtrēts",
"status.hide": "Slēpt ierakstu",
@ -675,6 +687,7 @@
"status.reblog": "Pastiprināt",
"status.reblog_private": "Pastiprināt, nemainot redzamību",
"status.reblogged_by": "{name} pastiprināja",
"status.reblogs": "{count, plural, zero {pastiprinājumu} one {pastiprinājums} other {pastiprinājumi}}",
"status.reblogs.empty": "Neviens šo ierakstu vēl nav pastiprinājis. Kad būs, tie parādīsies šeit.",
"status.redraft": "Dzēst un pārrakstīt",
"status.remove_bookmark": "Noņemt grāmatzīmi",

View file

@ -17,9 +17,12 @@
"account.badges.group": "गट",
"account.block": "@{name} यांना ब्लॉक करा",
"account.block_domain": "{domain} पासून सर्व लपवा",
"account.block_short": "अवरोध",
"account.blocked": "ब्लॉक केले आहे",
"account.browse_more_on_origin_server": "मूळ प्रोफाइलवर अधिक ब्राउझ करा",
"account.cancel_follow_request": "फॉलो विनंती मागे घ्या",
"account.copy": "दुवा कॉपी करा",
"account.direct": "खाजगीरित्या उल्लेखीत @{name}",
"account.disable_notifications": "जेव्हा @{name} पोस्ट करतात तेव्हा मला सूचित करणे थांबवा",
"account.domain_blocked": "Domain hidden",
"account.edit_profile": "प्रोफाइल एडिट करा",
@ -29,6 +32,7 @@
"account.featured_tags.last_status_never": "पोस्ट नाहीत",
"account.featured_tags.title": "{name} चे वैशिष्ट्यीकृत हॅशटॅग",
"account.follow": "अनुयायी व्हा",
"account.follow_back": "आपणही अनुसरण करा",
"account.followers": "अनुयायी",
"account.followers.empty": "ह्या वापरकर्त्याचा आतापर्यंत कोणी अनुयायी नाही.",
"account.followers_counter": "{count, plural, one {{counter} Toot} other {{counter} Toots}}",
@ -45,6 +49,7 @@
"account.mention": "@{name} चा उल्लेख करा",
"account.moved_to": "{name} ने सूचित केले आहे की त्यांचे नवीन खाते आता आहे:",
"account.mute": "@{name} ला मूक कारा",
"account.mute_short": "नि:शब्द",
"account.muted": "मौन",
"account.open_original_page": "मूळ पृष्ठ उघडा",
"account.posts": "Toots",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Alsnog het profiel tonen",
"limited_account_hint.title": "Dit profiel is door de moderatoren van {domain} verborgen.",
"link_preview.author": "Door {name}",
"link_preview.more_from_author": "Meer van {name}",
"lists.account.add": "Aan lijst toevoegen",
"lists.account.remove": "Uit lijst verwijderen",
"lists.delete": "Lijst verwijderen",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Shfaqe profilin sido qoftë",
"limited_account_hint.title": "Ky profil është fshehur nga moderatorët e {domain}.",
"link_preview.author": "Nga {name}",
"link_preview.more_from_author": "Më tepër nga {name}",
"lists.account.add": "Shto në listë",
"lists.account.remove": "Hiqe nga lista",
"lists.delete": "Fshije listën",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Ipak prikaži profil",
"limited_account_hint.title": "Ovaj profil su sakrili moderatori {domain}.",
"link_preview.author": "Po {name}",
"link_preview.more_from_author": "Više od {name}",
"lists.account.add": "Dodaj na listu",
"lists.account.remove": "Ukloni sa liste",
"lists.delete": "Izbriši listu",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Ипак прикажи профил",
"limited_account_hint.title": "Овај профил су сакрили модератори {domain}.",
"link_preview.author": "По {name}",
"link_preview.more_from_author": "Више од {name}",
"lists.account.add": "Додај на листу",
"lists.account.remove": "Уклони са листе",
"lists.delete": "Избриши листу",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Visa profil ändå",
"limited_account_hint.title": "Denna profil har dolts av {domain}s moderatorer.",
"link_preview.author": "Av {name}",
"link_preview.more_from_author": "Mer från {name}",
"lists.account.add": "Lägg till i lista",
"lists.account.remove": "Ta bort från lista",
"lists.delete": "Radera lista",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "แสดงโปรไฟล์ต่อไป",
"limited_account_hint.title": "มีการซ่อนโปรไฟล์นี้โดยผู้กลั่นกรองของ {domain}",
"link_preview.author": "โดย {name}",
"link_preview.more_from_author": "เพิ่มเติมจาก {name}",
"lists.account.add": "เพิ่มไปยังรายการ",
"lists.account.remove": "เอาออกจากรายการ",
"lists.delete": "ลบรายการ",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Yine de profili göster",
"limited_account_hint.title": "Bu profil {domain} moderatörleri tarafından gizlendi.",
"link_preview.author": "Yazar: {name}",
"link_preview.more_from_author": "{name} kişisinden daha fazlası",
"lists.account.add": "Listeye ekle",
"lists.account.remove": "Listeden kaldır",
"lists.delete": "Listeyi sil",

View file

@ -414,6 +414,7 @@
"limited_account_hint.action": "Усе одно показати профіль",
"limited_account_hint.title": "Цей профіль сховали модератори {domain}.",
"link_preview.author": "Від {name}",
"link_preview.more_from_author": "Більше від {name}",
"lists.account.add": "Додати до списку",
"lists.account.remove": "Вилучити зі списку",
"lists.delete": "Видалити список",

View file

@ -13,6 +13,7 @@
# from_account_id :bigint(8) not null
# type :string
# filtered :boolean default(FALSE), not null
# group_key :string
#
class Notification < ApplicationRecord
@ -165,6 +166,67 @@ class Notification < ApplicationRecord
end
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('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)
end
# Differs from :paginate_groups_by_max_id in that it gives the results immediately following min_id,
# whereas since_id gives the items with largest id, but with since_id as a cutoff.
# Results will be in ascending order by id.
def paginate_groups_by_min_id(limit, max_id: nil, min_id: nil)
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('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)
end
def to_a_grouped_paginated_by_id(limit, options = {})
if options[:min_id].present?
paginate_groups_by_min_id(limit, min_id: options[:min_id], max_id: options[:max_id]).reverse
else
paginate_groups_by_max_id(limit, max_id: options[:max_id], since_id: options[:since_id]).to_a
end
end
def preload_cache_collection_target_statuses(notifications, &_block)
notifications.group_by(&:type).each do |type, grouped_notifications|
associations = TARGET_STATUS_INCLUDES_BY_TYPE[type]

View file

@ -0,0 +1,29 @@
# frozen_string_literal: true
class NotificationGroup < ActiveModelSerializers::Model
attributes :group_key, :sample_accounts, :notifications_count, :notification
def self.from_notification(notification)
if notification.group_key.present?
# TODO: caching and preloading
sample_accounts = notification.account.notifications.where(group_key: notification.group_key).order(id: :desc).limit(3).map(&:from_account)
notifications_count = notification.account.notifications.where(group_key: notification.group_key).count
else
sample_accounts = [notification.from_account]
notifications_count = 1
end
NotificationGroup.new(
notification: notification,
group_key: notification.group_key || "ungrouped-#{notification.id}",
sample_accounts: sample_accounts,
notifications_count: notifications_count
)
end
delegate :type,
:target_status,
:report,
:account_relationship_severance_event,
to: :notification, prefix: false
end

View file

@ -0,0 +1,45 @@
# frozen_string_literal: true
class REST::NotificationGroupSerializer < ActiveModel::Serializer
attributes :group_key, :notifications_count, :type
attribute :page_min_id, if: :paginated?
attribute :page_max_id, if: :paginated?
attribute :latest_page_notification_at, if: :paginated?
has_many :sample_accounts, serializer: REST::AccountSerializer
belongs_to :target_status, key: :status, if: :status_type?, serializer: REST::StatusSerializer
belongs_to :report, if: :report_type?, serializer: REST::ReportSerializer
belongs_to :account_relationship_severance_event, key: :event, if: :relationship_severance_event?, serializer: REST::AccountRelationshipSeveranceEventSerializer
def status_type?
[:favourite, :reblog, :status, :mention, :poll, :update].include?(object.type)
end
def report_type?
object.type == :'admin.report'
end
def relationship_severance_event?
object.type == :severed_relationships
end
def page_min_id
range = instance_options[:group_metadata][object.group_key]
range.present? ? range[:min_id].to_s : object.notification.id.to_s
end
def page_max_id
range = instance_options[:group_metadata][object.group_key]
range.present? ? range[:max_id].to_s : object.notification.id.to_s
end
def latest_page_notification_at
range = instance_options[:group_metadata][object.group_key]
range.present? ? range[:latest_notification_at] : object.notification.created_at
end
def paginated?
instance_options[:group_metadata].present?
end
end

View file

@ -3,6 +3,9 @@
class NotifyService < BaseService
include Redisable
MAXIMUM_GROUP_SPAN_HOURS = 12
MAXIMUM_GROUP_GAP_TIME = 4.hours.to_i
NON_EMAIL_TYPES = %i(
admin.report
admin.sign_up
@ -186,6 +189,7 @@ class NotifyService < BaseService
return if dismiss?
@notification.filtered = filter?
@notification.group_key = notification_group_key
@notification.save!
# It's possible the underlying activity has been deleted
@ -205,6 +209,24 @@ class NotifyService < BaseService
private
def notification_group_key
return nil if @notification.filtered || %i(favourite reblog).exclude?(@notification.type)
type_prefix = "#{@notification.type}-#{@notification.target_status.id}"
redis_key = "notif-group/#{@recipient.id}/#{type_prefix}"
hour_bucket = @notification.activity.created_at.utc.to_i / 1.hour.to_i
# Reuse previous group if it does not span too large an amount of time
previous_bucket = redis.get(redis_key).to_i
hour_bucket = previous_bucket if hour_bucket < previous_bucket + MAXIMUM_GROUP_SPAN_HOURS
# Do not track groups past a given inactivity time
# We do not concern ourselves with race conditions since we use hour buckets
redis.set(redis_key, hour_bucket, ex: MAXIMUM_GROUP_GAP_TIME)
"#{type_prefix}-#{hour_bucket}"
end
def dismiss?
DismissCondition.new(@notification).dismiss?
end

View file

@ -3,7 +3,7 @@
- if self_destruct?
.flash-message.warning
= t('auth.status.self_destruct', domain: ENV.fetch('LOCAL_DOMAIN'))
= t('auth.status.self_destruct', domain: Rails.configuration.x.local_domain)
- else
= render partial: 'status', locals: { user: @user, strikes: @strikes }

View file

@ -3,7 +3,7 @@
.simple_form
%h1.title= t('self_destruct.title')
%p.lead= t('self_destruct.lead_html', domain: ENV.fetch('LOCAL_DOMAIN'))
%p.lead= t('self_destruct.lead_html', domain: Rails.configuration.x.local_domain)
.form-footer
%ul.no-list