From 16a6e5c118386e65c7c4dbcc6f47b7281c984978 Mon Sep 17 00:00:00 2001 From: Claire Date: Thu, 18 Sep 2025 14:46:31 +0200 Subject: [PATCH] Add click-through for quoted limited accounts (#36167) --- .../mastodon/components/status_quoted.tsx | 39 ++++++++++++++++++- app/javascript/mastodon/locales/en.json | 2 + 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/app/javascript/mastodon/components/status_quoted.tsx b/app/javascript/mastodon/components/status_quoted.tsx index 2726b1a55a2..8c8216701a6 100644 --- a/app/javascript/mastodon/components/status_quoted.tsx +++ b/app/javascript/mastodon/components/status_quoted.tsx @@ -1,4 +1,4 @@ -import { useEffect, useMemo, useRef } from 'react'; +import { useCallback, useEffect, useMemo, useRef } from 'react'; import { FormattedMessage } from 'react-intl'; @@ -6,13 +6,16 @@ import type { Map as ImmutableMap } from 'immutable'; import { LearnMoreLink } from 'mastodon/components/learn_more_link'; import StatusContainer from 'mastodon/containers/status_container'; +import { domain } from 'mastodon/initial_state'; +import type { Account } from 'mastodon/models/account'; import type { Status } from 'mastodon/models/status'; import type { RootState } from 'mastodon/store'; import { useAppDispatch, useAppSelector } from 'mastodon/store'; +import { revealAccount } from '../actions/accounts_typed'; import { fetchStatus } from '../actions/statuses'; -import type { Account } from '../models/account'; import { makeGetStatusWithExtraInfo } from '../selectors'; +import { getAccountHidden } from '../selectors/accounts'; import { Button } from './button'; @@ -56,6 +59,29 @@ type GetStatusSelector = ( type QuoteMap = ImmutableMap<'state' | 'quoted_status', string | null>; +const LimitedAccountHint: React.FC<{ accountId: string }> = ({ accountId }) => { + const dispatch = useAppDispatch(); + const reveal = useCallback(() => { + dispatch(revealAccount({ id: accountId })); + }, [dispatch, accountId]); + + return ( + <> + + + + ); +}; + interface QuotedStatusProps { quote: QuoteMap; contextType?: string; @@ -89,6 +115,13 @@ export const QuotedStatus: React.FC = ({ getStatusSelector(state, { id: quotedStatusId, contextType }), ); + const accountId: string | null = status?.get('account') + ? (status.get('account') as Account).id + : null; + const hiddenAccount = useAppSelector( + (state) => accountId && getAccountHidden(state, accountId), + ); + const shouldFetchQuote = !status?.get('isLoading') && quoteState !== 'deleted' && @@ -164,6 +197,8 @@ export const QuotedStatus: React.FC = ({ defaultMessage='Post unavailable' /> ); + } else if (hiddenAccount && accountId) { + quoteError = ; } if (quoteError) { diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index e88cc16eaca..f7dde46fcd4 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -895,6 +895,8 @@ "status.quote": "Quote", "status.quote.cancel": "Cancel quote", "status.quote_error.filtered": "Hidden due to one of your filters", + "status.quote_error.limited_account_hint.action": "Show anyway", + "status.quote_error.limited_account_hint.title": "This account has been hidden by the moderators of {domain}.", "status.quote_error.not_available": "Post unavailable", "status.quote_error.pending_approval": "Post pending", "status.quote_error.pending_approval_popout.body": "On Mastodon, you can control whether someone can quote you. This post is pending while we're getting the original author's approval.",