fix: pass email explicitly to handleForwardAsAttachment from the list
The list context-menu wiring called selectEmail(email) then invoked handleForwardAsAttachment() synchronously in the same tick. Since handleForwardAsAttachment read selectedEmail from its own closure, and Zustand's store update doesn't propagate into this render's closure until the next render, this could forward the previously selected message (or no-op if nothing was selected yet) instead of the row the user actually right-clicked. Parameterize handleForwardAsAttachment to accept an explicit `email` (defaulting to selectedEmail), the same pattern handleDelete already uses in this file for the same class of problem, and pass it explicitly from the list context-menu wiring. The EmailViewer overflow menu's wiring is unaffected - it always operates on the single currently-open email via the default parameter. Caught by GitHub Copilot's automated PR review.
This commit is contained in:
@@ -1559,8 +1559,16 @@ export default function Home() {
|
|||||||
// by its existing blobId (no re-fetch/re-upload needed - JMAP blobs are
|
// by its existing blobId (no re-fetch/re-upload needed - JMAP blobs are
|
||||||
// account-scoped, not per-email). Skips prepareComposerQuoteHeader
|
// account-scoped, not per-email). Skips prepareComposerQuoteHeader
|
||||||
// entirely, so the body starts blank instead of quoting the original.
|
// entirely, so the body starts blank instead of quoting the original.
|
||||||
const handleForwardAsAttachment = async () => {
|
// Takes an explicit `email` (defaulting to selectedEmail), same pattern
|
||||||
if (!selectedEmail) return;
|
// handleDelete uses just below, rather than always reading selectedEmail
|
||||||
|
// from this closure - callers that just called selectEmail(email) and
|
||||||
|
// invoke this synchronously in the same tick would otherwise see the
|
||||||
|
// PRE-update value (the Zustand store updates immediately, but this
|
||||||
|
// render's selectedEmail closure doesn't until the next render),
|
||||||
|
// forwarding the previously selected message or no-op'ing on an
|
||||||
|
// unselected row. See the list context-menu wiring below.
|
||||||
|
const handleForwardAsAttachment = async (email: Email | null = selectedEmail) => {
|
||||||
|
if (!email) return;
|
||||||
// Same filename options "Export as .eml" uses (see emailFilenameOptions
|
// Same filename options "Export as .eml" uses (see emailFilenameOptions
|
||||||
// in email-viewer.tsx), so the two actions produce consistent filenames
|
// in email-viewer.tsx), so the two actions produce consistent filenames
|
||||||
// for the same message rather than the synthetic attachment silently
|
// for the same message rather than the synthetic attachment silently
|
||||||
@@ -1572,7 +1580,7 @@ export default function Home() {
|
|||||||
filenameStripDiacritics,
|
filenameStripDiacritics,
|
||||||
filenameCollapseSeparators,
|
filenameCollapseSeparators,
|
||||||
} = useSettingsStore.getState();
|
} = useSettingsStore.getState();
|
||||||
const payload = buildForwardAsAttachmentPayload(selectedEmail, t('email_composer.prefix.forward'), {
|
const payload = buildForwardAsAttachmentPayload(email, t('email_composer.prefix.forward'), {
|
||||||
template: emailDownloadTemplate,
|
template: emailDownloadTemplate,
|
||||||
spaceReplacement: filenameSpaceReplacement,
|
spaceReplacement: filenameSpaceReplacement,
|
||||||
lowercase: filenameLowercase,
|
lowercase: filenameLowercase,
|
||||||
@@ -1582,8 +1590,8 @@ export default function Home() {
|
|||||||
if (!payload) return;
|
if (!payload) return;
|
||||||
|
|
||||||
const ok = await emailHooks.onBeforeForward.intercept({
|
const ok = await emailHooks.onBeforeForward.intercept({
|
||||||
originalEmailId: selectedEmail.id,
|
originalEmailId: email.id,
|
||||||
originalEmail: emailToReadView(selectedEmail),
|
originalEmail: emailToReadView(email),
|
||||||
mode: 'forward' as const,
|
mode: 'forward' as const,
|
||||||
});
|
});
|
||||||
if (!ok) return;
|
if (!ok) return;
|
||||||
@@ -1602,7 +1610,7 @@ export default function Home() {
|
|||||||
mode: "forward",
|
mode: "forward",
|
||||||
draftId: null,
|
draftId: null,
|
||||||
replyTo: {
|
replyTo: {
|
||||||
subject: selectedEmail.subject,
|
subject: email.subject,
|
||||||
attachments: [payload.attachment],
|
attachments: [payload.attachment],
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -3280,7 +3288,7 @@ export default function Home() {
|
|||||||
}}
|
}}
|
||||||
onForwardAsAttachment={(email) => {
|
onForwardAsAttachment={(email) => {
|
||||||
selectEmail(email);
|
selectEmail(email);
|
||||||
handleForwardAsAttachment();
|
handleForwardAsAttachment(email);
|
||||||
}}
|
}}
|
||||||
onMarkAsRead={async (email, read) => {
|
onMarkAsRead={async (email, read) => {
|
||||||
if (client) {
|
if (client) {
|
||||||
|
|||||||
Reference in New Issue
Block a user