Skip to content

Commit

Permalink
Merge pull request #2835 from ClearlyClaire/glitch-soc/merge-upstream
Browse files Browse the repository at this point in the history
Merge upstream changes up to fe04291
  • Loading branch information
ClearlyClaire authored Sep 4, 2024
2 parents 664dfa6 + cb1eaa1 commit 5a1d7db
Show file tree
Hide file tree
Showing 485 changed files with 1,193 additions and 800 deletions.
3 changes: 3 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,8 @@ RUN apt-get update && \
export DEBIAN_FRONTEND=noninteractive && \
apt-get -y install --no-install-recommends libicu-dev libidn11-dev ffmpeg imagemagick libvips42 libpam-dev

# Disable download prompt for Corepack
ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0

# Move welcome message to where VS Code expects it
COPY .devcontainer/welcome-message.txt /usr/local/etc/vscode-dev-containers/first-run-notice.txt
2 changes: 1 addition & 1 deletion .devcontainer/codespaces/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
},

"onCreateCommand": "git config --global --add safe.directory ${containerWorkspaceFolder}",
"postCreateCommand": "COREPACK_ENABLE_DOWNLOAD_PROMPT=0 bin/setup",
"postCreateCommand": "bin/setup",
"waitFor": "postCreateCommand",

"customizations": {
Expand Down
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.3.4
3.3.5
16 changes: 8 additions & 8 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -100,17 +100,17 @@ GEM
attr_required (1.0.2)
awrence (1.2.1)
aws-eventstream (1.3.0)
aws-partitions (1.969.0)
aws-sdk-core (3.202.1)
aws-partitions (1.970.0)
aws-sdk-core (3.203.0)
aws-eventstream (~> 1, >= 1.3.0)
aws-partitions (~> 1, >= 1.651.0)
aws-sigv4 (~> 1.9)
jmespath (~> 1, >= 1.6.1)
aws-sdk-kms (1.88.0)
aws-sdk-core (~> 3, >= 3.201.0)
aws-sdk-kms (1.89.0)
aws-sdk-core (~> 3, >= 3.203.0)
aws-sigv4 (~> 1.5)
aws-sdk-s3 (1.159.0)
aws-sdk-core (~> 3, >= 3.201.0)
aws-sdk-s3 (1.160.0)
aws-sdk-core (~> 3, >= 3.203.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.5)
aws-sigv4 (1.9.1)
Expand Down Expand Up @@ -790,7 +790,7 @@ GEM
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
semantic_range (3.0.0)
shoulda-matchers (6.3.1)
shoulda-matchers (6.4.0)
activesupport (>= 5.2.0)
sidekiq (6.5.12)
connection_pool (>= 2.2.5, < 3)
Expand Down Expand Up @@ -837,7 +837,7 @@ GEM
unicode-display_width (>= 1.1.1, < 3)
terrapin (1.0.1)
climate_control
test-prof (1.4.1)
test-prof (1.4.2)
thor (1.3.2)
tilt (2.4.0)
timeout (0.4.1)
Expand Down
2 changes: 2 additions & 0 deletions app/controllers/api/v2_alpha/notifications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ def load_notifications
end

def load_grouped_notifications
return [] if @notifications.empty?

MastodonOTELTracer.in_span('Api::V2Alpha::NotificationsController#load_grouped_notifications') do
NotificationGroup.from_notifications(@notifications, pagination_range: (@notifications.last.id)..(@notifications.first.id), grouped_types: params[:grouped_types])
end
Expand Down
33 changes: 17 additions & 16 deletions app/javascript/flavours/glitch/actions/notification_groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
selectSettingsNotificationsQuickFilterActive,
selectSettingsNotificationsShows,
} from 'flavours/glitch/selectors/settings';
import type { AppDispatch } from 'flavours/glitch/store';
import type { AppDispatch, RootState } from 'flavours/glitch/store';
import {
createAppAsyncThunk,
createDataLoadingThunk,
Expand All @@ -32,6 +32,14 @@ function excludeAllTypesExcept(filter: string) {
return allNotificationTypes.filter((item) => item !== filter);
}

function getExcludedTypes(state: RootState) {
const activeFilter = selectSettingsNotificationsQuickFilterActive(state);

return activeFilter === 'all'
? selectSettingsNotificationsExcludedTypes(state)
: excludeAllTypesExcept(activeFilter);
}

function dispatchAssociatedRecords(
dispatch: AppDispatch,
notifications: ApiNotificationGroupJSON[] | ApiNotificationJSON[],
Expand Down Expand Up @@ -62,17 +70,8 @@ function dispatchAssociatedRecords(

export const fetchNotifications = createDataLoadingThunk(
'notificationGroups/fetch',
async (_params, { getState }) => {
const activeFilter =
selectSettingsNotificationsQuickFilterActive(getState());

return apiFetchNotifications({
exclude_types:
activeFilter === 'all'
? selectSettingsNotificationsExcludedTypes(getState())
: excludeAllTypesExcept(activeFilter),
});
},
async (_params, { getState }) =>
apiFetchNotifications({ exclude_types: getExcludedTypes(getState()) }),
({ notifications, accounts, statuses }, { dispatch }) => {
dispatch(importFetchedAccounts(accounts));
dispatch(importFetchedStatuses(statuses));
Expand All @@ -92,9 +91,11 @@ export const fetchNotifications = createDataLoadingThunk(

export const fetchNotificationsGap = createDataLoadingThunk(
'notificationGroups/fetchGap',
async (params: { gap: NotificationGap }) =>
apiFetchNotifications({ max_id: params.gap.maxId }),

async (params: { gap: NotificationGap }, { getState }) =>
apiFetchNotifications({
max_id: params.gap.maxId,
exclude_types: getExcludedTypes(getState()),
}),
({ notifications, accounts, statuses }, { dispatch }) => {
dispatch(importFetchedAccounts(accounts));
dispatch(importFetchedStatuses(statuses));
Expand All @@ -109,6 +110,7 @@ export const pollRecentNotifications = createDataLoadingThunk(
async (_params, { getState }) => {
return apiFetchNotifications({
max_id: undefined,
exclude_types: getExcludedTypes(getState()),
// In slow mode, we don't want to include notifications that duplicate the already-displayed ones
since_id: usePendingItems
? getState().notificationGroups.groups.find(
Expand Down Expand Up @@ -183,7 +185,6 @@ export const setNotificationsFilter = createAppAsyncThunk(
path: ['notifications', 'quickFilter', 'active'],
value: filterType,
});
// dispatch(expandNotifications({ forceLoad: true }));
void dispatch(fetchNotifications());
dispatch(saveSettings());
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,11 @@ export const NotificationAdminReport: React.FC<{

if (!account || !targetAccount) return null;

const domain = account.acct.split('@')[1];

const values = {
name: (
<bdi
dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }}
/>
),
target: (
<bdi
dangerouslySetInnerHTML={{
__html: targetAccount.get('display_name_html'),
}}
/>
),
name: <bdi>{domain ?? `@${account.acct}`}</bdi>,
target: <bdi>@{targetAccount.acct}</bdi>,
category: intl.formatMessage(messages[report.category]),
count: report.status_ids.length,
};
Expand Down
33 changes: 17 additions & 16 deletions app/javascript/mastodon/actions/notification_groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
selectSettingsNotificationsQuickFilterActive,
selectSettingsNotificationsShows,
} from 'mastodon/selectors/settings';
import type { AppDispatch } from 'mastodon/store';
import type { AppDispatch, RootState } from 'mastodon/store';
import {
createAppAsyncThunk,
createDataLoadingThunk,
Expand All @@ -32,6 +32,14 @@ function excludeAllTypesExcept(filter: string) {
return allNotificationTypes.filter((item) => item !== filter);
}

function getExcludedTypes(state: RootState) {
const activeFilter = selectSettingsNotificationsQuickFilterActive(state);

return activeFilter === 'all'
? selectSettingsNotificationsExcludedTypes(state)
: excludeAllTypesExcept(activeFilter);
}

function dispatchAssociatedRecords(
dispatch: AppDispatch,
notifications: ApiNotificationGroupJSON[] | ApiNotificationJSON[],
Expand Down Expand Up @@ -62,17 +70,8 @@ function dispatchAssociatedRecords(

export const fetchNotifications = createDataLoadingThunk(
'notificationGroups/fetch',
async (_params, { getState }) => {
const activeFilter =
selectSettingsNotificationsQuickFilterActive(getState());

return apiFetchNotifications({
exclude_types:
activeFilter === 'all'
? selectSettingsNotificationsExcludedTypes(getState())
: excludeAllTypesExcept(activeFilter),
});
},
async (_params, { getState }) =>
apiFetchNotifications({ exclude_types: getExcludedTypes(getState()) }),
({ notifications, accounts, statuses }, { dispatch }) => {
dispatch(importFetchedAccounts(accounts));
dispatch(importFetchedStatuses(statuses));
Expand All @@ -92,9 +91,11 @@ export const fetchNotifications = createDataLoadingThunk(

export const fetchNotificationsGap = createDataLoadingThunk(
'notificationGroups/fetchGap',
async (params: { gap: NotificationGap }) =>
apiFetchNotifications({ max_id: params.gap.maxId }),

async (params: { gap: NotificationGap }, { getState }) =>
apiFetchNotifications({
max_id: params.gap.maxId,
exclude_types: getExcludedTypes(getState()),
}),
({ notifications, accounts, statuses }, { dispatch }) => {
dispatch(importFetchedAccounts(accounts));
dispatch(importFetchedStatuses(statuses));
Expand All @@ -109,6 +110,7 @@ export const pollRecentNotifications = createDataLoadingThunk(
async (_params, { getState }) => {
return apiFetchNotifications({
max_id: undefined,
exclude_types: getExcludedTypes(getState()),
// In slow mode, we don't want to include notifications that duplicate the already-displayed ones
since_id: usePendingItems
? getState().notificationGroups.groups.find(
Expand Down Expand Up @@ -183,7 +185,6 @@ export const setNotificationsFilter = createAppAsyncThunk(
path: ['notifications', 'quickFilter', 'active'],
value: filterType,
});
// dispatch(expandNotifications({ forceLoad: true }));
void dispatch(fetchNotifications());
dispatch(saveSettings());
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,11 @@ export const NotificationAdminReport: React.FC<{

if (!account || !targetAccount) return null;

const domain = account.acct.split('@')[1];

const values = {
name: (
<bdi
dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }}
/>
),
target: (
<bdi
dangerouslySetInnerHTML={{
__html: targetAccount.get('display_name_html'),
}}
/>
),
name: <bdi>{domain ?? `@${account.acct}`}</bdi>,
target: <bdi>@{targetAccount.acct}</bdi>,
category: intl.formatMessage(messages[report.category]),
count: report.status_ids.length,
};
Expand Down
28 changes: 28 additions & 0 deletions app/javascript/mastodon/locales/pt-BR.json
Original file line number Diff line number Diff line change
Expand Up @@ -524,7 +524,9 @@
"notification.moderation_warning.action_silence": "Sua conta foi limitada.",
"notification.moderation_warning.action_suspend": "Sua conta foi suspensa.",
"notification.own_poll": "Sua enquete terminou",
"notification.poll": "Uma enquete que você votou terminou",
"notification.reblog": "{name} deu boost no teu toot",
"notification.reblog.name_and_others_with_link": "{name} e <a>{count, plural, one {# outra} other {# outras}}</a> impulsionaram a publicação",
"notification.relationships_severance_event": "Conexões perdidas com {name}",
"notification.relationships_severance_event.account_suspension": "Um administrador de {from} suspendeu {target}, o que significa que você não pode mais receber atualizações deles ou interagir com eles.",
"notification.relationships_severance_event.domain_block": "An admin from {from} has blocked {target}, including {followersCount} of your followers and {followingCount, plural, one {# account} other {# accounts}} you follow.",
Expand All @@ -533,16 +535,32 @@
"notification.status": "{name} acabou de tootar",
"notification.update": "{name} editou uma publicação",
"notification_requests.accept": "Aceitar",
"notification_requests.accept_multiple": "{count, plural, one {Aceite # pedido…} other {Aceite # pedidos…}}",
"notification_requests.confirm_accept_multiple.button": "{count, plural, one {Aceite # pedido} other {Aceite # pedidos}}",
"notification_requests.confirm_accept_multiple.message": "Você está prestes a aceitar {count, plural, one {um pedido de notificação} other {# pedidos de notificação}}. Tem certeza de que deseja continuar?",
"notification_requests.confirm_accept_multiple.title": "Aceitar solicitações de notificação?",
"notification_requests.confirm_dismiss_multiple.button": "{count, plural, one {Dispensar pedido} other {Dispensar pedidos}}",
"notification_requests.confirm_dismiss_multiple.message": "Você está prestes a descartar {count, plural, one {um pedido de notificação} other {# pedidos de notificação}}. Você não será capaz de acessar facilmente{count, plural, one {} other {}} novamente. Tem certeza de que deseja continuar?",
"notification_requests.confirm_dismiss_multiple.title": "Descartar solicitações de notificação?",
"notification_requests.dismiss": "Rejeitar",
"notification_requests.dismiss_multiple": "{count, plural, one {Dispensar # pedido…} other {Dispensar # pedidos…}}",
"notification_requests.edit_selection": "Editar",
"notification_requests.exit_selection": "Concluído",
"notification_requests.explainer_for_limited_account": "As notificações desta conta foram filtradas porque a conta foi limitada por um moderador.",
"notification_requests.explainer_for_limited_remote_account": "As notificações desta conta foram filtradas porque a conta ou o seu servidor foi limitado por um moderador.",
"notification_requests.maximize": "Maximizar",
"notification_requests.minimize_banner": "Minimizar banner de notificações filtradas",
"notification_requests.notifications_from": "Notificações de {name}",
"notification_requests.title": "Notificações filtradas",
"notification_requests.view": "Ver notificações",
"notifications.clear": "Limpar notificações",
"notifications.clear_confirmation": "Você tem certeza de que deseja limpar todas as suas notificações?",
"notifications.clear_title": "Limpar notificações?",
"notifications.column_settings.admin.report": "Novas denúncias:",
"notifications.column_settings.admin.sign_up": "Novas inscrições:",
"notifications.column_settings.alert": "Notificações no computador",
"notifications.column_settings.beta.category": "Recursos experimentais",
"notifications.column_settings.beta.grouping": "Agrupar notificações",
"notifications.column_settings.favourite": "Favoritos:",
"notifications.column_settings.filter_bar.advanced": "Exibir todas as categorias",
"notifications.column_settings.filter_bar.category": "Barra de filtro rápido",
Expand Down Expand Up @@ -574,6 +592,11 @@
"notifications.policy.accept": "Aceitar",
"notifications.policy.accept_hint": "Mostrar nas notificações",
"notifications.policy.drop": "Ignorar",
"notifications.policy.drop_hint": "Envie para o void, para nunca mais ser visto novamente",
"notifications.policy.filter": "Filtrar",
"notifications.policy.filter_hint": "Enviar para caixa de notificações filtradas",
"notifications.policy.filter_limited_accounts_hint": "Limitado pelos moderadores do servidor",
"notifications.policy.filter_limited_accounts_title": "Contas moderadas",
"notifications.policy.filter_new_accounts.hint": "Created within the past {days, plural, one {one day} other {# days}}",
"notifications.policy.filter_new_accounts_title": "Novas contas",
"notifications.policy.filter_not_followers_hint": "Including people who have been following you fewer than {days, plural, one {one day} other {# days}}",
Expand All @@ -582,6 +605,7 @@
"notifications.policy.filter_not_following_title": "Pessoas que você não segue",
"notifications.policy.filter_private_mentions_hint": "Filtrado, a menos que respondido em sua própria menção ou se você segue o remetente",
"notifications.policy.filter_private_mentions_title": "Menções privadas não solicitadas",
"notifications.policy.title": "Gerenciar notificações de…",
"notifications_permission_banner.enable": "Ativar notificações no computador",
"notifications_permission_banner.how_to_control": "Para receber notificações quando o Mastodon não estiver aberto, ative as notificações no computador. Você pode controlar precisamente quais tipos de interações geram notificações no computador através do botão {icon}.",
"notifications_permission_banner.title": "Nunca perca nada",
Expand Down Expand Up @@ -708,9 +732,13 @@
"report.unfollow_explanation": "Você está seguindo esta conta. Para não ver as publicações dela em sua página inicial, deixe de segui-la.",
"report_notification.attached_statuses": "{count, plural, one {{count} publicação anexada} other {{count} publicações anexadas}}",
"report_notification.categories.legal": "Legal",
"report_notification.categories.legal_sentence": "conteúdo ilegal",
"report_notification.categories.other": "Outro",
"report_notification.categories.other_sentence": "outro",
"report_notification.categories.spam": "Spam",
"report_notification.categories.spam_sentence": "spam",
"report_notification.categories.violation": "Violação de regra",
"report_notification.categories.violation_sentence": "violação de regra",
"report_notification.open": "Abrir denúncia",
"search.no_recent_searches": "Nenhuma busca recente",
"search.placeholder": "Pesquisar",
Expand Down
12 changes: 11 additions & 1 deletion app/lib/annual_report/source.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@ def initialize(account, year)
protected

def year_as_snowflake_range
(Mastodon::Snowflake.id_at(DateTime.new(year, 1, 1))..Mastodon::Snowflake.id_at(DateTime.new(year, 12, 31)))
(beginning_snowflake_id..ending_snowflake_id)
end

private

def beginning_snowflake_id
Mastodon::Snowflake.id_at DateTime.new(year).beginning_of_year
end

def ending_snowflake_id
Mastodon::Snowflake.id_at DateTime.new(year).end_of_year
end
end
15 changes: 12 additions & 3 deletions app/models/account_statuses_cleanup_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -145,15 +145,15 @@ def old_enough_scope(max_id = nil)
end

def without_self_fav_scope
Status.where('NOT EXISTS (SELECT 1 FROM favourites fav WHERE fav.account_id = statuses.account_id AND fav.status_id = statuses.id)')
Status.where.not(self_status_reference_exists(Favourite))
end

def without_self_bookmark_scope
Status.where('NOT EXISTS (SELECT 1 FROM bookmarks bookmark WHERE bookmark.account_id = statuses.account_id AND bookmark.status_id = statuses.id)')
Status.where.not(self_status_reference_exists(Bookmark))
end

def without_pinned_scope
Status.where('NOT EXISTS (SELECT 1 FROM status_pins pin WHERE pin.account_id = statuses.account_id AND pin.status_id = statuses.id)')
Status.where.not(self_status_reference_exists(StatusPin))
end

def without_media_scope
Expand All @@ -174,4 +174,13 @@ def without_popular_scope
def account_statuses
Status.where(account_id: account_id)
end

def self_status_reference_exists(model)
model
.where(model.arel_table[:account_id].eq Status.arel_table[:account_id])
.where(model.arel_table[:status_id].eq Status.arel_table[:id])
.select(1)
.arel
.exists
end
end
Loading

0 comments on commit 5a1d7db

Please sign in to comment.