From 63574bd275edfb7b6e277abef2df8223550f271d Mon Sep 17 00:00:00 2001 From: Echo Date: Tue, 29 Sep 2026 15:28:34 +0000 Subject: [PATCH] Composer redesign: Sensitive field prevent from submitting and change label (#40749) --- .../features/compose/redesign/index.tsx | 44 ++----------- .../features/compose/redesign/sensitive.tsx | 63 +++++++++++++++++++ app/javascript/mastodon/locales/en.json | 2 +- 3 files changed, 69 insertions(+), 40 deletions(-) create mode 100644 app/javascript/mastodon/features/compose/redesign/sensitive.tsx diff --git a/app/javascript/mastodon/features/compose/redesign/index.tsx b/app/javascript/mastodon/features/compose/redesign/index.tsx index 628c9f18084..9cef2cecb09 100644 --- a/app/javascript/mastodon/features/compose/redesign/index.tsx +++ b/app/javascript/mastodon/features/compose/redesign/index.tsx @@ -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<

)} - {sensitive && ( - - )} + !!state.compose.get('spoiler')); - useEffect(() => { - if (!isSensitive) { - dispatch(requestComposerFocus()); - } - }, [isSensitive, dispatch]); - const onSensitiveChange = useCallback(() => { dispatch(changeComposeSpoilerness()); }, [dispatch]); - const onSensitiveTextChange: React.ChangeEventHandler = - 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, }; } diff --git a/app/javascript/mastodon/features/compose/redesign/sensitive.tsx b/app/javascript/mastodon/features/compose/redesign/sensitive.tsx new file mode 100644 index 00000000000..2971089ca61 --- /dev/null +++ b/app/javascript/mastodon/features/compose/redesign/sensitive.tsx @@ -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 = useCallback( + (event) => { + dispatch(changeComposeSpoilerText(event.target.value)); + }, + [dispatch], + ); + const onKeyDown: React.KeyboardEventHandler = useCallback( + (event) => { + const key = normalizeKey(event.key); + if (key === 'enter') { + event.preventDefault(); + dispatch(requestComposerFocus()); + return false; + } + return; + }, + [dispatch], + ); + if (!sensitive) { + return null; + } + return ( + + ); +}; diff --git a/app/javascript/mastodon/locales/en.json b/app/javascript/mastodon/locales/en.json index 823cd8d6ca3..25d05f9237c 100644 --- a/app/javascript/mastodon/locales/en.json +++ b/app/javascript/mastodon/locales/en.json @@ -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",