fix: open the inbox on a cold start instead of the folder the app was left in

This commit is contained in:
Linus Rath
2026-10-31 04:46:53 +01:00
parent 4470a4ba82
commit 9067908fef
2 changed files with 36 additions and 3 deletions
@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest';
import type { Email } from '../../api/types';
import type { Email, Mailbox } from '../../api/types';
import {
boundEmailCache,
PERSISTED_ROWS_PER_FOLDER,
@@ -102,6 +102,8 @@ describe('boundEmailCache', () => {
});
});
const INBOX = { id: 'inbox', name: 'Inbox', role: 'inbox', isShared: false } as unknown as Mailbox;
describe('email-store persistence', () => {
const { partialize, merge } = useEmailStore.persist.getOptions();
@@ -149,6 +151,7 @@ describe('email-store persistence', () => {
it('restores the open folder into the list on hydration', () => {
const live = rows('live', 3);
const persisted = JSON.parse(JSON.stringify(partialize!(viewState({
mailboxes: [INBOX],
emails: live,
totalEmails: 42,
queryState: 'q2',
@@ -170,7 +173,7 @@ describe('email-store persistence', () => {
const legacy = {
accountSnapshots: {},
activeAccountId: 'me',
mailboxes: [],
mailboxes: [INBOX],
emailStates: {},
currentMailboxId: 'inbox',
mailboxSnapshots: { inbox: snap },
@@ -190,4 +193,24 @@ describe('email-store persistence', () => {
const initial = useEmailStore.getInitialState();
expect(merge!(undefined, initial)).toBe(initial);
});
// A cold start reopened the folder (or the search) the app was left in;
// the webmail opens the Inbox (64b39c504).
it('opens the Inbox on a cold start, with its cached rows', () => {
const work = { id: 'work', name: 'Work', role: null, isShared: false } as unknown as Mailbox;
const persisted = JSON.parse(JSON.stringify(partialize!(viewState({
mailboxes: [INBOX, work],
currentMailboxId: 'work',
emails: rows('work', 2),
totalEmails: 2,
mailboxSnapshots: { inbox: { emails: rows('in', 3), total: 3, queryState: 'qi' } },
}))));
const restored = merge!(persisted, useEmailStore.getInitialState());
expect(restored.currentMailboxId).toBe('inbox');
expect(restored.emails.map((e) => e.id)).toEqual(['in0', 'in1', 'in2']);
// The folder's own rows are still cached for when it is opened.
expect(restored.mailboxSnapshots.work.emails).toHaveLength(2);
});
});
+11 -1
View File
@@ -912,6 +912,16 @@ function snapshotFromActive(state: EmailState): AccountSnapshot {
};
}
/**
* A cold start opens the Inbox, not the folder the app was last left in
* (webmail 64b39c504); its cached rows still show at once. Snapshots of the
* other accounts keep their folder for an account switch.
*/
export function coldStartView(snap: AccountSnapshot): AccountSnapshot {
const inbox = snap.mailboxes?.find((m) => m.role === 'inbox' && !m.isShared);
return { ...snap, currentMailboxId: inbox?.id ?? null };
}
function viewFromSnapshot(snap: AccountSnapshot | null): {
mailboxes: Mailbox[];
mailboxState?: string;
@@ -2416,7 +2426,7 @@ export const useEmailStore = create<EmailState>()(
merge: (persisted, current) => {
if (!persisted) return current;
const cache = persisted as PersistedEmailCache;
return { ...current, ...cache, ...viewFromSnapshot(cache) };
return { ...current, ...cache, ...viewFromSnapshot(coldStartView(cache)) };
},
},
),