Change display of blocked and muted quoted users (#36619)
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
|
||||||
import { FormattedMessage } from 'react-intl';
|
import { FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
@@ -83,6 +83,62 @@ const LimitedAccountHint: React.FC<{ accountId: string }> = ({ accountId }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const FilteredQuote: React.FC<{
|
||||||
|
reveal: VoidFunction;
|
||||||
|
quotedAccountId: string;
|
||||||
|
quoteState: string;
|
||||||
|
}> = ({ reveal, quotedAccountId, quoteState }) => {
|
||||||
|
const account = useAppSelector((state) =>
|
||||||
|
quotedAccountId ? state.accounts.get(quotedAccountId) : undefined,
|
||||||
|
);
|
||||||
|
|
||||||
|
const quoteAuthorName = account?.acct;
|
||||||
|
const domain = quoteAuthorName?.split('@')[1];
|
||||||
|
|
||||||
|
let message;
|
||||||
|
|
||||||
|
switch (quoteState) {
|
||||||
|
case 'blocked_account':
|
||||||
|
message = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='status.quote_error.blocked_account_hint.title'
|
||||||
|
defaultMessage="This post is hidden because you've blocked @{name}."
|
||||||
|
values={{ name: quoteAuthorName }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'blocked_domain':
|
||||||
|
message = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='status.quote_error.blocked_domain_hint.title'
|
||||||
|
defaultMessage="This post is hidden because you've blocked {domain}."
|
||||||
|
values={{ domain }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case 'muted_account':
|
||||||
|
message = (
|
||||||
|
<FormattedMessage
|
||||||
|
id='status.quote_error.muted_account_hint.title'
|
||||||
|
defaultMessage="This post is hidden because you've muted @{name}."
|
||||||
|
values={{ name: quoteAuthorName }}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{message}
|
||||||
|
<button onClick={reveal} className='link-button'>
|
||||||
|
<FormattedMessage
|
||||||
|
id='status.quote_error.limited_account_hint.action'
|
||||||
|
defaultMessage='Show anyway'
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
interface QuotedStatusProps {
|
interface QuotedStatusProps {
|
||||||
quote: QuoteMap;
|
quote: QuoteMap;
|
||||||
contextType?: string;
|
contextType?: string;
|
||||||
@@ -130,6 +186,11 @@ export const QuotedStatus: React.FC<QuotedStatusProps> = ({
|
|||||||
const isLoaded = loadingState === 'complete';
|
const isLoaded = loadingState === 'complete';
|
||||||
|
|
||||||
const isFetchingQuoteRef = useRef(false);
|
const isFetchingQuoteRef = useRef(false);
|
||||||
|
const [revealed, setRevealed] = useState(false);
|
||||||
|
|
||||||
|
const reveal = useCallback(() => {
|
||||||
|
setRevealed(true);
|
||||||
|
}, [setRevealed]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isLoaded) {
|
if (isLoaded) {
|
||||||
@@ -189,6 +250,20 @@ export const QuotedStatus: React.FC<QuotedStatusProps> = ({
|
|||||||
defaultMessage='Post removed by author'
|
defaultMessage='Post removed by author'
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
} else if (
|
||||||
|
(quoteState === 'blocked_account' ||
|
||||||
|
quoteState === 'blocked_domain' ||
|
||||||
|
quoteState === 'muted_account') &&
|
||||||
|
!revealed &&
|
||||||
|
accountId
|
||||||
|
) {
|
||||||
|
quoteError = (
|
||||||
|
<FilteredQuote
|
||||||
|
quoteState={quoteState}
|
||||||
|
reveal={reveal}
|
||||||
|
quotedAccountId={accountId}
|
||||||
|
/>
|
||||||
|
);
|
||||||
} else if (
|
} else if (
|
||||||
!status ||
|
!status ||
|
||||||
!quotedStatusId ||
|
!quotedStatusId ||
|
||||||
|
|||||||
@@ -911,9 +911,12 @@
|
|||||||
"status.pin": "Pin on profile",
|
"status.pin": "Pin on profile",
|
||||||
"status.quote": "Quote",
|
"status.quote": "Quote",
|
||||||
"status.quote.cancel": "Cancel quote",
|
"status.quote.cancel": "Cancel quote",
|
||||||
|
"status.quote_error.blocked_account_hint.title": "This post is hidden because you've blocked @{name}.",
|
||||||
|
"status.quote_error.blocked_domain_hint.title": "This post is hidden because you've blocked {domain}.",
|
||||||
"status.quote_error.filtered": "Hidden due to one of your filters",
|
"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.action": "Show anyway",
|
||||||
"status.quote_error.limited_account_hint.title": "This account has been hidden by the moderators of {domain}.",
|
"status.quote_error.limited_account_hint.title": "This account has been hidden by the moderators of {domain}.",
|
||||||
|
"status.quote_error.muted_account_hint.title": "This post is hidden because you've muted @{name}.",
|
||||||
"status.quote_error.not_available": "Post unavailable",
|
"status.quote_error.not_available": "Post unavailable",
|
||||||
"status.quote_error.pending_approval": "Post pending",
|
"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.",
|
"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.",
|
||||||
|
|||||||
@@ -98,12 +98,12 @@ class StatusCacheHydrator
|
|||||||
if quote.quoted_status.nil?
|
if quote.quoted_status.nil?
|
||||||
payload[nested ? :quoted_status_id : :quoted_status] = nil
|
payload[nested ? :quoted_status_id : :quoted_status] = nil
|
||||||
payload[:state] = 'deleted'
|
payload[:state] = 'deleted'
|
||||||
elsif StatusFilter.new(quote.quoted_status, Account.find_by(id: account_id)).filtered_for_quote?
|
|
||||||
payload[nested ? :quoted_status_id : :quoted_status] = nil
|
|
||||||
payload[:state] = 'unauthorized'
|
|
||||||
else
|
else
|
||||||
payload[:state] = 'accepted'
|
filter_state = StatusFilter.new(quote.quoted_status, Account.find_by(id: account_id)).filter_state_for_quote
|
||||||
if nested
|
payload[:state] = filter_state || 'accepted'
|
||||||
|
if filter_state == 'unauthorized'
|
||||||
|
payload[nested ? :quoted_status_id : :quoted_status] = nil
|
||||||
|
elsif nested
|
||||||
payload[:quoted_status_id] = quote.quoted_status_id&.to_s
|
payload[:quoted_status_id] = quote.quoted_status_id&.to_s
|
||||||
else
|
else
|
||||||
payload[:quoted_status] = StatusCacheHydrator.new(quote.quoted_status).hydrate(account_id, nested: true)
|
payload[:quoted_status] = StatusCacheHydrator.new(quote.quoted_status).hydrate(account_id, nested: true)
|
||||||
|
|||||||
@@ -15,10 +15,18 @@ class StatusFilter
|
|||||||
blocked_by_policy? || (account_present? && filtered_status?) || silenced_account?
|
blocked_by_policy? || (account_present? && filtered_status?) || silenced_account?
|
||||||
end
|
end
|
||||||
|
|
||||||
def filtered_for_quote?
|
def filter_state_for_quote
|
||||||
return false if !account.nil? && account.id == status.account_id
|
if !account.nil? && account.id == status.account_id
|
||||||
|
nil
|
||||||
blocked_by_policy? || (account_present? && filtered_status?)
|
elsif blocked_by_policy?
|
||||||
|
'unauthorized'
|
||||||
|
elsif account_present? && blocking_domain?
|
||||||
|
'blocked_domain'
|
||||||
|
elsif account_present? && blocking_account?
|
||||||
|
'blocked_account'
|
||||||
|
elsif account_present? && muting_account?
|
||||||
|
'muted_account'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
@@ -8,13 +8,12 @@ class REST::BaseQuoteSerializer < ActiveModel::Serializer
|
|||||||
|
|
||||||
# Extra states when a status is unavailable
|
# Extra states when a status is unavailable
|
||||||
return 'deleted' if object.quoted_status.nil?
|
return 'deleted' if object.quoted_status.nil?
|
||||||
return 'unauthorized' if status_filter.filtered_for_quote?
|
|
||||||
|
|
||||||
object.state
|
status_filter.filter_state_for_quote || object.state
|
||||||
end
|
end
|
||||||
|
|
||||||
def quoted_status
|
def quoted_status
|
||||||
object.quoted_status if object.accepted? && object.quoted_status.present? && !object.quoted_status&.reblog? && !status_filter.filtered_for_quote?
|
object.quoted_status if object.accepted? && object.quoted_status.present? && !object.quoted_status&.reblog? && status_filter.filter_state_for_quote != 'unauthorized'
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|||||||
Reference in New Issue
Block a user