From c657c4c5ba2f10da5629932be8d60516244d393a Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Wed, 4 Nov 2026 12:55:41 +0100 Subject: [PATCH] fix: keep unfolded messages readable when the conversation is read again after a send --- lib/__tests__/held-send.test.ts | 9 +++++++++ lib/held-send.ts | 11 ++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/lib/__tests__/held-send.test.ts b/lib/__tests__/held-send.test.ts index e4294da5b..2822db7c2 100644 --- a/lib/__tests__/held-send.test.ts +++ b/lib/__tests__/held-send.test.ts @@ -61,4 +61,13 @@ describe('echoes of sent replies', () => { expect(mergeEchoes([...server, { id: 'c' } as Email], [...server, echo]).map((e) => (e.sentEcho ? 'echo' : e.id))).toEqual(['a', 'b', 'c']); expect(mergeEchoes(server, [...server, echo]).map((e) => (e.sentEcho ? 'echo' : e.id))).toEqual(['a', 'b', 'echo']); }); + + it('keeps the body of a message already unfolded', () => { + const loaded = { id: 'a', keywords: {}, mailboxIds: { inbox: true }, bodyValues: { 1: { value: 'Hi' } } } as unknown as Email; + const listed = { id: 'a', keywords: { $seen: true }, mailboxIds: { archive: true } } as unknown as Email; + const [merged] = mergeEchoes([listed], [loaded]); + expect(merged.bodyValues).toEqual(loaded.bodyValues); + expect(merged.keywords).toEqual({ $seen: true }); + expect(merged.mailboxIds).toEqual({ archive: true }); + }); }); diff --git a/lib/held-send.ts b/lib/held-send.ts index 78b66e5fc..4ddb35749 100644 --- a/lib/held-send.ts +++ b/lib/held-send.ts @@ -97,6 +97,15 @@ export function addEcho(conversation: Email[], echo: Email): Email[] { */ export function mergeEchoes(server: Email[], shown: Email[]): Email[] { const ids = new Set(server.map((e) => e.id)); + const byId = new Map(shown.map((e) => [e.id, e])); + // The thread read carries list properties only: a message already unfolded + // keeps the body it loaded, with the server's flags and folders. + const merged = server.map((e) => { + const had = byId.get(e.id); + return had?.bodyValues && !e.bodyValues && !had.sentEcho + ? { ...had, keywords: e.keywords, mailboxIds: e.mailboxIds } + : e; + }); const echoes = shown.filter((e) => e.sentEcho && !ids.has(e.id)); - return echoes.length ? [...server, ...echoes] : server; + return echoes.length ? [...merged, ...echoes] : merged; }