Handle sensitive and spoiler separately when writing a post

Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
This commit is contained in:
marcin mikołajczak
2024-08-24 00:45:45 +02:00
parent d33589d103
commit 604ebdd24a
9 changed files with 38 additions and 102 deletions

View File

@ -12,11 +12,10 @@ import {
selectComposeSuggestion,
uploadCompose,
} from 'soapbox/actions/compose';
import AutosuggestInput, { AutoSuggestion } from 'soapbox/components/autosuggest-input';
import { Button, HStack, Stack } from 'soapbox/components/ui';
import EmojiPickerDropdown from 'soapbox/features/emoji/containers/emoji-picker-dropdown-container';
import { ComposeEditor } from 'soapbox/features/ui/util/async-components';
import { useAppDispatch, useAppSelector, useCompose, useDraggedFiles, useFeatures, useInstance, usePrevious } from 'soapbox/hooks';
import { useAppDispatch, useAppSelector, useCompose, useDraggedFiles, useFeatures, useInstance } from 'soapbox/hooks';
import QuotedStatusContainer from '../containers/quoted-status-container';
import ReplyIndicatorContainer from '../containers/reply-indicator-container';
@ -41,6 +40,7 @@ import UploadForm from './upload-form';
import VisualCharacterCounter from './visual-character-counter';
import Warning from './warning';
import type { AutoSuggestion } from 'soapbox/components/autosuggest-input';
import type { Emoji } from 'soapbox/features/emoji';
const messages = defineMessages({
@ -77,7 +77,6 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
const features = useFeatures();
const {
spoiler,
spoiler_text: spoilerText,
privacy,
is_submitting: isSubmitting,
@ -90,17 +89,13 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
modified_language: modifiedLanguage,
} = compose;
const prevSpoiler = usePrevious(spoiler);
const hasPoll = !!compose.poll;
const isEditing = compose.id !== null;
const anyMedia = compose.media_attachments.size > 0;
const [composeFocused, setComposeFocused] = useState(false);
const firstRender = useRef(true);
const formRef = useRef<HTMLDivElement>(null);
const spoilerTextRef = useRef<AutosuggestInput>(null);
const editorRef = useRef<LexicalEditor>(null);
const { isDraggedOver } = useDraggedFiles(formRef);
@ -171,10 +166,6 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
dispatch(uploadCompose(id, files, intl));
};
const focusSpoilerInput = () => {
spoilerTextRef.current?.input?.focus();
};
useEffect(() => {
document.addEventListener('click', handleClick, true);
@ -183,16 +174,6 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
};
}, []);
useEffect(() => {
if (spoiler && firstRender.current) {
firstRender.current = false;
} else if (!spoiler && prevSpoiler) {
//
} else if (spoiler && !prevSpoiler) {
focusSpoilerInput();
}
}, [spoiler]);
const renderButtons = useCallback(() => (
<HStack alignItems='center' space={2}>
<UploadButtonContainer composeId={id} />
@ -208,14 +189,6 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
<UploadForm composeId={id} onSubmit={handleSubmit} />
<PollForm composeId={id} />
<SpoilerInput
composeId={id}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSpoilerSuggestionSelected}
ref={spoilerTextRef}
/>
<ScheduleForm composeId={id} />
</Stack>
);
@ -280,6 +253,13 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
</HStack>
)}
<SpoilerInput
composeId={id}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSpoilerSuggestionSelected}
/>
<div>
<Suspense>
<ComposeEditor

View File

@ -7,8 +7,8 @@ import { useAppDispatch, useCompose } from 'soapbox/hooks';
import ComposeFormButton from './compose-form-button';
const messages = defineMessages({
marked: { id: 'compose_form.spoiler.marked', defaultMessage: 'Text is hidden behind warning' },
unmarked: { id: 'compose_form.spoiler.unmarked', defaultMessage: 'Text is not hidden' },
marked: { id: 'compose_form.spoiler.marked', defaultMessage: 'Media is marked as sensitive' },
unmarked: { id: 'compose_form.spoiler.unmarked', defaultMessage: 'Media is not marked as sensitive' },
});
interface ISpoilerButton {
@ -19,7 +19,7 @@ const SpoilerButton: React.FC<ISpoilerButton> = ({ composeId }) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const active = useCompose(composeId).spoiler;
const active = useCompose(composeId).sensitive;
const onClick = () =>
dispatch(changeComposeSpoilerness(composeId));

View File

@ -1,16 +1,13 @@
import clsx from 'clsx';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { changeComposeSpoilerness, changeComposeSpoilerText } from 'soapbox/actions/compose';
import { changeComposeSpoilerText } from 'soapbox/actions/compose';
import AutosuggestInput, { IAutosuggestInput } from 'soapbox/components/autosuggest-input';
import { Divider, Stack, Text } from 'soapbox/components/ui';
import { useAppDispatch, useCompose } from 'soapbox/hooks';
const messages = defineMessages({
title: { id: 'compose_form.spoiler_title', defaultMessage: 'Sensitive content' },
placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here (optional)' },
remove: { id: 'compose_form.spoiler_remove', defaultMessage: 'Remove sensitive' },
placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Subject (optional)' },
});
interface ISpoilerInput extends Pick<IAutosuggestInput, 'onSuggestionsFetchRequested' | 'onSuggestionsClearRequested' | 'onSuggestionSelected'> {
@ -26,56 +23,28 @@ const SpoilerInput = React.forwardRef<AutosuggestInput, ISpoilerInput>(({
}, ref) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const { language, modified_language, spoiler, spoiler_text: spoilerText, spoilerTextMap, suggestions } = useCompose(composeId);
const { language, modified_language, spoiler_text: spoilerText, spoilerTextMap, suggestions } = useCompose(composeId);
const handleChangeSpoilerText: React.ChangeEventHandler<HTMLInputElement> = (e) => {
dispatch(changeComposeSpoilerText(composeId, e.target.value));
};
const handleRemove = () => {
dispatch(changeComposeSpoilerness(composeId));
};
const value = !modified_language || modified_language === language ? spoilerText : spoilerTextMap.get(modified_language, '');
return (
<Stack
space={4}
className={clsx({
'relative transition-height': true,
'hidden': !spoiler,
})}
>
<Divider />
<Stack space={2}>
<Text weight='medium'>
{intl.formatMessage(messages.title)}
</Text>
<AutosuggestInput
placeholder={intl.formatMessage(messages.placeholder)}
value={value}
onChange={handleChangeSpoilerText}
disabled={!spoiler}
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSuggestionSelected}
searchTokens={[':']}
id='cw-spoiler-input'
className='rounded-md !bg-transparent dark:!bg-transparent'
ref={ref}
autoFocus
/>
<div className='text-center'>
<button type='button' className='text-danger-500' onClick={handleRemove}>
{intl.formatMessage(messages.remove)}
</button>
</div>
</Stack>
</Stack>
<AutosuggestInput
placeholder={intl.formatMessage(messages.placeholder)}
value={value}
onChange={handleChangeSpoilerText}
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSuggestionSelected}
searchTokens={[':']}
id='cw-spoiler-input'
className='rounded-md !bg-transparent dark:!bg-transparent'
ref={ref}
/>
);
});