Composer redesign: Fixes bug with new post button (#40166)

This commit is contained in:
Echo
2026-08-14 11:25:36 +00:00
committed by GitHub
parent 3695695d5e
commit 4ad1a2cf3e
3 changed files with 72 additions and 15 deletions

View File

@@ -6,20 +6,27 @@ import { closeModal } from '@/mastodon/actions/modal';
import { Button } from '@/mastodon/components/button/redesign';
import {
focusComposerTextarea,
openNewComposer,
resetComposer,
} from '@/mastodon/reducers/slices/composer';
import { useAppDispatch } from '@/mastodon/store';
import classes from './modals.module.scss';
const ComposerCancelConfirmModal: React.FC = () => {
const ComposerCancelConfirmModal: React.FC<{ openNew?: boolean }> = ({
openNew,
}) => {
const dispatch = useAppDispatch();
const handleDelete = useCallback(() => {
dispatch(resetComposer());
if (openNew) {
dispatch(openNewComposer({ force: true }));
} else {
dispatch(resetComposer());
}
dispatch(
closeModal({ modalType: 'COMPOSER_DRAFT_DELETE', ignoreFocus: false }),
);
}, [dispatch]);
}, [dispatch, openNew]);
const handleContinue = useCallback(() => {
dispatch(
closeModal({ modalType: 'COMPOSER_DRAFT_DELETE', ignoreFocus: false }),

View File

@@ -6,7 +6,7 @@ import { ArrowsOutSimpleIcon, MinusIcon, XIcon } from '@phosphor-icons/react';
import { IconButton } from '@/mastodon/components/button/redesign';
import {
hideComposer,
closeComposer,
minimizeComposerToggle,
selectIsMinimized,
} from '@/mastodon/reducers/slices/composer';
@@ -63,7 +63,7 @@ export const ComposeFormHeader: React.FC<{
const dispatch = useAppDispatch();
const onClose = useCallback(() => {
dispatch(hideComposer());
dispatch(closeComposer());
}, [dispatch]);
const onMinimize = useCallback(() => {
dispatch(minimizeComposerToggle());

View File

@@ -65,6 +65,27 @@ const composerSlice = createSlice({
export const composer = composerSlice.reducer;
export const { minimizeComposerToggle } = composerSlice.actions;
export const selectComposerIsChanged = createAppSelector(
[
(state) => state.compose.get('text') as string,
(state) => state.compose.get('spoiler_text') as string,
(state) => !!state.compose.get('poll'),
(state) => !!state.compose.get('quoted_status_id'),
(state) =>
state.compose.get(
'media_attachments',
) as unknown as Immutable.List<unknown>,
(state) => Number(state.compose.get('pending_media_attachments')),
],
(text, spoilerText, hasPoll, hasQuote, attachments, pendingAttachmentsNum) =>
text.trim().length > 0 ||
spoilerText.trim().length > 0 ||
hasPoll ||
hasQuote ||
attachments.size > 0 ||
pendingAttachmentsNum > 0,
);
interface ComposeNewPost {
type?: 'post';
}
@@ -76,10 +97,26 @@ interface ComposeNewMessage {
type: 'message';
toAccountId?: string;
}
type ComposeNewPayload = ComposeNewPost | ComposeNewReply | ComposeNewMessage;
type ComposeNewPayload = (
| ComposeNewPost
| ComposeNewReply
| ComposeNewMessage
) & { force?: boolean };
export const openNewComposer = createAppThunk(
(payload: ComposeNewPayload, { dispatch, getState }) => {
if (!payload.force && selectComposerIsChanged(getState())) {
dispatch(
openModal({
modalType: 'COMPOSER_DRAFT_DELETE',
modalProps: {
openNew: true,
},
}),
);
return;
}
dispatch(resetCompose());
if (payload.type === 'message') {
const account =
@@ -93,6 +130,11 @@ export const openNewComposer = createAppThunk(
dispatch(replyComposeById(payload.toStatusId));
}
dispatch(composerSlice.actions.showComposer());
// Delay for a frame to ensure the DOM has updated.
requestAnimationFrame(() => {
focusComposerTextarea();
});
},
);
@@ -101,15 +143,23 @@ export const resetComposer = createAppThunk((_arg, { dispatch }) => {
dispatch(resetCompose());
});
export const hideComposer = createAppThunk((_arg, { getState, dispatch }) => {
const compose = getState().compose;
const isChanged =
!!compose.get('text') ||
!!compose.get('spoiler_text') ||
!!compose.get('poll') ||
(compose.get('media_attachments') as unknown as Immutable.List<unknown>)
.size > 0 ||
Number(compose.get('pending_media_attachments')) > 0;
export const closeComposer = createAppThunk((_arg, { getState, dispatch }) => {
const isChanged = selectComposerIsChanged(getState());
if (!isChanged) {
dispatch(resetComposer());
} else {
dispatch(
openModal({
modalType: 'COMPOSER_DRAFT_DELETE',
modalProps: {},
}),
);
}
});
export const newComposer = createAppThunk((_arg, { getState, dispatch }) => {
const isChanged = selectComposerIsChanged(getState());
if (!isChanged) {
dispatch(resetComposer());