From d93572ea90e7b61aa570c7223f0a69561dbbff61 Mon Sep 17 00:00:00 2001 From: Kazuki Nagasawa <113568707+crafkaz@users.noreply.github.com> Date: Fri, 29 Aug 2025 05:50:19 +0900 Subject: [PATCH] Fix 404 error after deleting status from detail view (#35800) (#35881) --- app/javascript/mastodon/actions/statuses.js | 14 ++++++++++- .../mastodon/containers/status_container.jsx | 8 +++++- .../mastodon/features/status/index.jsx | 25 ++++++++++++++++--- .../confirmation_modals/delete_status.tsx | 15 ++++++++--- app/javascript/mastodon/locales/en.json | 1 + app/javascript/mastodon/locales/ja.json | 1 + 6 files changed, 56 insertions(+), 8 deletions(-) diff --git a/app/javascript/mastodon/actions/statuses.js b/app/javascript/mastodon/actions/statuses.js index 3fddd1bcc56..7572efe95f5 100644 --- a/app/javascript/mastodon/actions/statuses.js +++ b/app/javascript/mastodon/actions/statuses.js @@ -1,7 +1,10 @@ +import { defineMessages } from 'react-intl'; + import { browserHistory } from 'mastodon/components/router'; import api from '../api'; +import { showAlert } from './alerts'; import { ensureComposeIsVisible, setComposeToStatus } from './compose'; import { importFetchedStatus, importFetchedAccount } from './importer'; import { fetchContext } from './statuses_typed'; @@ -40,6 +43,10 @@ export const STATUS_TRANSLATE_SUCCESS = 'STATUS_TRANSLATE_SUCCESS'; export const STATUS_TRANSLATE_FAIL = 'STATUS_TRANSLATE_FAIL'; export const STATUS_TRANSLATE_UNDO = 'STATUS_TRANSLATE_UNDO'; +const messages = defineMessages({ + deleteSuccess: { id: 'status.delete.success', defaultMessage: 'Post deleted' }, +}); + export function fetchStatusRequest(id, skipLoading) { return { type: STATUS_FETCH_REQUEST, @@ -154,7 +161,7 @@ export function deleteStatus(id, withRedraft = false) { dispatch(deleteStatusRequest(id)); - api().delete(`/api/v1/statuses/${id}`, { params: { delete_media: !withRedraft } }).then(response => { + return api().delete(`/api/v1/statuses/${id}`, { params: { delete_media: !withRedraft } }).then(response => { dispatch(deleteStatusSuccess(id)); dispatch(deleteFromTimelines(id)); dispatch(importFetchedAccount(response.data.account)); @@ -162,9 +169,14 @@ export function deleteStatus(id, withRedraft = false) { if (withRedraft) { dispatch(redraft(status, response.data.text)); ensureComposeIsVisible(getState); + } else { + dispatch(showAlert({ message: messages.deleteSuccess })); } + + return response; }).catch(error => { dispatch(deleteStatusFail(id, error)); + throw error; }); }; } diff --git a/app/javascript/mastodon/containers/status_container.jsx b/app/javascript/mastodon/containers/status_container.jsx index f451db661c4..e73ef5b96e1 100644 --- a/app/javascript/mastodon/containers/status_container.jsx +++ b/app/javascript/mastodon/containers/status_container.jsx @@ -117,7 +117,13 @@ const mapDispatchToProps = (dispatch, { contextType }) => ({ if (!deleteModal) { dispatch(deleteStatus(status.get('id'), withRedraft)); } else { - dispatch(openModal({ modalType: 'CONFIRM_DELETE_STATUS', modalProps: { statusId: status.get('id'), withRedraft } })); + dispatch(openModal({ + modalType: 'CONFIRM_DELETE_STATUS', + modalProps: { + statusId: status.get('id'), + withRedraft + } + })); } }, diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx index 3c197150e5e..362ad2c5e29 100644 --- a/app/javascript/mastodon/features/status/index.jsx +++ b/app/javascript/mastodon/features/status/index.jsx @@ -251,12 +251,31 @@ class Status extends ImmutablePureComponent { }; handleDeleteClick = (status, withRedraft = false) => { - const { dispatch } = this.props; + const { dispatch, history } = this.props; + + const handleDeleteSuccess = () => { + history.push('/'); + }; if (!deleteModal) { - dispatch(deleteStatus(status.get('id'), withRedraft)); + dispatch(deleteStatus(status.get('id'), withRedraft)) + .then(() => { + if (!withRedraft) { + handleDeleteSuccess(); + } + }) + .catch(() => { + // Error handling - could show error message + }); } else { - dispatch(openModal({ modalType: 'CONFIRM_DELETE_STATUS', modalProps: { statusId: status.get('id'), withRedraft } })); + dispatch(openModal({ + modalType: 'CONFIRM_DELETE_STATUS', + modalProps: { + statusId: status.get('id'), + withRedraft, + onDeleteSuccess: handleDeleteSuccess + } + })); } }; diff --git a/app/javascript/mastodon/features/ui/components/confirmation_modals/delete_status.tsx b/app/javascript/mastodon/features/ui/components/confirmation_modals/delete_status.tsx index 39e80cf7410..215ba31a464 100644 --- a/app/javascript/mastodon/features/ui/components/confirmation_modals/delete_status.tsx +++ b/app/javascript/mastodon/features/ui/components/confirmation_modals/delete_status.tsx @@ -40,14 +40,23 @@ export const ConfirmDeleteStatusModal: React.FC< { statusId: string; withRedraft: boolean; + onDeleteSuccess?: () => void; } & BaseConfirmationModalProps -> = ({ statusId, withRedraft, onClose }) => { +> = ({ statusId, withRedraft, onClose, onDeleteSuccess }) => { const intl = useIntl(); const dispatch = useAppDispatch(); const onConfirm = useCallback(() => { - dispatch(deleteStatus(statusId, withRedraft)); - }, [dispatch, statusId, withRedraft]); + void dispatch(deleteStatus(statusId, withRedraft)) + .then(() => { + onDeleteSuccess?.(); + onClose(); + }) + .catch(() => { + // Error handling - still close modal + onClose(); + }); + }, [dispatch, statusId, withRedraft, onDeleteSuccess, onClose]); return (