mirror of
https://github.com/mastodon/mastodon.git
synced 2025-10-06 09:02:43 +00:00
Show hint explaining post visibility when quoting a "quiet public" post (#36065)
This commit is contained in:
parent
3c79c512fe
commit
cf20c5db9c
|
@ -16,6 +16,7 @@ import type { Status } from '../models/status';
|
||||||
|
|
||||||
import { showAlert } from './alerts';
|
import { showAlert } from './alerts';
|
||||||
import { focusCompose } from './compose';
|
import { focusCompose } from './compose';
|
||||||
|
import { openModal } from './modal';
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
quoteErrorUpload: {
|
quoteErrorUpload: {
|
||||||
|
@ -110,8 +111,16 @@ export const quoteCompose = createAppThunk(
|
||||||
|
|
||||||
export const quoteComposeByStatus = createAppThunk(
|
export const quoteComposeByStatus = createAppThunk(
|
||||||
(status: Status, { dispatch, getState }) => {
|
(status: Status, { dispatch, getState }) => {
|
||||||
const composeState = getState().compose;
|
const state = getState();
|
||||||
|
const composeState = state.compose;
|
||||||
const mediaAttachments = composeState.get('media_attachments');
|
const mediaAttachments = composeState.get('media_attachments');
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
||||||
|
const wasQuietPostHintModalDismissed: boolean =
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||||
|
state.settings.getIn(
|
||||||
|
['dismissed_banners', 'quote/quiet_post_hint'],
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
if (composeState.get('poll')) {
|
if (composeState.get('poll')) {
|
||||||
dispatch(showAlert({ message: messages.quoteErrorPoll }));
|
dispatch(showAlert({ message: messages.quoteErrorPoll }));
|
||||||
|
@ -131,6 +140,16 @@ export const quoteComposeByStatus = createAppThunk(
|
||||||
status.getIn(['quote_approval', 'current_user']) !== 'manual'
|
status.getIn(['quote_approval', 'current_user']) !== 'manual'
|
||||||
) {
|
) {
|
||||||
dispatch(showAlert({ message: messages.quoteErrorUnauthorized }));
|
dispatch(showAlert({ message: messages.quoteErrorUnauthorized }));
|
||||||
|
} else if (
|
||||||
|
status.get('visibility') === 'unlisted' &&
|
||||||
|
!wasQuietPostHintModalDismissed
|
||||||
|
) {
|
||||||
|
dispatch(
|
||||||
|
openModal({
|
||||||
|
modalType: 'CONFIRM_QUIET_QUOTE',
|
||||||
|
modalProps: { status },
|
||||||
|
}),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
dispatch(quoteCompose(status));
|
dispatch(quoteCompose(status));
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,10 +79,12 @@ const visibilityOptions = {
|
||||||
const PrivacyModalButton: FC<PrivacyDropdownProps> = ({ disabled = false }) => {
|
const PrivacyModalButton: FC<PrivacyDropdownProps> = ({ disabled = false }) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const { visibility, quotePolicy } = useAppSelector((state) => ({
|
const quotePolicy = useAppSelector(
|
||||||
visibility: state.compose.get('privacy') as StatusVisibility,
|
(state) => state.compose.get('quote_policy') as ApiQuotePolicy,
|
||||||
quotePolicy: state.compose.get('quote_policy') as ApiQuotePolicy,
|
);
|
||||||
}));
|
const visibility = useAppSelector(
|
||||||
|
(state) => state.compose.get('privacy') as StatusVisibility,
|
||||||
|
);
|
||||||
|
|
||||||
const { icon, iconComponent } = useMemo(() => {
|
const { icon, iconComponent } = useMemo(() => {
|
||||||
const option = visibilityOptions[visibility];
|
const option = visibilityOptions[visibility];
|
||||||
|
|
|
@ -43,10 +43,6 @@ export const ConfirmationModal: React.FC<
|
||||||
onSecondary?.();
|
onSecondary?.();
|
||||||
}, [onClose, onSecondary]);
|
}, [onClose, onSecondary]);
|
||||||
|
|
||||||
const handleCancel = useCallback(() => {
|
|
||||||
onClose();
|
|
||||||
}, [onClose]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='modal-root__modal safety-action-modal'>
|
<div className='modal-root__modal safety-action-modal'>
|
||||||
<div className='safety-action-modal__top'>
|
<div className='safety-action-modal__top'>
|
||||||
|
@ -58,7 +54,7 @@ export const ConfirmationModal: React.FC<
|
||||||
|
|
||||||
<div className='safety-action-modal__bottom'>
|
<div className='safety-action-modal__bottom'>
|
||||||
<div className='safety-action-modal__actions'>
|
<div className='safety-action-modal__actions'>
|
||||||
<button onClick={handleCancel} className='link-button'>
|
<button onClick={onClose} className='link-button'>
|
||||||
{cancel ?? (
|
{cancel ?? (
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
id='confirmation_modal.cancel'
|
id='confirmation_modal.cancel'
|
||||||
|
|
|
@ -11,3 +11,4 @@ export { ConfirmLogOutModal } from './log_out';
|
||||||
export { ConfirmFollowToListModal } from './follow_to_list';
|
export { ConfirmFollowToListModal } from './follow_to_list';
|
||||||
export { ConfirmMissingAltTextModal } from './missing_alt_text';
|
export { ConfirmMissingAltTextModal } from './missing_alt_text';
|
||||||
export { ConfirmRevokeQuoteModal } from './revoke_quote';
|
export { ConfirmRevokeQuoteModal } from './revoke_quote';
|
||||||
|
export { QuietPostQuoteInfoModal } from './quiet_post_quote_info';
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
import { defineMessages, useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { quoteCompose } from '@/mastodon/actions/compose_typed';
|
||||||
|
import { closeModal } from '@/mastodon/actions/modal';
|
||||||
|
import { changeSetting } from '@/mastodon/actions/settings';
|
||||||
|
import type { Status } from '@/mastodon/models/status';
|
||||||
|
import { useAppDispatch } from '@/mastodon/store';
|
||||||
|
|
||||||
|
import { ConfirmationModal } from './confirmation_modal';
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
title: {
|
||||||
|
id: 'confirmations.quiet_post_quote_info.title',
|
||||||
|
defaultMessage: 'Quoting quiet public posts',
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
id: 'confirmations.quiet_post_quote_info.message',
|
||||||
|
defaultMessage:
|
||||||
|
'When quoting a quiet public post, your post will be hidden from trending timelines.',
|
||||||
|
},
|
||||||
|
got_it: {
|
||||||
|
id: 'confirmations.quiet_post_quote_info.got_it',
|
||||||
|
defaultMessage: 'Got it',
|
||||||
|
},
|
||||||
|
dismiss: {
|
||||||
|
id: 'confirmations.quiet_post_quote_info.dismiss',
|
||||||
|
defaultMessage: "Don't remind me again",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [1] Since we only want this modal to have two buttons – "Don't ask again" and
|
||||||
|
* "Got it" – , we have to use the `onClose` handler to handle the "Don't ask again"
|
||||||
|
* functionality. Because of this, we need to set `closeWhenConfirm` to false and
|
||||||
|
* close the modal manually.
|
||||||
|
* This prevents the modal from being dismissed permanently when just confirming.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export const QuietPostQuoteInfoModal: React.FC<{ status: Status }> = ({
|
||||||
|
status,
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const confirm = useCallback(() => {
|
||||||
|
dispatch(quoteCompose(status));
|
||||||
|
// [1]
|
||||||
|
dispatch(
|
||||||
|
closeModal({ modalType: 'CONFIRM_QUIET_QUOTE', ignoreFocus: true }),
|
||||||
|
);
|
||||||
|
}, [dispatch, status]);
|
||||||
|
|
||||||
|
const dismiss = useCallback(() => {
|
||||||
|
dispatch(quoteCompose(status));
|
||||||
|
dispatch(
|
||||||
|
changeSetting(['dismissed_banners', 'quote/quiet_post_hint'], true),
|
||||||
|
);
|
||||||
|
// [1]
|
||||||
|
dispatch(
|
||||||
|
closeModal({ modalType: 'CONFIRM_QUIET_QUOTE', ignoreFocus: true }),
|
||||||
|
);
|
||||||
|
}, [dispatch, status]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ConfirmationModal
|
||||||
|
closeWhenConfirm={false} // [1]
|
||||||
|
title={intl.formatMessage(messages.title)}
|
||||||
|
message={intl.formatMessage(messages.message)}
|
||||||
|
confirm={intl.formatMessage(messages.got_it)}
|
||||||
|
cancel={intl.formatMessage(messages.dismiss)}
|
||||||
|
onConfirm={confirm}
|
||||||
|
onClose={dismiss}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
|
@ -38,6 +38,7 @@ import {
|
||||||
ConfirmFollowToListModal,
|
ConfirmFollowToListModal,
|
||||||
ConfirmMissingAltTextModal,
|
ConfirmMissingAltTextModal,
|
||||||
ConfirmRevokeQuoteModal,
|
ConfirmRevokeQuoteModal,
|
||||||
|
QuietPostQuoteInfoModal,
|
||||||
} from './confirmation_modals';
|
} from './confirmation_modals';
|
||||||
import { ImageModal } from './image_modal';
|
import { ImageModal } from './image_modal';
|
||||||
import MediaModal from './media_modal';
|
import MediaModal from './media_modal';
|
||||||
|
@ -62,6 +63,7 @@ export const MODAL_COMPONENTS = {
|
||||||
'CONFIRM_FOLLOW_TO_LIST': () => Promise.resolve({ default: ConfirmFollowToListModal }),
|
'CONFIRM_FOLLOW_TO_LIST': () => Promise.resolve({ default: ConfirmFollowToListModal }),
|
||||||
'CONFIRM_MISSING_ALT_TEXT': () => Promise.resolve({ default: ConfirmMissingAltTextModal }),
|
'CONFIRM_MISSING_ALT_TEXT': () => Promise.resolve({ default: ConfirmMissingAltTextModal }),
|
||||||
'CONFIRM_REVOKE_QUOTE': () => Promise.resolve({ default: ConfirmRevokeQuoteModal }),
|
'CONFIRM_REVOKE_QUOTE': () => Promise.resolve({ default: ConfirmRevokeQuoteModal }),
|
||||||
|
'CONFIRM_QUIET_QUOTE': () => Promise.resolve({ default: QuietPostQuoteInfoModal }),
|
||||||
'MUTE': MuteModal,
|
'MUTE': MuteModal,
|
||||||
'BLOCK': BlockModal,
|
'BLOCK': BlockModal,
|
||||||
'DOMAIN_BLOCK': DomainBlockModal,
|
'DOMAIN_BLOCK': DomainBlockModal,
|
||||||
|
|
|
@ -239,6 +239,10 @@
|
||||||
"confirmations.missing_alt_text.secondary": "Post anyway",
|
"confirmations.missing_alt_text.secondary": "Post anyway",
|
||||||
"confirmations.missing_alt_text.title": "Add alt text?",
|
"confirmations.missing_alt_text.title": "Add alt text?",
|
||||||
"confirmations.mute.confirm": "Mute",
|
"confirmations.mute.confirm": "Mute",
|
||||||
|
"confirmations.quiet_post_quote_info.dismiss": "Don't remind me again",
|
||||||
|
"confirmations.quiet_post_quote_info.got_it": "Got it",
|
||||||
|
"confirmations.quiet_post_quote_info.message": "When quoting a quiet public post, your post will be hidden from trending timelines.",
|
||||||
|
"confirmations.quiet_post_quote_info.title": "Quoting quiet public posts",
|
||||||
"confirmations.redraft.confirm": "Delete & redraft",
|
"confirmations.redraft.confirm": "Delete & redraft",
|
||||||
"confirmations.redraft.message": "Are you sure you want to delete this post and re-draft it? Favorites and boosts will be lost, and replies to the original post will be orphaned.",
|
"confirmations.redraft.message": "Are you sure you want to delete this post and re-draft it? Favorites and boosts will be lost, and replies to the original post will be orphaned.",
|
||||||
"confirmations.redraft.title": "Delete & redraft post?",
|
"confirmations.redraft.title": "Delete & redraft post?",
|
||||||
|
|
|
@ -118,6 +118,7 @@ const initialState = ImmutableMap({
|
||||||
'explore/statuses': false,
|
'explore/statuses': false,
|
||||||
'explore/tags': false,
|
'explore/tags': false,
|
||||||
'notifications/remove_quote_hint': false,
|
'notifications/remove_quote_hint': false,
|
||||||
|
'quote/quiet_post_hint': false,
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user