Composer redesign: Sensitive field prevent from submitting and change label (#40749)

This commit is contained in:
Echo
2026-09-29 15:28:34 +00:00
committed by GitHub
parent e8170d6d92
commit 63574bd275
3 changed files with 69 additions and 40 deletions

View File

@@ -1,7 +1,7 @@
import type React from 'react';
import { useCallback, useEffect, useId } from 'react';
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
import { FormattedMessage } from 'react-intl';
import classNames from 'classnames';
@@ -9,17 +9,14 @@ import { FlagIcon, LockSimpleOpenIcon } from '@phosphor-icons/react';
import {
changeComposeSpoilerness,
changeComposeSpoilerText,
insertEmojiCompose,
} from '@/mastodon/actions/compose';
import { ToggleButton } from '@/mastodon/components/button/redesign';
import { TextInputField } from '@/mastodon/components/form_fields/redesign';
import { normalizeKey } from '@/mastodon/components/hotkeys/utils';
import { Icon, useIconWeight } from '@/mastodon/components/icon';
import {
closeComposer,
getComposerTextarea,
requestComposerFocus,
submitComposer,
} from '@/mastodon/reducers/slices/composer';
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
@@ -36,17 +33,11 @@ import {
selectComposeSensitive,
selectComposeType,
} from './selectors';
import { ComposeSensitiveField } from './sensitive';
import classes from './styles.module.scss';
import { ComposeTextarea } from './textarea';
import { ComposeVisibility } from './visibility';
const messages = defineMessages({
sensitiveText: {
id: 'compose.sensitive.text',
defaultMessage: 'Sensitive content description',
},
});
interface RedesignComposeFormProps {
autoFocus?: boolean;
className?: string;
@@ -58,12 +49,11 @@ export const RedesignComposeForm: React.FC<
RedesignComposeFormProps & React.ComponentPropsWithRef<'form'>
> = ({ autoFocus, className, noMinimize, redirectOnSuccess, ...props }) => {
const type = useAppSelector(selectComposeType);
const { sensitive, sensitiveText } = useAppSelector(selectComposeSensitive);
const { sensitive } = useAppSelector(selectComposeSensitive);
const { onSensitiveChange, onSensitiveTextChange, onEmojiPick, onSubmit } =
const { onSensitiveChange, onEmojiPick, onSubmit } =
useComposeHandlers(redirectOnSuccess);
const intl = useIntl();
const titleId = useId();
const sensitiveIcon = useIconWeight(FlagIcon, sensitive && 'fill');
@@ -110,15 +100,7 @@ export const RedesignComposeForm: React.FC<
</p>
)}
{sensitive && (
<TextInputField
label={intl.formatMessage(messages.sensitiveText)}
value={sensitiveText}
onChange={onSensitiveTextChange}
// eslint-disable-next-line jsx-a11y/no-autofocus -- Focuses on open
autoFocus
/>
)}
<ComposeSensitiveField />
<ComposeTextarea
// eslint-disable-next-line jsx-a11y/no-autofocus
@@ -162,24 +144,9 @@ function useComposeHandlers(redirectOnSuccess?: boolean) {
};
}, [dispatch, isModalOpen]);
// Sensitive handling
const isSensitive = useAppSelector((state) => !!state.compose.get('spoiler'));
useEffect(() => {
if (!isSensitive) {
dispatch(requestComposerFocus());
}
}, [isSensitive, dispatch]);
const onSensitiveChange = useCallback(() => {
dispatch(changeComposeSpoilerness());
}, [dispatch]);
const onSensitiveTextChange: React.ChangeEventHandler<HTMLInputElement> =
useCallback(
(event) => {
dispatch(changeComposeSpoilerText(event.target.value));
},
[dispatch],
);
const onEmojiPick: OnEmojiPick = useCallback(
(emoji) => {
@@ -219,6 +186,5 @@ function useComposeHandlers(redirectOnSuccess?: boolean) {
onSubmit,
onEmojiPick,
onSensitiveChange,
onSensitiveTextChange,
};
}

View File

@@ -0,0 +1,63 @@
import { useCallback, useEffect } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { changeComposeSpoilerText } from '@/mastodon/actions/compose';
import { TextInputField } from '@/mastodon/components/form_fields';
import { normalizeKey } from '@/mastodon/components/hotkeys/utils';
import { requestComposerFocus } from '@/mastodon/reducers/slices/composer';
import { useAppDispatch, useAppSelector } from '@/mastodon/store';
import { selectComposeSensitive } from './selectors';
const messages = defineMessages({
sensitiveText: {
id: 'compose.sensitive.text',
defaultMessage: 'Content warning',
},
});
export const ComposeSensitiveField: React.FC = () => {
const { sensitive, sensitiveText } = useAppSelector(selectComposeSensitive);
const intl = useIntl();
const dispatch = useAppDispatch();
const isSensitive = useAppSelector((state) => !!state.compose.get('spoiler'));
useEffect(() => {
if (!isSensitive) {
dispatch(requestComposerFocus());
}
}, [isSensitive, dispatch]);
const onChange: React.ChangeEventHandler<HTMLInputElement> = useCallback(
(event) => {
dispatch(changeComposeSpoilerText(event.target.value));
},
[dispatch],
);
const onKeyDown: React.KeyboardEventHandler<HTMLInputElement> = useCallback(
(event) => {
const key = normalizeKey(event.key);
if (key === 'enter') {
event.preventDefault();
dispatch(requestComposerFocus());
return false;
}
return;
},
[dispatch],
);
if (!sensitive) {
return null;
}
return (
<TextInputField
label={intl.formatMessage(messages.sensitiveText)}
value={sensitiveText}
onChange={onChange}
onKeyDown={onKeyDown}
// eslint-disable-next-line jsx-a11y/no-autofocus -- Focuses on open
autoFocus
/>
);
};

View File

@@ -574,7 +574,7 @@
"compose.reply_private.title.new": "New private reply",
"compose.saved.body": "Post saved.",
"compose.sensitive": "Sensitive",
"compose.sensitive.text": "Sensitive content description",
"compose.sensitive.text": "Content warning",
"compose.switch_modal.back": "Back",
"compose.switch_modal.body": "Your message has limited visibility. If you convert to a post, it will switch to your default post visibility.",
"compose.switch_modal.continue": "Continue",