[Glitch] Show hint explaining post visibility when quoting a "quiet public" post

Port cf20c5db9c to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
This commit is contained in:
diondiondion
2025-09-09 14:43:23 +02:00
committed by Claire
parent 4b85fcabff
commit 1bb92520d6
7 changed files with 108 additions and 10 deletions

View File

@@ -16,6 +16,7 @@ import type { Status } from '../models/status';
import { showAlert } from './alerts';
import { focusCompose } from './compose';
import { openModal } from './modal';
const messages = defineMessages({
quoteErrorUpload: {
@@ -110,8 +111,16 @@ export const quoteCompose = createAppThunk(
export const quoteComposeByStatus = createAppThunk(
(status: Status, { dispatch, getState }) => {
const composeState = getState().compose;
const state = getState();
const composeState = state.compose;
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')) {
dispatch(showAlert({ message: messages.quoteErrorPoll }));
@@ -131,6 +140,16 @@ export const quoteComposeByStatus = createAppThunk(
status.getIn(['quote_approval', 'current_user']) !== 'manual'
) {
dispatch(showAlert({ message: messages.quoteErrorUnauthorized }));
} else if (
status.get('visibility') === 'unlisted' &&
!wasQuietPostHintModalDismissed
) {
dispatch(
openModal({
modalType: 'CONFIRM_QUIET_QUOTE',
modalProps: { status },
}),
);
} else {
dispatch(quoteCompose(status));
}

View File

@@ -79,10 +79,12 @@ const visibilityOptions = {
const PrivacyModalButton: FC<PrivacyDropdownProps> = ({ disabled = false }) => {
const intl = useIntl();
const { visibility, quotePolicy } = useAppSelector((state) => ({
visibility: state.compose.get('privacy') as StatusVisibility,
quotePolicy: state.compose.get('quote_policy') as ApiQuotePolicy,
}));
const quotePolicy = useAppSelector(
(state) => state.compose.get('quote_policy') as ApiQuotePolicy,
);
const visibility = useAppSelector(
(state) => state.compose.get('privacy') as StatusVisibility,
);
const { icon, iconComponent } = useMemo(() => {
const option = visibilityOptions[visibility];

View File

@@ -51,10 +51,6 @@ export const ConfirmationModal: React.FC<
onSecondary?.();
}, [onClose, onSecondary]);
const handleCancel = useCallback(() => {
onClose();
}, [onClose]);
return (
<div className='modal-root__modal safety-action-modal'>
<div className='safety-action-modal__top'>
@@ -66,7 +62,7 @@ export const ConfirmationModal: React.FC<
<div className='safety-action-modal__bottom'>
<div className='safety-action-modal__actions'>
<button onClick={handleCancel} className='link-button'>
<button onClick={onClose} className='link-button'>
{cancel ?? (
<FormattedMessage
id='confirmation_modal.cancel'

View File

@@ -11,3 +11,4 @@ export { ConfirmLogOutModal } from './log_out';
export { ConfirmFollowToListModal } from './follow_to_list';
export { ConfirmMissingAltTextModal } from './missing_alt_text';
export { ConfirmRevokeQuoteModal } from './revoke_quote';
export { QuietPostQuoteInfoModal } from './quiet_post_quote_info';

View File

@@ -0,0 +1,77 @@
import { useCallback } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { quoteCompose } from '@/flavours/glitch/actions/compose_typed';
import { closeModal } from '@/flavours/glitch/actions/modal';
import { changeSetting } from '@/flavours/glitch/actions/settings';
import type { Status } from '@/flavours/glitch/models/status';
import { useAppDispatch } from '@/flavours/glitch/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}
/>
);
};

View File

@@ -39,6 +39,7 @@ import {
ConfirmFollowToListModal,
ConfirmMissingAltTextModal,
ConfirmRevokeQuoteModal,
QuietPostQuoteInfoModal,
} from './confirmation_modals';
import DeprecatedSettingsModal from './deprecated_settings_modal';
import DoodleModal from './doodle_modal';
@@ -68,6 +69,7 @@ export const MODAL_COMPONENTS = {
'CONFIRM_FOLLOW_TO_LIST': () => Promise.resolve({ default: ConfirmFollowToListModal }),
'CONFIRM_MISSING_ALT_TEXT': () => Promise.resolve({ default: ConfirmMissingAltTextModal }),
'CONFIRM_REVOKE_QUOTE': () => Promise.resolve({ default: ConfirmRevokeQuoteModal }),
'CONFIRM_QUIET_QUOTE': () => Promise.resolve({ default: QuietPostQuoteInfoModal }),
'MUTE': MuteModal,
'BLOCK': BlockModal,
'DOMAIN_BLOCK': DomainBlockModal,

View File

@@ -125,6 +125,7 @@ const initialState = ImmutableMap({
'explore/statuses': false,
'explore/tags': false,
'notifications/remove_quote_hint': false,
'quote/quiet_post_hint': false,
}),
});