Compose: overhaul Spoiler feature

environments/review-cw-improve-4ktex0/deployments/1228
Alex Gleason 2022-10-31 16:19:51 -05:00
rodzic 9ea0b9cdbe
commit f51f2984a5
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 7211D1F99744FBB7
4 zmienionych plików z 93 dodań i 35 usunięć

Wyświetl plik

@ -45,7 +45,7 @@ const textAtCursorMatchesToken = (str: string, caretPosition: number, searchToke
}
};
interface IAutosuggestInput extends Pick<React.HTMLAttributes<HTMLInputElement>, 'onChange' | 'onKeyUp' | 'onKeyDown'> {
export interface IAutosuggestInput extends Pick<React.HTMLAttributes<HTMLInputElement>, 'onChange' | 'onKeyUp' | 'onKeyDown'> {
value: string,
suggestions: ImmutableList<any>,
disabled?: boolean,

Wyświetl plik

@ -10,7 +10,6 @@ import {
clearComposeSuggestions,
fetchComposeSuggestions,
selectComposeSuggestion,
changeComposeSpoilerText,
insertEmojiCompose,
uploadCompose,
} from 'soapbox/actions/compose';
@ -38,6 +37,7 @@ import UploadButtonContainer from '../containers/upload_button_container';
import WarningContainer from '../containers/warning_container';
import { countableText } from '../util/counter';
import SpoilerInput from './spoiler-input';
import TextCharacterCounter from './text_character_counter';
import VisualCharacterCounter from './visual_character_counter';
@ -48,7 +48,7 @@ const allowedAroundShortCode = '><\u0085\u0020\u00a0\u1680\u2000\u2001\u2002\u20
const messages = defineMessages({
placeholder: { id: 'compose_form.placeholder', defaultMessage: 'What\'s on your mind?' },
pollPlaceholder: { id: 'compose_form.poll_placeholder', defaultMessage: 'Add a poll topic...' },
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here' },
spoiler_placeholder: { id: 'compose_form.spoiler_placeholder', defaultMessage: 'Write your warning here (optional)' },
publish: { id: 'compose_form.publish', defaultMessage: 'Post' },
publishLoud: { id: 'compose_form.publish_loud', defaultMessage: '{publish}!' },
message: { id: 'compose_form.message', defaultMessage: 'Message' },
@ -165,10 +165,6 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
dispatch(selectComposeSuggestion(id, tokenStart, token, value, ['spoiler_text']));
};
const handleChangeSpoilerText: React.ChangeEventHandler<HTMLInputElement> = (e) => {
dispatch(changeComposeSpoilerText(id, e.target.value));
};
const setCursor = (start: number, end: number = start) => {
if (!autosuggestTextareaRef.current?.textarea) return;
autosuggestTextareaRef.current.textarea.setSelectionRange(start, end);
@ -265,7 +261,7 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
}
return (
<Stack className='w-full' space={1} ref={formRef} onClick={handleClick}>
<Stack className='w-full' space={4} ref={formRef} onClick={handleClick}>
{scheduledStatusCount > 0 && (
<Warning
message={(
@ -291,30 +287,6 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
{!shouldCondense && <ReplyMentions composeId={id} />}
<div
className={classNames({
'relative transition-height': true,
'hidden': !spoiler,
})}
>
<AutosuggestInput
placeholder={intl.formatMessage(messages.spoiler_placeholder)}
value={spoilerText}
onChange={handleChangeSpoilerText}
onKeyDown={handleKeyDown}
disabled={!spoiler}
ref={spoilerTextRef}
suggestions={suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSpoilerSuggestionSelected}
searchTokens={[':']}
id='cw-spoiler-input'
className='border-none shadow-none px-0 py-2 text-base'
autoFocus
/>
</div>
<AutosuggestTextarea
ref={(isModalOpen && shouldCondense) ? undefined : autosuggestTextareaRef}
placeholder={intl.formatMessage(hasPoll ? messages.pollPlaceholder : messages.placeholder)}
@ -334,11 +306,18 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
>
{
!condensed &&
<div className='compose-form__modifiers'>
<Stack space={4} className='compose-form__modifiers'>
<UploadForm composeId={id} />
<PollForm composeId={id} />
<ScheduleFormContainer composeId={id} />
</div>
<SpoilerInput
composeId={id}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSpoilerSuggestionSelected}
/>
</Stack>
}
</AutosuggestTextarea>

Wyświetl plik

@ -0,0 +1,79 @@
import classNames from 'clsx';
import React from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { changeComposeSpoilerness, 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' },
});
interface ISpoilerInput extends Pick<IAutosuggestInput, 'onSuggestionsFetchRequested' | 'onSuggestionsClearRequested' | 'onSuggestionSelected'> {
composeId: string extends 'default' ? never : string,
}
/** Text input for content warning in composer. */
const SpoilerInput: React.FC<ISpoilerInput> = ({
composeId,
onSuggestionsFetchRequested,
onSuggestionsClearRequested,
onSuggestionSelected,
}) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const compose = useCompose(composeId);
const handleChangeSpoilerText: React.ChangeEventHandler<HTMLInputElement> = (e) => {
dispatch(changeComposeSpoilerText(composeId, e.target.value));
};
const handleRemove = () => {
dispatch(changeComposeSpoilerness(composeId));
};
return (
<Stack
space={4}
className={classNames({
'relative transition-height': true,
'hidden': !compose.spoiler,
})}
>
<Divider />
<Stack space={2}>
<Text weight='medium'>
{intl.formatMessage(messages.title)}
</Text>
<AutosuggestInput
placeholder={intl.formatMessage(messages.placeholder)}
value={compose.spoiler_text}
onChange={handleChangeSpoilerText}
disabled={!compose.spoiler}
suggestions={compose.suggestions}
onSuggestionsFetchRequested={onSuggestionsFetchRequested}
onSuggestionsClearRequested={onSuggestionsClearRequested}
onSuggestionSelected={onSuggestionSelected}
searchTokens={[':']}
id='cw-spoiler-input'
className='rounded-md dark:!bg-transparent !bg-transparent'
autoFocus
/>
<div className='text-center'>
<button className='text-danger-500' onClick={handleRemove}>
{intl.formatMessage(messages.remove)}
</button>
</div>
</Stack>
</Stack>
);
};
export default SpoilerInput;

Wyświetl plik

@ -288,7 +288,7 @@
"compose_form.sensitive.unmarked": "Media is not marked as sensitive",
"compose_form.spoiler.marked": "Text is hidden behind warning",
"compose_form.spoiler.unmarked": "Text is not hidden",
"compose_form.spoiler_placeholder": "Write your warning here",
"compose_form.spoiler_placeholder": "Write your warning here (optional)",
"confirmation_modal.cancel": "Cancel",
"confirmations.admin.deactivate_user.confirm": "Deactivate @{name}",
"confirmations.admin.deactivate_user.heading": "Deactivate @{acct}",