diff --git a/components/mail/mail-app.tsx b/components/mail/mail-app.tsx index 5ea969c10..4958207a6 100644 --- a/components/mail/mail-app.tsx +++ b/components/mail/mail-app.tsx @@ -2474,8 +2474,11 @@ export function MailApp({ linkSegments: routeSegments }: MailAppProps = {}) { // and compose again". const handleCancelScheduledSend = async (email: Email) => { if (email.isSmimeScheduled || email.scheduledUndoStatus !== 'pending') return; + const wasOpen = useEmailStore.getState().selectedEmail?.id === email.id; const restored = await cancelScheduledForEdit(email); if (restored === undefined) return; + // The store closed it in the reader; on a phone or tablet the list comes back. + if (wasOpen && (isMobile || isTablet)) handleMobileBack(); toast.success( tViewer('send_cancelled'), t('notifications.moved_to_mailbox', { mailbox: t('sidebar.mailboxes.drafts') }), diff --git a/stores/__tests__/email-store-undo-send.test.ts b/stores/__tests__/email-store-undo-send.test.ts index 175ad47a3..2f51f5d51 100644 --- a/stores/__tests__/email-store-undo-send.test.ts +++ b/stores/__tests__/email-store-undo-send.test.ts @@ -110,6 +110,19 @@ describe('cancelling a send and restoring the draft', () => { await expect(useEmailStore.getState().cancelScheduledEmailForEdit(client, scheduled)).resolves.toEqual({ id: 'sent-1' }); }); + // The reader kept showing the Scheduled banner and its buttons for a + // message that was back in Drafts. + it('closes the cancelled message in the reader, and leaves another open message alone', async () => { + useEmailStore.setState({ selectedEmail: { ...scheduled, isScheduled: true } as Email }); + await useEmailStore.getState().cancelScheduledEmailForEdit(client, scheduled); + expect(useEmailStore.getState().selectedEmail).toBeNull(); + + const other = { id: 'other-1' } as Email; + useEmailStore.setState({ selectedEmail: other }); + await useEmailStore.getState().cancelScheduledEmailForEdit(client, scheduled); + expect(useEmailStore.getState().selectedEmail).toBe(other); + }); + it('restores mail sent from the own identity in the own Drafts, as before', async () => { const restored = await useEmailStore.getState().cancelUndoSend(client, { ...pending, submissionAccountId: 'account-1' }); diff --git a/stores/email-store.ts b/stores/email-store.ts index d84bc07bf..716d9a3bf 100644 --- a/stores/email-store.ts +++ b/stores/email-store.ts @@ -7966,13 +7966,15 @@ export const useEmailStore = create((set, get) => ({ try { if (email.isSmimeScheduled) { await client.deleteEmail(email.id, accountId); - set(state => ({ - selectedEmail: state.selectedEmail?.id === email.id ? null : state.selectedEmail, - selectedEmailKeys: dropFromSelection(state, e => e.id === email.id), - })); } else { await restoreSentToDraft(client, get().mailboxes, email.id, accountId); } + // Gone from Scheduled either way: the reader must not keep showing it + // with the Scheduled banner and its buttons. + set(state => ({ + selectedEmail: state.selectedEmail?.id === email.id ? null : state.selectedEmail, + selectedEmailKeys: dropFromSelection(state, e => e.id === email.id), + })); } catch (error) { void get().fetchScheduledEmails(client); throw new SendCancelledCleanupError(email.isSmimeScheduled ? 'remove' : 'restore', error);