pl-fe: compose reducer cleanup

Signed-off-by: nicole mikołajczyk <git@mkljczk.pl>
This commit is contained in:
nicole mikołajczyk
2025-10-29 00:07:35 +01:00
parent 355b834c99
commit 45c262d02d
29 changed files with 220 additions and 227 deletions

View File

@@ -301,7 +301,7 @@ const handleComposeSubmit = (dispatch: AppDispatch, getState: () => RootState, c
const state = getState();
const accountUrl = selectOwnAccount(state)!.url;
const draftId = getState().compose[composeId]!.draft_id;
const draftId = getState().compose[composeId]!.draftId;
dispatch(submitComposeSuccess(composeId, data));
@@ -324,7 +324,7 @@ const handleComposeSubmit = (dispatch: AppDispatch, getState: () => RootState, c
};
const needsDescriptions = (state: RootState, composeId: string) => {
const media = state.compose[composeId]!.media_attachments;
const media = state.compose[composeId]!.mediaAttachments;
const missingDescriptionModal = useSettingsStore.getState().settings.missingDescriptionModal;
const hasMissing = media.filter(item => !item.description).length > 0;
@@ -333,12 +333,12 @@ const needsDescriptions = (state: RootState, composeId: string) => {
};
const validateSchedule = (state: RootState, composeId: string) => {
const schedule = state.compose[composeId]?.schedule;
if (!schedule) return true;
const scheduledAt = state.compose[composeId]?.scheduledAt;
if (!scheduledAt) return true;
const fiveMinutesFromNow = new Date(new Date().getTime() + 300000);
return schedule.getTime() > fiveMinutesFromNow.getTime() || (state.auth.client.features.scheduledStatusesBackwards && schedule.getTime() < new Date().getTime());
return scheduledAt.getTime() > fiveMinutesFromNow.getTime() || (state.auth.client.features.scheduledStatusesBackwards && scheduledAt.getTime() < new Date().getTime());
};
interface SubmitComposeOpts {
@@ -357,7 +357,7 @@ const submitCompose = (composeId: string, opts: SubmitComposeOpts = {}, preview
const compose = state.compose[composeId]!;
const status = compose.text;
const media = compose.media_attachments;
const media = compose.mediaAttachments;
const statusId = compose.id;
let to = compose.to;
const { forceImplicitAddressing } = useSettingsStore.getState().settings;
@@ -403,22 +403,22 @@ const submitCompose = (composeId: string, opts: SubmitComposeOpts = {}, preview
}
const idempotencyKey = compose.idempotencyKey;
const contentType = compose.content_type === 'wysiwyg' ? 'text/markdown' : compose.content_type;
const contentType = compose.contentType === 'wysiwyg' ? 'text/markdown' : compose.contentType;
const params: CreateStatusParams = {
status,
in_reply_to_id: compose.in_reply_to || undefined,
in_reply_to_id: compose.inReplyToId || undefined,
quote_id: compose.quote || undefined,
media_ids: media.map(item => item.id),
sensitive: compose.sensitive,
spoiler_text: compose.spoiler_text,
visibility: compose.privacy,
spoiler_text: compose.spoilerText,
visibility: compose.visibility,
content_type: contentType,
scheduled_at: preview ? undefined : compose.schedule?.toISOString(),
language: compose.language || compose.suggested_language || undefined,
scheduled_at: preview ? undefined : compose.scheduledAt?.toISOString(),
language: compose.language || compose.suggestedLanguage || undefined,
to: explicitAddressing && to.length ? to : undefined,
local_only: !compose.federated,
interaction_policy: ['public', 'unlisted', 'private'].includes(compose.privacy) && compose.interactionPolicy || undefined,
local_only: compose.local_only,
interaction_policy: ['public', 'unlisted', 'private'].includes(compose.visibility) && compose.interactionPolicy || undefined,
preview,
};
@@ -438,7 +438,7 @@ const submitCompose = (composeId: string, opts: SubmitComposeOpts = {}, preview
if (params.spoiler_text) {
params.spoiler_text_map = compose.spoilerTextMap;
params.spoiler_text_map[compose.language] = compose.spoiler_text;
params.spoiler_text_map[compose.language] = compose.spoilerText;
}
const poll = params.poll;
@@ -447,8 +447,8 @@ const submitCompose = (composeId: string, opts: SubmitComposeOpts = {}, preview
}
}
if (compose.privacy === 'group' && compose.group_id) {
params.group_id = compose.group_id;
if (compose.visibility === 'group' && compose.groupId) {
params.group_id = compose.groupId;
}
if (preview) {
@@ -504,7 +504,7 @@ const uploadCompose = (composeId: string, files: FileList, intl: IntlShape) =>
if (!isLoggedIn(getState)) return;
const attachmentLimit = getState().instance.configuration.statuses.max_media_attachments;
const media = getState().compose[composeId]?.media_attachments;
const media = getState().compose[composeId]?.mediaAttachments;
const progress = new Array(files.length).fill(0);
let total = Array.from(files).reduce((a, v) => a + v.size, 0);

View File

@@ -21,8 +21,8 @@ const messages = defineMessages({
const checkComposeContent = (compose?: Compose) =>
!!compose && [
compose.editorState && compose.editorState.length > 0,
compose.spoiler_text.length > 0,
compose.media_attachments.length > 0,
compose.spoilerText.length > 0,
compose.mediaAttachments.length > 0,
compose.poll !== null,
].some(check => check === true);
@@ -68,12 +68,12 @@ const ModalRoot: React.FC<IModalRoot> = ({ children, onCancel, onClose, type })
openModal('CONFIRM', {
heading: isEditing
? <FormattedMessage id='confirmations.cancel_editing.heading' defaultMessage='Cancel post editing' />
: compose.draft_id
: compose.draftId
? <FormattedMessage id='confirmations.cancel_draft.heading' defaultMessage='Discard draft changes' />
: <FormattedMessage id='confirmations.cancel.heading' defaultMessage='Discard post' />,
message: isEditing
? <FormattedMessage id='confirmations.cancel_editing.message' defaultMessage='Are you sure you want to discard the changes to this post? All changes will be lost.' />
: compose.draft_id
: compose.draftId
? <FormattedMessage id='confirmations.cancel_draft_editing.message' defaultMessage='Are you sure you want to discard the changes to this draft post? All changes will be lost.' />
: <FormattedMessage id='confirmations.cancel.message' defaultMessage='Are you sure you want to discard the currently composed post?' />,
confirm: intl.formatMessage(messages.confirm),

View File

@@ -20,7 +20,7 @@ const ClearLinkSuggestion = ({
handleReject,
}: IClearLinkSuggestion) => {
const compose = useCompose(composeId);
const suggestion = compose.clear_link_suggestion;
const suggestion = compose.clearLinkSuggestion;
if (!suggestion) return null;

View File

@@ -136,20 +136,20 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
const persistDraftStatus = usePersistDraftStatus();
const {
spoiler_text: spoilerText,
privacy,
is_submitting: isSubmitting,
is_changing_upload: isChangingUpload,
is_uploading: isUploading,
schedule: scheduledAt,
group_id: groupId,
spoilerText,
visibility,
isSubmitting,
isChangingUpload,
isUploading,
scheduledAt,
groupId,
text,
modified_language: modifiedLanguage,
modifiedLanguage,
} = compose;
const hasPoll = !!compose.poll;
const isEditing = compose.id !== null;
const anyMedia = compose.media_attachments.length > 0;
const anyMedia = compose.mediaAttachments.length > 0;
const [composeFocused, setComposeFocused] = useState(false);
@@ -246,7 +246,7 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
const onAcceptClearLinkSuggestion = (key: string) => {
const editor = editorRef.current;
const suggestion = compose.clear_link_suggestion;
const suggestion = compose.clearLinkSuggestion;
if (!editor || !suggestion) return;
editor.update(() => {
@@ -290,7 +290,7 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
</div>
), [features, id, anyMedia]);
const showModifiers = !condensed && (compose.media_attachments.length || compose.is_uploading || compose.poll?.options.length || compose.schedule);
const showModifiers = !condensed && (compose.mediaAttachments.length || compose.isUploading || compose.poll?.options.length || compose.scheduledAt);
const composeModifiers = showModifiers && (
<div className='⁂-compose-form__modifiers'>
@@ -305,14 +305,14 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
if (isEditing) {
publishText = intl.formatMessage(messages.saveChanges);
} else if (privacy === 'direct') {
} else if (visibility === 'direct') {
publishIcon = require('@phosphor-icons/core/regular/at.svg');
publishText = intl.formatMessage(messages.message);
} else if (privacy === 'private' || privacy === 'mutuals_only') {
} else if (visibility === 'private' || visibility === 'mutuals_only') {
publishIcon = require('@phosphor-icons/core/regular/lock.svg');
publishText = intl.formatMessage(messages.publish);
} else {
publishText = privacy !== 'unlisted' ? intl.formatMessage(messages.publishLoud, { publish: intl.formatMessage(messages.publish) }) : intl.formatMessage(messages.publish);
publishText = visibility !== 'unlisted' ? intl.formatMessage(messages.publishLoud, { publish: intl.formatMessage(messages.publish) }) : intl.formatMessage(messages.publish);
}
if (scheduledAt) {
@@ -351,7 +351,7 @@ const ComposeForm = <ID extends string>({ id, shouldCondense, autoFocus, clickab
onClick={handleClick}
onSubmit={handleSubmit}
>
{!!compose.in_reply_to && compose.approvalRequired && (
{!!compose.inReplyToId && compose.approvalRequired && (
<Warning
message={(
<FormattedMessage id='compose_form.approval_required' defaultMessage='The reply needs to be approved by the post author.' />

View File

@@ -27,7 +27,7 @@ const ContentTypeButton: React.FC<IContentTypeButton> = ({ composeId, compact })
const dispatch = useAppDispatch();
const instance = useInstance();
const contentType = useCompose(composeId).content_type;
const { contentType } = useCompose(composeId);
const handleChange = (contentType: string) => () => dispatch(changeComposeContentType(composeId, contentType));

View File

@@ -26,7 +26,7 @@ const HashtagCasingSuggestion = ({
const dispatch = useAppDispatch();
const compose = useCompose(composeId);
const suggestion = compose.hashtag_casing_suggestion;
const suggestion = compose.hashtagCasingSuggestion;
const onIgnore = () => {
dispatch(ignoreHashtagCasingSuggestion(composeId));

View File

@@ -25,9 +25,9 @@ const InteractionPolicyButton: React.FC<IInteractionPolicyButton> = ({ composeId
});
};
const { privacy, interactionPolicy } = useCompose(composeId);
const { visibility, interactionPolicy } = useCompose(composeId);
if (!['public', 'unlisted', 'private'].includes(privacy)) return null;
if (!['public', 'unlisted', 'private'].includes(visibility)) return null;
return (
<ComposeFormButton

View File

@@ -49,7 +49,7 @@ const getLanguageDropdown = (composeId: string): React.FC<ILanguageDropdown> =>
const {
language,
modified_language: modifiedLanguage,
modifiedLanguage,
textMap,
} = useCompose(composeId);
@@ -226,8 +226,8 @@ const LanguageDropdownButton: React.FC<ILanguageDropdownButton> = ({ composeId,
const {
language,
modified_language: modifiedLanguage,
suggested_language: suggestedLanguage,
modifiedLanguage,
suggestedLanguage,
textMap,
} = useCompose(composeId);

View File

@@ -23,7 +23,7 @@ const PollButton: React.FC<IPollButton> = ({ composeId, disabled }) => {
const compose = useCompose(composeId);
const unavailable = compose.is_uploading;
const unavailable = compose.isUploading;
const active = compose.poll !== null;
const onClick = () => {

View File

@@ -55,7 +55,7 @@ const Option: React.FC<IOption> = ({
const dispatch = useAppDispatch();
const intl = useIntl();
const { suggestions, modified_language: language } = useCompose(composeId);
const { suggestions, modifiedLanguage: language } = useCompose(composeId);
const handleOptionTitleChange = (event: React.ChangeEvent<HTMLInputElement>) => onChange(index, event.target.value);
@@ -120,7 +120,7 @@ const PollForm: React.FC<IPollForm> = ({ composeId }) => {
const intl = useIntl();
const { configuration } = useInstance();
const { poll, language, modified_language: modifiedLanguage } = useCompose(composeId);
const { poll, language, modifiedLanguage } = useCompose(composeId);
const options = !modifiedLanguage || modifiedLanguage === language ? poll?.options : poll?.options_map.map((option, key) => option[modifiedLanguage] || poll.options[key]);
const expiresIn = poll?.expires_in;

View File

@@ -137,9 +137,9 @@ const PrivacyDropdown: React.FC<IPrivacyDropdown> = ({
const { data: lists = [] } = useLists(getOrderedLists);
const { data: circles = [] } = useCircles(getOrderedLists);
const isReply = !!compose.in_reply_to;
const isReply = !!compose.inReplyToId;
const value = compose.privacy;
const value = compose.visibility;
const unavailable = compose.id;
const onChange = (value: string) => value && dispatch(changeComposeVisibility(composeId,
@@ -162,7 +162,7 @@ const PrivacyDropdown: React.FC<IPrivacyDropdown> = ({
text: intl.formatMessage(messages.local_short),
meta: intl.formatMessage(messages.local_long),
type: 'toggle',
checked: !compose.federated,
checked: compose.local_only,
onChange: () => dispatch(changeComposeFederated(composeId)),
});
@@ -175,7 +175,7 @@ const PrivacyDropdown: React.FC<IPrivacyDropdown> = ({
return null;
}
const text = compose.federated ? valueOption?.text : intl.formatMessage(messages.local, {
const text = compose.visibility ? valueOption?.text : intl.formatMessage(messages.local, {
privacy: valueOption?.text,
});

View File

@@ -16,7 +16,7 @@ const ReplyGroupIndicator = (props: IReplyGroupIndicator) => {
const getStatus = useCallback(makeGetStatus(), []);
const status = useAppSelector((state) => getStatus(state, { id: state.compose[composeId]?.in_reply_to! }));
const status = useAppSelector((state) => getStatus(state, { id: state.compose[composeId]?.inReplyToId! }));
const group = status?.group;
if (!group) {

View File

@@ -19,7 +19,7 @@ const ReplyMentions: React.FC<IReplyMentions> = ({ composeId }) => {
const { forceImplicitAddressing } = useSettings();
const explicitAddressing = features.createStatusExplicitAddressing && !forceImplicitAddressing;
if (!explicitAddressing || !compose.in_reply_to || !to) {
if (!explicitAddressing || !compose.inReplyToId || !to) {
return null;
}
@@ -31,7 +31,7 @@ const ReplyMentions: React.FC<IReplyMentions> = ({ composeId }) => {
});
};
if (!compose.parent_reblogged_by && to.length === 0) {
if (!compose.parentRebloggedById && to.length === 0) {
return null;
}

View File

@@ -23,7 +23,7 @@ const ScheduleButton: React.FC<IScheduleButton> = ({ composeId, disabled }) => {
const compose = useCompose(composeId);
const active = !!compose.schedule;
const active = !!compose.scheduledAt;
const unavailable = !!compose.id;
const handleClick = () => {

View File

@@ -32,7 +32,7 @@ const ScheduleForm: React.FC<IScheduleForm> = ({ composeId }) => {
const intl = useIntl();
const features = useFeatures();
const scheduledAt = useCompose(composeId).schedule;
const { scheduledAt } = useCompose(composeId);
const active = !!scheduledAt;
const onSchedule = (date: Date | null) => {

View File

@@ -24,13 +24,13 @@ const SpoilerInput: React.FC<ISpoilerInput> = ({
}) => {
const intl = useIntl();
const dispatch = useAppDispatch();
const { language, modified_language, spoiler_text: spoilerText, spoilerTextMap, suggestions } = useCompose(composeId);
const { language, modifiedLanguage, spoilerText, spoilerTextMap, suggestions } = useCompose(composeId);
const handleChangeSpoilerText: React.ChangeEventHandler<HTMLInputElement> = (e) => {
dispatch(changeComposeSpoilerText(composeId, e.target.value));
};
const value = !modified_language || modified_language === language ? spoilerText : spoilerTextMap[modified_language] || '';
const value = !modifiedLanguage || modifiedLanguage === language ? spoilerText : spoilerTextMap[modifiedLanguage] || '';
return (
<AutosuggestInput
@@ -45,7 +45,7 @@ const SpoilerInput: React.FC<ISpoilerInput> = ({
searchTokens={[':']}
id='cw-spoiler-input'
className='⁂-compose-form__spoiler-input'
lang={modified_language || undefined}
lang={modifiedLanguage || undefined}
/>
);
};

View File

@@ -17,7 +17,7 @@ interface IUploadForm {
const UploadForm: React.FC<IUploadForm> = ({ composeId, onSubmit }) => {
const dispatch = useAppDispatch();
const { is_uploading: isUploading, media_attachments: mediaAttachments } = useCompose(composeId);
const { isUploading, mediaAttachments } = useCompose(composeId);
const mediaIds = mediaAttachments.map((item) => item.id);

View File

@@ -9,12 +9,9 @@ interface IComposeUploadProgress {
/** File upload progress bar for post composer. */
const ComposeUploadProgress: React.FC<IComposeUploadProgress> = ({ composeId }) => {
const compose = useCompose(composeId);
const { isUploading, progress } = useCompose(composeId);
const active = compose.is_uploading;
const progress = compose.progress;
if (!active) {
if (!isUploading) {
return null;
}

View File

@@ -19,7 +19,7 @@ const UploadCompose: React.FC<IUploadCompose> = ({ composeId, id, onSubmit, onDr
const dispatch = useAppDispatch();
const { pleroma: { metadata: { description_limit: descriptionLimit } } } = useInstance();
const media = useCompose(composeId).media_attachments.find(item => item.id === id)!;
const media = useCompose(composeId).mediaAttachments.find(item => item.id === id)!;
const handleDescriptionChange = (description: string, position?: [number, number]) => {
return dispatch(changeUploadCompose(composeId, media.id, {

View File

@@ -15,7 +15,7 @@ interface IReplyIndicatorContainer {
const ReplyIndicatorContainer: React.FC<IReplyIndicatorContainer> = ({ composeId }) => {
const getStatus = useCallback(makeGetStatus(), []);
const { in_reply_to: inReplyToId, id: statusId } = useCompose(composeId);
const { inReplyToId, id: statusId } = useCompose(composeId);
const status = useAppSelector(state => getStatus(state, { id: inReplyToId! }));
const dispatch = useAppDispatch();

View File

@@ -14,13 +14,13 @@ interface IUploadButtonContainer {
const UploadButtonContainer: React.FC<IUploadButtonContainer> = ({ composeId }) => {
const dispatch = useAppDispatch();
const { is_uploading: disabled, resetFileKey } = useCompose(composeId);
const { isUploading, resetFileKey } = useCompose(composeId);
const onSelectFile = (files: FileList, intl: IntlShape) => {
dispatch(uploadCompose(composeId, files, intl));
};
return <UploadButton disabled={disabled} resetFileKey={resetFileKey} onSelectFile={onSelectFile} />;
return <UploadButton disabled={isUploading} resetFileKey={resetFileKey} onSelectFile={onSelectFile} />;
};
export { UploadButtonContainer as default };

View File

@@ -17,9 +17,9 @@ interface IWarningWrapper {
const WarningWrapper: React.FC<IWarningWrapper> = ({ composeId }) => {
const compose = useCompose(composeId);
const needsLockWarning = useAppSelector((state) => (compose.privacy === 'private' || compose.privacy === 'mutuals_only') && !selectOwnAccount(state)!.locked);
const hashtagWarning = (compose.privacy !== 'public' && compose.privacy !== 'group') && APPROX_HASHTAG_RE.test(compose.text);
const directMessageWarning = compose.privacy === 'direct';
const needsLockWarning = useAppSelector((state) => (compose.visibility === 'private' || compose.visibility === 'mutuals_only') && !selectOwnAccount(state)!.locked);
const hashtagWarning = (compose.visibility !== 'public' && compose.visibility !== 'group') && APPROX_HASHTAG_RE.test(compose.text);
const directMessageWarning = compose.visibility === 'direct';
if (needsLockWarning) {
return (

View File

@@ -99,7 +99,7 @@ const ComposeEditor = React.forwardRef<LexicalEditor, IComposeEditor>(({
placeholder,
}, ref) => {
const dispatch = useAppDispatch();
const { content_type: contentType, modified_language: language } = useCompose(composeId);
const { contentType, modifiedLanguage: language } = useCompose(composeId);
const isWysiwyg = contentType === 'wysiwyg';
const nodes = useNodes(isWysiwyg);
const intl = useIntl();
@@ -117,18 +117,18 @@ const ComposeEditor = React.forwardRef<LexicalEditor, IComposeEditor>(({
if (!compose) return;
const editorState = !compose.modified_language || compose.modified_language === compose.language
const editorState = !compose.modifiedLanguage || compose.modifiedLanguage === compose.language
? compose.editorState
: compose.editorStateMap[compose.modified_language] || '';
: compose.editorStateMap[compose.modifiedLanguage] || '';
if (editorState) {
return editorState;
}
return () => {
const text = !compose.modified_language || compose.modified_language === compose.language
const text = !compose.modifiedLanguage || compose.modifiedLanguage === compose.language
? compose.text
: compose.textMap[compose.modified_language] || '';
: compose.textMap[compose.modifiedLanguage] || '';
if (isWysiwyg) {
$convertFromMarkdownString(text, TRANSFORMERS);

View File

@@ -50,8 +50,8 @@ const StatePlugin: React.FC<IStatePlugin> = ({ composeId, isWysiwyg }) => {
};
};
if (compose.clear_link_suggestion?.key) {
const node = $getNodeByKey(compose.clear_link_suggestion.key);
if (compose.clearLinkSuggestion?.key) {
const node = $getNodeByKey(compose.clearLinkSuggestion.key);
const url = (node as LinkNode | null)?.getURL?.();
if (!url || node === null || !compareUrl(url).isDirty) {
dispatch(suggestClearLink(composeId, null));
@@ -63,7 +63,7 @@ const StatePlugin: React.FC<IStatePlugin> = ({ composeId, isWysiwyg }) => {
const links = [...$nodesOfType(AutoLinkNode), ...$nodesOfType(LinkNode)];
for (const link of links) {
if (compose.dismissed_clear_links_suggestions.includes(link.getKey())) {
if (compose.dismissedClearLinksSuggestions.includes(link.getKey())) {
continue;
}
@@ -87,7 +87,7 @@ const StatePlugin: React.FC<IStatePlugin> = ({ composeId, isWysiwyg }) => {
const state = getState();
const compose = state.compose[composeId];
if (compose.hashtag_casing_suggestion_ignored) return;
if (compose.hashtagCasingSuggestionIgnored) return;
editorState.read(() => {
const hashtagNodes = $nodesOfType(HashtagNode);
@@ -118,7 +118,7 @@ const StatePlugin: React.FC<IStatePlugin> = ({ composeId, isWysiwyg }) => {
let quoteId: string | undefined;
for (const id of ids) {
if (compose?.dismissed_quotes.includes(id)) continue;
if (compose?.dismissedQuotes.includes(id)) continue;
if (state.statuses[id]) {
quoteId = id;

View File

@@ -13,6 +13,8 @@ import { useInteractionPolicies } from 'pl-fe/queries/settings/use-interaction-p
import type { BaseModalProps } from 'pl-fe/features/ui/components/modal-root';
const MANAGABLE_VISIBILITIES = ['public', 'unlisted', 'private'];
interface ComposeInteractionPolicyModalProps {
composeId: string;
}
@@ -22,7 +24,7 @@ const ComposeInteractionPolicyModal: React.FC<BaseModalProps & ComposeInteractio
const { interactionPolicies: initial } = useInteractionPolicies();
const compose = useCompose(composeId);
const canManageInteractionPolicies = compose.privacy === 'public' || compose.privacy === 'unlisted' || compose.privacy === 'private';
const canManageInteractionPolicies = MANAGABLE_VISIBILITIES.includes(compose.visibility);
useEffect(() => {
if (!canManageInteractionPolicies) {
@@ -35,7 +37,7 @@ const ComposeInteractionPolicyModal: React.FC<BaseModalProps & ComposeInteractio
return null;
}
const interactionPolicy = (compose.interactionPolicy || initial[compose.privacy as 'public']);
const interactionPolicy = (compose.interactionPolicy || initial[compose.visibility as 'public']);
const onClickClose = () => {
onClose('COMPOSE_INTERACTION_POLICY');
@@ -70,7 +72,7 @@ const ComposeInteractionPolicyModal: React.FC<BaseModalProps & ComposeInteractio
/>
<InteractionPolicyConfig
interactionPolicy={interactionPolicy}
visibility={compose.privacy as 'public'}
visibility={compose.visibility as 'public'}
onChange={onChange}
singlePost
/>

View File

@@ -32,7 +32,7 @@ const ComposeModal: React.FC<BaseModalProps & ComposeModalProps> = ({ onClose, c
const { openModal } = useModalsActions();
const persistDraftStatus = usePersistDraftStatus();
const { id: statusId, privacy, in_reply_to: inReplyTo, quote, group_id: groupId } = compose;
const { id: statusId, visibility, inReplyToId, quote, groupId } = compose;
const { isDragging, isDraggedOver } = useDraggedFiles(node, (files) => {
dispatch(uploadCompose(composeId, files, intl));
@@ -43,12 +43,12 @@ const ComposeModal: React.FC<BaseModalProps & ComposeModalProps> = ({ onClose, c
openModal('CONFIRM', {
heading: statusId
? <FormattedMessage id='confirmations.cancel_editing.heading' defaultMessage='Cancel post editing' />
: compose.draft_id
: compose.draftId
? <FormattedMessage id='confirmations.cancel_draft.heading' defaultMessage='Discard draft changes' />
: <FormattedMessage id='confirmations.cancel.heading' defaultMessage='Discard post' />,
message: statusId
? <FormattedMessage id='confirmations.cancel_editing.message' defaultMessage='Are you sure you want to cancel editing this post? All changes will be lost.' />
: compose.draft_id
: compose.draftId
? <FormattedMessage id='confirmations.cancel_draft_editing.message' defaultMessage='Are you sure you want to cancel editing this draft post? All changes will be lost.' />
: <FormattedMessage id='confirmations.cancel.message' defaultMessage='Are you sure you want to cancel creating this post?' />,
confirm: intl.formatMessage(statusId ? messages.cancelEditing : messages.confirm),
@@ -69,19 +69,19 @@ const ComposeModal: React.FC<BaseModalProps & ComposeModalProps> = ({ onClose, c
};
const renderTitle = () => {
if (compose.draft_id) {
if (compose.draftId) {
return <FormattedMessage id='navigation_bar.compose_draft' defaultMessage='Edit draft post' />;
} else if (compose.redacting) {
return <FormattedMessage id='navigation_bar.compose_redact' defaultMessage='Redact post' />;
} else if (statusId) {
return <FormattedMessage id='navigation_bar.compose_edit' defaultMessage='Edit post' />;
} else if (privacy === 'direct') {
} else if (visibility === 'direct') {
return <FormattedMessage id='navigation_bar.compose_direct' defaultMessage='Direct message' />;
} else if (inReplyTo && groupId) {
} else if (inReplyToId && groupId) {
return <FormattedMessage id='navigation_bar.compose_group_reply' defaultMessage='Reply to group post' />;
} else if (groupId) {
return <FormattedMessage id='navigation_bar.compose_group' defaultMessage='Compose to group' />;
} else if (inReplyTo) {
} else if (inReplyToId) {
return <FormattedMessage id='navigation_bar.compose_reply' defaultMessage='Reply to post' />;
} else if (quote) {
return <FormattedMessage id='navigation_bar.compose_quote' defaultMessage='Quote post' />;

View File

@@ -19,10 +19,10 @@ const ReplyMentionsModal: React.FC<BaseModalProps & ReplyMentionsModalProps> = (
const compose = useCompose(composeId);
const getStatus = useCallback(makeGetStatus(), []);
const status = useAppSelector(state => getStatus(state, { id: compose.in_reply_to! }));
const status = useAppSelector(state => getStatus(state, { id: compose.inReplyToId! }));
const { account } = useOwnAccount();
const mentions = statusToMentionsAccountIdsArray(status!, account!, compose.parent_reblogged_by);
const mentions = statusToMentionsAccountIdsArray(status!, account!, compose.parentRebloggedById);
const author = status?.account_id;
const onClickClose = () => {

View File

@@ -64,7 +64,7 @@ const usePersistDraftStatus = () => {
const draft = {
...compose,
draft_id: compose.draft_id || crypto.randomUUID(),
draft_id: compose.draftId || crypto.randomUUID(),
};
const drafts = queryClient.getQueryData<Record<string, DraftStatus>>(['draftStatuses']) || {};

View File

@@ -106,37 +106,37 @@ interface Compose {
// User-edited text
editorState: string | null;
editorStateMap: Record<Language | string, string | null>;
spoiler_text: string;
spoilerText: string;
spoilerTextMap: Record<Language | string, string>;
text: string;
textMap: Record<Language | string, string>;
// Non-text content
poll: ComposePoll | null;
media_attachments: Array<MediaAttachment>;
mediaAttachments: Array<MediaAttachment>;
// Post settings
content_type: string;
privacy: string;
federated: boolean;
contentType: string;
visibility: string;
local_only: boolean;
language: Language | string | null;
sensitive: boolean;
interactionPolicy: InteractionPolicy | null;
schedule: Date | null;
scheduledAt: Date | null;
// References to other posts/groups/users
draft_id: string | null;
group_id: string | null;
draftId: string | null;
groupId: string | null;
id: string | null;
in_reply_to: string | null;
inReplyToId: string | null;
quote: string | null;
to: Array<string>;
parent_reblogged_by: string | null;
parentRebloggedById: string | null;
// State flags
is_changing_upload: boolean;
is_submitting: boolean;
is_uploading: boolean;
isChangingUpload: boolean;
isSubmitting: boolean;
isUploading: boolean;
progress: number;
// Internal
@@ -145,20 +145,19 @@ interface Compose {
resetFileKey: number | null;
// Currently modified language
modified_language: Language | string | null;
modifiedLanguage: Language | string | null;
// Suggestions
approvalRequired: boolean;
suggested_language: string | null;
suggestedLanguage: string | null;
suggestions: Array<string> | Array<Emoji>;
suggestion_token: string | null;
tagHistory: Array<string>;
dismissed_clear_links_suggestions: Array<string>;
clear_link_suggestion: ClearLinkSuggestion | null;
dismissedClearLinksSuggestions: Array<string>;
clearLinkSuggestion: ClearLinkSuggestion | null;
preview: Partial<BaseStatus> | null;
dismissed_quotes: Array<string>;
hashtag_casing_suggestion: string | null;
hashtag_casing_suggestion_ignored: boolean | null;
dismissedQuotes: Array<string>;
hashtagCasingSuggestion: string | null;
hashtagCasingSuggestionIgnored: boolean | null;
// Moderation features
redacting: boolean;
@@ -167,46 +166,45 @@ interface Compose {
const newCompose = (params: Partial<Compose> = {}): Compose => ({
caretPosition: null,
content_type: 'text/plain',
draft_id: null,
contentType: 'text/plain',
draftId: null,
editorState: null,
editorStateMap: {},
group_id: null,
groupId: null,
idempotencyKey: '',
id: null,
in_reply_to: null,
is_changing_upload: false,
is_submitting: false,
is_uploading: false,
media_attachments: [],
inReplyToId: null,
isChangingUpload: false,
isSubmitting: false,
isUploading: false,
mediaAttachments: [],
poll: null,
privacy: 'public',
visibility: 'public',
progress: 0,
quote: null,
resetFileKey: null,
schedule: null,
scheduledAt: null,
sensitive: false,
spoiler_text: '',
spoilerText: '',
spoilerTextMap: {},
suggestions: [],
suggestion_token: null,
tagHistory: [],
text: '',
textMap: {},
to: [],
parent_reblogged_by: null,
dismissed_quotes: [],
parentRebloggedById: null,
dismissedQuotes: [],
language: null,
modified_language: null,
suggested_language: null,
federated: true,
modifiedLanguage: null,
suggestedLanguage: null,
local_only: false,
approvalRequired: false,
interactionPolicy: null,
dismissed_clear_links_suggestions: [],
clear_link_suggestion: null,
dismissedClearLinksSuggestions: [],
clearLinkSuggestion: null,
preview: null,
hashtag_casing_suggestion: null,
hashtag_casing_suggestion_ignored: null,
hashtagCasingSuggestion: null,
hashtagCasingSuggestionIgnored: null,
redacting: false,
redactingOverwrite: false,
...params,
@@ -238,10 +236,10 @@ const statusToMentionsAccountIdsArray = (status: Pick<Status, 'mentions' | 'acco
};
const appendMedia = (compose: Compose, media: MediaAttachment, defaultSensitive?: boolean) => {
const prevSize = compose.media_attachments.length;
const prevSize = compose.mediaAttachments.length;
compose.media_attachments.push(media);
compose.is_uploading = false;
compose.mediaAttachments.push(media);
compose.isUploading = false;
compose.resetFileKey = Math.floor((Math.random() * 0x10000));
compose.idempotencyKey = crypto.randomUUID();
@@ -251,9 +249,9 @@ const appendMedia = (compose: Compose, media: MediaAttachment, defaultSensitive?
};
const removeMedia = (compose: Compose, mediaId: string) => {
const prevSize = compose.media_attachments.length;
const prevSize = compose.mediaAttachments.length;
compose.media_attachments = compose.media_attachments.filter(item => item.id !== mediaId);
compose.mediaAttachments = compose.mediaAttachments.filter(item => item.id !== mediaId);
compose.idempotencyKey = crypto.randomUUID();
if (prevSize === 1) {
@@ -264,11 +262,10 @@ const removeMedia = (compose: Compose, mediaId: string) => {
const insertSuggestion = (compose: Compose, position: number, token: string | null, completion: string, path: ComposeSuggestionSelectAction['path']) => {
const updateText = (oldText?: string) => `${oldText?.slice(0, position)}${completion} ${oldText?.slice(position + (token?.length ?? 0))}`;
if (path[0] === 'spoiler_text') {
compose.spoiler_text = updateText(compose.spoiler_text);
compose.spoilerText = updateText(compose.spoilerText);
} else if (compose.poll) {
compose.poll.options[path[2]] = updateText(compose.poll.options[path[2]]);
}
compose.suggestion_token = null;
compose.suggestions = [];
compose.idempotencyKey = crypto.randomUUID();
};
@@ -280,7 +277,6 @@ const updateSuggestionTags = (compose: Compose, token: string, tags: Tag[]) => {
.filter((tag) => tag.name.toLowerCase().startsWith(prefix.toLowerCase()))
.slice(0, 4)
.map((tag) => '#' + tag.name);
compose.suggestion_token = token;
};
const privacyPreference = (a: string, b: string, list_id: number | null, conversationScope = false) => {
@@ -323,8 +319,8 @@ const importAccount = (compose: Compose, account: CredentialAccount) => {
if (!settings) return;
if (settings.defaultPrivacy) compose.privacy = settings.defaultPrivacy;
if (settings.defaultContentType) compose.content_type = settings.defaultContentType;
if (settings.defaultPrivacy) compose.visibility = settings.defaultPrivacy;
if (settings.defaultContentType) compose.contentType = settings.defaultContentType;
compose.tagHistory = tagHistory.get(account.id) || [];
};
@@ -343,8 +339,8 @@ const importAccount = (compose: Compose, account: CredentialAccount) => {
const updateDefaultContentType = (compose: Compose, instance: Instance) => {
const postFormats = instance.pleroma.metadata.post_formats;
compose.content_type = postFormats.includes(compose.content_type) || (postFormats.includes('text/markdown') && compose.content_type === 'wysiwyg')
? compose.content_type
compose.contentType = postFormats.includes(compose.contentType) || (postFormats.includes('text/markdown') && compose.contentType === 'wysiwyg')
? compose.contentType
: postFormats.includes('text/markdown')
? 'text/markdown'
: postFormats[0];
@@ -367,7 +363,7 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
switch (action.type) {
case COMPOSE_TYPE_CHANGE:
return updateCompose(state, action.composeId, compose => {
compose.content_type = action.value;
compose.contentType = action.value;
compose.idempotencyKey = crypto.randomUUID();
});
case COMPOSE_SPOILERNESS_CHANGE:
@@ -377,26 +373,26 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
});
case COMPOSE_SPOILER_TEXT_CHANGE:
return updateCompose(state, action.composeId, compose => {
if (!compose.modified_language || compose.modified_language === compose.language) {
compose.spoiler_text = action.text;
} else if (compose.modified_language) {
compose.spoilerTextMap[compose.modified_language] = action.text;
if (!compose.modifiedLanguage || compose.modifiedLanguage === compose.language) {
compose.spoilerText = action.text;
} else if (compose.modifiedLanguage) {
compose.spoilerTextMap[compose.modifiedLanguage] = action.text;
}
});
case COMPOSE_VISIBILITY_CHANGE:
return updateCompose(state, action.composeId, compose => {
compose.privacy = action.value;
compose.visibility = action.value;
compose.idempotencyKey = crypto.randomUUID();
});
case COMPOSE_LANGUAGE_CHANGE:
return updateCompose(state, action.composeId, compose => {
compose.language = action.value;
compose.modified_language = action.value;
compose.modifiedLanguage = action.value;
compose.idempotencyKey = crypto.randomUUID();
});
case COMPOSE_MODIFIED_LANGUAGE_CHANGE:
return updateCompose(state, action.composeId, compose => {
compose.modified_language = action.value;
compose.modifiedLanguage = action.value;
compose.idempotencyKey = crypto.randomUUID();
});
case COMPOSE_CHANGE:
@@ -408,29 +404,29 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
return updateCompose(state, action.composeId, compose => {
const defaultCompose = state.default!;
const to = action.explicitAddressing
const mentions = action.explicitAddressing
? statusToMentionsArray(action.status, action.account, action.rebloggedBy)
: [];
compose.group_id = action.status.group_id;
compose.in_reply_to = action.status.id;
compose.to = to;
compose.parent_reblogged_by = action.rebloggedBy?.id || null;
compose.groupId = action.status.group_id;
compose.inReplyToId = action.status.id;
compose.to = mentions;
compose.parentRebloggedById = action.rebloggedBy?.id || null;
compose.text = !action.explicitAddressing ? statusToTextMentions(action.status, action.account) : '';
compose.privacy = privacyPreference(action.status.visibility, defaultCompose.privacy, action.status.list_id, action.conversationScope);
compose.federated = action.status.local_only !== true;
compose.visibility = privacyPreference(action.status.visibility, defaultCompose.visibility, action.status.list_id, action.conversationScope);
compose.local_only = action.status.local_only === true;
compose.caretPosition = null;
compose.idempotencyKey = crypto.randomUUID();
compose.content_type = defaultCompose.content_type;
compose.contentType = defaultCompose.contentType;
compose.approvalRequired = action.approvalRequired || false;
if (action.preserveSpoilers && action.status.spoiler_text) {
compose.sensitive = true;
compose.spoiler_text = action.status.spoiler_text;
compose.spoilerText = action.status.spoiler_text;
}
});
case COMPOSE_EVENT_REPLY:
return updateCompose(state, action.composeId, compose => {
compose.in_reply_to = action.status.id;
compose.inReplyToId = action.status.id;
compose.to = statusToMentionsArray(action.status, action.account);
compose.idempotencyKey = crypto.randomUUID();
});
@@ -441,26 +437,26 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
compose.quote = action.status.id;
compose.to = [author];
compose.parent_reblogged_by = null;
compose.parentRebloggedById = null;
compose.text = '';
compose.privacy = privacyPreference(action.status.visibility, defaultCompose.privacy, action.status.list_id);
compose.visibility = privacyPreference(action.status.visibility, defaultCompose.visibility, action.status.list_id);
compose.caretPosition = null;
compose.idempotencyKey = crypto.randomUUID();
compose.content_type = defaultCompose.content_type;
compose.spoiler_text = '';
compose.contentType = defaultCompose.contentType;
compose.spoilerText = '';
if (action.status.visibility === 'group') {
compose.group_id = action.status.group_id;
compose.privacy = 'group';
compose.groupId = action.status.group_id;
compose.visibility = 'group';
}
});
case COMPOSE_SUBMIT_REQUEST:
return updateCompose(state, action.composeId, compose => {
compose.is_submitting = true;
compose.isSubmitting = true;
});
case COMPOSE_UPLOAD_CHANGE_REQUEST:
return updateCompose(state, action.composeId, compose => {
compose.is_changing_upload = true;
compose.isChangingUpload = true;
});
case COMPOSE_REPLY_CANCEL:
case COMPOSE_RESET:
@@ -469,30 +465,30 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
draft[action.composeId] = create(state.default, (draft) => ({
...draft,
idempotencyKey: crypto.randomUUID(),
in_reply_to: action.composeId.startsWith('reply:') ? action.composeId.slice(6) : null,
in_reply_to_id: action.composeId.startsWith('reply:') ? action.composeId.slice(6) : null,
...(action.composeId.startsWith('group:') ? {
privacy: 'group',
visibility: 'group',
group_id: action.composeId.slice(6),
} : undefined),
}));
});
case COMPOSE_SUBMIT_FAIL:
return updateCompose(state, action.composeId, compose => {
compose.is_submitting = false;
compose.isSubmitting = false;
});
case COMPOSE_UPLOAD_CHANGE_FAIL:
return updateCompose(state, action.composeId, compose => {
compose.is_changing_upload = false;
compose.isChangingUpload = false;
});
case COMPOSE_UPLOAD_REQUEST:
return updateCompose(state, action.composeId, compose => {
compose.is_uploading = true;
compose.isUploading = true;
});
case COMPOSE_UPLOAD_SUCCESS:
return updateCompose(state, action.composeId, compose => appendMedia(compose, action.media, state.default.sensitive));
case COMPOSE_UPLOAD_FAIL:
return updateCompose(state, action.composeId, compose => {
compose.is_uploading = false;
compose.isUploading = false;
});
case COMPOSE_UPLOAD_UNDO:
return updateCompose(state, action.composeId, compose => removeMedia(compose, action.mediaId));
@@ -509,26 +505,24 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
case COMPOSE_DIRECT:
return updateCompose(state, 'compose-modal', compose => {
compose.text = [compose.text.trim(), `@${action.account.acct} `].filter((str) => str.length !== 0).join(' ');
compose.privacy = 'direct';
compose.visibility = 'direct';
compose.caretPosition = null;
compose.idempotencyKey = crypto.randomUUID();
});
case COMPOSE_GROUP_POST:
return updateCompose(state, action.composeId, compose => {
compose.privacy = 'group';
compose.group_id = action.groupId;
compose.visibility = 'group';
compose.groupId = action.groupId;
compose.caretPosition = null;
compose.idempotencyKey = crypto.randomUUID();
});
case COMPOSE_SUGGESTIONS_CLEAR:
return updateCompose(state, action.composeId, compose => {
compose.suggestions = [];
compose.suggestion_token = null;
});
case COMPOSE_SUGGESTIONS_READY:
return updateCompose(state, action.composeId, compose => {
compose.suggestions = action.accounts ? action.accounts.map((item) => item.id) : action.emojis || [];
compose.suggestion_token = action.token;
});
case COMPOSE_SUGGESTION_SELECT:
return updateCompose(state, action.composeId, compose => insertSuggestion(compose, action.position, action.token, action.completion, action.path));
@@ -540,17 +534,17 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
});
case TIMELINE_DELETE:
return updateCompose(state, 'compose-modal', compose => {
if (action.statusId === compose.in_reply_to) {
compose.in_reply_to = null;
if (action.statusId === compose.inReplyToId) {
compose.inReplyToId = null;
} if (action.statusId === compose.quote) {
compose.quote = null;
}
});
case COMPOSE_UPLOAD_CHANGE_SUCCESS:
return updateCompose(state, action.composeId, compose => {
compose.is_changing_upload = false;
compose.isChangingUpload = false;
compose.media_attachments = compose.media_attachments.map(item => {
compose.mediaAttachments = compose.mediaAttachments.map(item => {
if (item.id === action.media.id) {
return action.media;
}
@@ -560,34 +554,34 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
});
case COMPOSE_SET_STATUS:
return updateCompose(state, 'compose-modal', compose => {
const to = action.explicitAddressing ? getExplicitMentions(action.status.account.id, action.status) : [];
const mentions = action.explicitAddressing ? getExplicitMentions(action.status.account.id, action.status) : [];
if (!action.withRedraft && !action.draftId) {
compose.id = action.status.id;
}
compose.text = action.rawText || unescapeHTML(expandMentions(action.status));
compose.to = to;
compose.parent_reblogged_by = null;
compose.in_reply_to = action.status.in_reply_to_id;
compose.privacy = action.status.visibility;
compose.to = mentions;
compose.parentRebloggedById = null;
compose.inReplyToId = action.status.in_reply_to_id;
compose.visibility = action.status.visibility;
compose.caretPosition = null;
compose.idempotencyKey = crypto.randomUUID();
const contentType = action.contentType === 'text/markdown' && state.default.content_type === 'wysiwyg'
const contentType = action.contentType === 'text/markdown' && state.default.contentType === 'wysiwyg'
? 'wysiwyg'
: action.contentType || 'text/plain';
compose.content_type = contentType;
compose.contentType = contentType;
compose.quote = action.status.quote_id;
compose.group_id = action.status.group_id;
compose.groupId = action.status.group_id;
compose.language = action.status.language;
compose.media_attachments = action.status.media_attachments;
compose.mediaAttachments = action.status.media_attachments;
compose.sensitive = action.status.sensitive;
compose.redacting = action.redacting || false;
if (action.status.spoiler_text.length > 0) {
compose.spoiler_text = action.status.spoiler_text;
compose.spoilerText = action.status.spoiler_text;
} else {
compose.spoiler_text = '';
compose.spoilerText = '';
}
if (action.poll) {
@@ -599,7 +593,7 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
}
if (action.draftId) {
compose.draft_id = action.draftId;
compose.draftId = action.draftId;
}
if (action.editorState) {
@@ -616,15 +610,15 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
});
case COMPOSE_SCHEDULE_ADD:
return updateCompose(state, action.composeId, compose => {
compose.schedule = new Date(Date.now() + 10 * 60 * 1000);
compose.scheduledAt = new Date(Date.now() + 10 * 60 * 1000);
});
case COMPOSE_SCHEDULE_SET:
return updateCompose(state, action.composeId, compose => {
compose.schedule = action.date;
compose.scheduledAt = action.date;
});
case COMPOSE_SCHEDULE_REMOVE:
return updateCompose(state, action.composeId, compose => {
compose.schedule = null;
compose.scheduledAt = null;
});
case COMPOSE_POLL_OPTION_ADD:
return updateCompose(state, action.composeId, compose => {
@@ -635,9 +629,9 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
case COMPOSE_POLL_OPTION_CHANGE:
return updateCompose(state, action.composeId, compose => {
if (!compose.poll) return;
if (!compose.modified_language || compose.modified_language === compose.language) {
if (!compose.modifiedLanguage || compose.modifiedLanguage === compose.language) {
compose.poll.options[action.index] = action.title;
if (compose.modified_language) compose.poll.options_map[action.index][compose.modified_language] = action.title;
if (compose.modifiedLanguage) compose.poll.options_map[action.index][compose.modifiedLanguage] = action.title;
}
});
case COMPOSE_POLL_OPTION_REMOVE:
@@ -671,12 +665,12 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
// return updateCompose(state, 'default', compose => updateSetting(compose, action.path, action.value));
case COMPOSE_EDITOR_STATE_SET:
return updateCompose(state, action.composeId, compose => {
if (!compose.modified_language || compose.modified_language === compose.language) {
if (!compose.modifiedLanguage || compose.modifiedLanguage === compose.language) {
compose.editorState = action.editorState as string;
compose.text = action.text as string;
} else if (compose.modified_language) {
compose.editorStateMap[compose.modified_language] = action.editorState as string;
compose.textMap[compose.modified_language] = action.text as string;
} else if (compose.modifiedLanguage) {
compose.editorStateMap[compose.modifiedLanguage] = action.editorState as string;
compose.textMap[compose.modifiedLanguage] = action.text as string;
}
});
case EVENT_COMPOSE_CANCEL:
@@ -689,11 +683,11 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
});
case COMPOSE_CHANGE_MEDIA_ORDER:
return updateCompose(state, action.composeId, compose => {
const indexA = compose.media_attachments.findIndex(x => x.id === action.a);
const indexB = compose.media_attachments.findIndex(x => x.id === action.b);
const indexA = compose.mediaAttachments.findIndex(x => x.id === action.a);
const indexB = compose.mediaAttachments.findIndex(x => x.id === action.b);
const item = compose.media_attachments.splice(indexA, 1)[0];
compose.media_attachments.splice(indexB, 0, item);
const item = compose.mediaAttachments.splice(indexA, 1)[0];
compose.mediaAttachments.splice(indexB, 0, item);
});
case COMPOSE_ADD_SUGGESTED_QUOTE:
return updateCompose(state, action.composeId, compose => {
@@ -701,13 +695,13 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
});
case COMPOSE_ADD_SUGGESTED_LANGUAGE:
return updateCompose(state, action.composeId, compose => {
compose.suggested_language = action.language;
compose.suggestedLanguage = action.language;
});
case COMPOSE_LANGUAGE_ADD:
return updateCompose(state, action.composeId, compose => {
compose.editorStateMap[action.value] = compose.editorState;
compose.textMap[action.value] = compose.text;
compose.spoilerTextMap[action.value] = compose.spoiler_text;
compose.spoilerTextMap[action.value] = compose.spoilerText;
if (compose.poll) compose.poll.options_map.forEach((option, key) => option[action.value] = compose.poll!.options[key]);
});
case COMPOSE_LANGUAGE_DELETE:
@@ -718,12 +712,12 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
});
case COMPOSE_QUOTE_CANCEL:
return updateCompose(state, action.composeId, (compose) => {
if (compose.quote) compose.dismissed_quotes.push(compose.quote);
if (compose.quote) compose.dismissedQuotes.push(compose.quote);
compose.quote = null;
});
case COMPOSE_FEDERATED_CHANGE:
return updateCompose(state, action.composeId, compose => {
compose.federated = !compose.federated;
compose.local_only = !compose.local_only;
});
case COMPOSE_INTERACTION_POLICY_OPTION_CHANGE:
return updateCompose(state, action.composeId, compose => {
@@ -738,14 +732,14 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
return updateCompose(state, 'default', (compose) => updateDefaultContentType(compose, action.instance));
case COMPOSE_CLEAR_LINK_SUGGESTION_CREATE:
return updateCompose(state, action.composeId, compose => {
compose.clear_link_suggestion = action.suggestion;
compose.clearLinkSuggestion = action.suggestion;
});
case COMPOSE_CLEAR_LINK_SUGGESTION_IGNORE:
return updateCompose(state, action.composeId, compose => {
if (compose.clear_link_suggestion?.key === action.key) {
compose.clear_link_suggestion = null;
if (compose.clearLinkSuggestion?.key === action.key) {
compose.clearLinkSuggestion = null;
}
compose.dismissed_clear_links_suggestions.push(action.key);
compose.dismissedClearLinksSuggestions.push(action.key);
});
case COMPOSE_PREVIEW_SUCCESS:
return updateCompose(state, action.composeId, compose => {
@@ -757,12 +751,12 @@ const compose = (state = initialState, action: ComposeAction | EventsAction | In
});
case COMPOSE_HASHTAG_CASING_SUGGESTION_SET:
return updateCompose(state, action.composeId, compose => {
compose.hashtag_casing_suggestion = action.suggestion;
compose.hashtagCasingSuggestion = action.suggestion;
});
case COMPOSE_HASHTAG_CASING_SUGGESTION_IGNORE:
return updateCompose(state, action.composeId, compose => {
compose.hashtag_casing_suggestion = null;
compose.hashtag_casing_suggestion_ignored = true;
compose.hashtagCasingSuggestion = null;
compose.hashtagCasingSuggestionIgnored = true;
});
case COMPOSE_REDACTING_OVERWRITE_CHANGE:
return updateCompose(state, action.composeId, compose => {