From 9c55b2fbe47d9123747c2689a4047d40dceaad3a Mon Sep 17 00:00:00 2001 From: Claire Date: Wed, 27 Aug 2025 16:55:39 +0200 Subject: [PATCH] Enable quotes of manually-reviewed quotes with a different label (#35925) --- .../components/status/reblog_button.tsx | 58 +++++++++++++++---- app/javascript/mastodon/locales/en.json | 3 + 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/app/javascript/mastodon/components/status/reblog_button.tsx b/app/javascript/mastodon/components/status/reblog_button.tsx index 2ebedf781fc..23da29961ec 100644 --- a/app/javascript/mastodon/components/status/reblog_button.tsx +++ b/app/javascript/mastodon/components/status/reblog_button.tsx @@ -46,6 +46,14 @@ const messages = defineMessages({ id: 'status.cannot_quote', defaultMessage: 'Author has disabled quoting on this post', }, + quote_followers_only: { + id: 'status.quote_followers_only', + defaultMessage: 'Only followers can quote this post', + }, + quote_manual_review: { + id: 'status.quote_manual_review', + defaultMessage: 'Author will manually review', + }, quote_private: { id: 'status.quote_private', defaultMessage: 'Private posts cannot be quoted', @@ -63,6 +71,10 @@ const messages = defineMessages({ id: 'status.cannot_reblog', defaultMessage: 'This post cannot be boosted', }, + request_quote: { + id: 'status.request_quote', + defaultMessage: 'Request to quote', + }, }); interface ReblogButtonProps { @@ -79,13 +91,21 @@ export const StatusReblogButton: FC = ({ const statusState = useAppSelector((state) => selectStatusState(state, status), ); - const { isLoggedIn, isReblogged, isReblogAllowed, isQuoteAllowed } = - statusState; + const { + isLoggedIn, + isReblogged, + isReblogAllowed, + isQuoteAutomaticallyAccepted, + isQuoteManuallyAccepted, + } = statusState; const { iconComponent } = useMemo( () => reblogIconText(statusState), [statusState], ); - const disabled = !isQuoteAllowed && !isReblogAllowed; + const disabled = + !isQuoteAutomaticallyAccepted && + !isQuoteManuallyAccepted && + !isReblogAllowed; const dispatch = useAppDispatch(); const statusId = status.get('id') as string; @@ -320,9 +340,15 @@ const selectStatusState = createAppSelector( status.get('visibility') === 'private', isReblogged: !!status.get('reblogged'), isReblogAllowed: isPublic || isMineAndPrivate, - isQuoteAllowed: + isQuoteAutomaticallyAccepted: status.getIn(['quote_approval', 'current_user']) === 'automatic' && (isPublic || isMineAndPrivate), + isQuoteManuallyAccepted: + status.getIn(['quote_approval', 'current_user']) === 'manual' && + (isPublic || isMineAndPrivate), + isQuoteFollowersOnly: + status.getIn(['quote_approval', 'automatic', 0]) === 'followers' || + status.getIn(['quote_approval', 'manual', 0]) === 'followers', }; }, ); @@ -364,7 +390,9 @@ function reblogIconText({ function quoteIconText({ isMine, - isQuoteAllowed, + isQuoteAutomaticallyAccepted, + isQuoteManuallyAccepted, + isQuoteFollowersOnly, isPublic, }: StatusState): IconText { const iconText: IconText = { @@ -372,12 +400,22 @@ function quoteIconText({ iconComponent: FormatQuote, }; - if (!isQuoteAllowed || (!isPublic && !isMine)) { - iconText.meta = !isQuoteAllowed - ? messages.quote_cannot - : messages.quote_private; - iconText.iconComponent = FormatQuoteOff; + if (!isPublic && !isMine) { iconText.disabled = true; + iconText.iconComponent = FormatQuoteOff; + iconText.meta = messages.quote_private; + } else if (isQuoteAutomaticallyAccepted) { + iconText.title = messages.quote; + } else if (isQuoteManuallyAccepted) { + iconText.title = messages.request_quote; + iconText.meta = messages.quote_manual_review; + } else { + iconText.disabled = true; + iconText.iconComponent = FormatQuoteOff; + iconText.meta = isQuoteFollowersOnly + ? messages.quote_followers_only + : messages.quote_cannot; } + return iconText; } diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 57a45c2b64b..0adeaf0896d 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -898,6 +898,8 @@ "status.quote_error.pending_approval": "Post pending", "status.quote_error.pending_approval_popout.body": "Quotes shared across the Fediverse may take time to display, as different servers have different protocols.", "status.quote_error.pending_approval_popout.title": "Pending quote? Remain calm", + "status.quote_followers_only": "Only followers can quote this post", + "status.quote_manual_review": "Author will manually review", "status.quote_policy_change": "Change who can quote", "status.quote_post_author": "Quoted a post by @{name}", "status.quote_private": "Private posts cannot be quoted", @@ -916,6 +918,7 @@ "status.reply": "Reply", "status.replyAll": "Reply to thread", "status.report": "Report @{name}", + "status.request_quote": "Request to quote", "status.revoke_quote": "Remove my post from @{name}’s post", "status.sensitive_warning": "Sensitive content", "status.share": "Share",