From 0729f05aebcac439d2cc16220d2bd494e9a89463 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Wed, 4 Nov 2026 06:56:31 +0100 Subject: [PATCH] feat: name the account the tray's unread list is from when several are signed in --- lib/desktop/__tests__/os-window.test.tsx | 12 ++++++++++++ lib/desktop/os-summary.ts | 4 +++- lib/desktop/types.ts | 2 ++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/desktop/__tests__/os-window.test.tsx b/lib/desktop/__tests__/os-window.test.tsx index 1b28a60bb..9702a9044 100644 --- a/lib/desktop/__tests__/os-window.test.tsx +++ b/lib/desktop/__tests__/os-window.test.tsx @@ -490,6 +490,18 @@ describe('the summary', () => { expect(summary.unread).toEqual([expect.objectContaining({ emailId: 'e1', accountId: 'acc', sender: 'Alice', subject: 'Lunch?' })]); expect(JSON.parse(summary.unread[0].context!)).toMatchObject({ emailId: 'e1', slot: 3 }); expect(getEmails).toHaveBeenCalledWith('in', undefined, 5, 0, undefined, false, { notKeyword: '$seen' }); + // One account: no need to say whose. + expect(summary.account).toBeUndefined(); + }); + + it('with two accounts it names the one the unread mail is from', async () => { + const { useAccountStore } = await import('@/stores/account-store'); + useAccountStore.setState({ accounts: [ + { id: 'alice@one', cookieSlot: 3, serverUrl: 'https://one.example', username: 'alice@example.org' }, + { id: 'bob@two', cookieSlot: 4, serverUrl: 'https://two.example', username: 'bob@example.org' }, + ] as never }); + const { readSummary } = await import('../os-summary'); + expect((await readSummary('en')).account).toBe('alice@example.org'); }); it('before the policy is known it is empty', async () => { diff --git a/lib/desktop/os-summary.ts b/lib/desktop/os-summary.ts index 599dd942a..9476a1d84 100644 --- a/lib/desktop/os-summary.ts +++ b/lib/desktop/os-summary.ts @@ -81,7 +81,9 @@ export async function readSummary(locale: string | undefined, now = Date.now()): const next = nextEventOf(events, now); if (next) nextEvent = { title: next.title ?? '', when: formatEventTime(eventStart(next), now, locale) }; } - return { unread, recent, nextEvent }; + // The tray lists one account's inbox: with more than one, it says whose. + const several = useAccountStore.getState().accounts.length > 1; + return { unread, recent, nextEvent, ...(several && entry.username ? { account: entry.username } : {}) }; } /** Keeps main's copy current: when the unread count moves, and now and then for the next event. */ diff --git a/lib/desktop/types.ts b/lib/desktop/types.ts index f091da3bf..047efba8f 100644 --- a/lib/desktop/types.ts +++ b/lib/desktop/types.ts @@ -610,6 +610,8 @@ export interface DesktopOsSummary { /** Newest conversations, whether read or not, for the jump list. */ recent: DesktopOsTrayMessage[]; nextEvent: { title: string; when: string } | null; + /** The account `unread` is from, when more than one is signed in. */ + account?: string; } export type DesktopOsPowerEvent = 'suspend' | 'resume' | 'lock-screen' | 'unlock-screen';