feat: per-account All Mail folder selection
Replaces the global allMailFolderIds (string[] | null) with a per-account
Record<accountId, string[]>, so each account chooses which of its own folders
the "All Mail" view merges. A missing entry = "not configured" (defaults to
every no-role folder); an explicit [] = "no folders".
- settings-store: type/default -> Record (default {}); persist version 4 -> 5,
migration drops the legacy global list (the active account isn't known at
migrate time); onRehydrate + importSettings coerce/ignore any non-record
(legacy global string[] | null) shape. isPlainRecord() guard.
- email-store.resolveAllMailJmapIds: reads the entry for the account the view is
scoped to (viewingAccountId ?? activeAccountId); undefined -> all no-role,
[] -> none.
- layout-settings: read/write the active account's entry; when more than one
account is logged in, an italic hint names the account the selection applies
to (settings.appearance.all_mail.account_hint, 19 locales; de/ro translated).
- Test: stores/__tests__/settings-store-all-mail.test.ts (per-account
independence, explicit-empty vs not-configured, importSettings legacy guard).
This commit is contained in:
committed by
Linus Rath
parent
5c2f206c74
commit
751f3c1685
@@ -0,0 +1,55 @@
|
||||
import { describe, it, expect, beforeEach } from 'vitest';
|
||||
import { useSettingsStore } from '../settings-store';
|
||||
|
||||
describe('settings-store per-account allMailFolderIds', () => {
|
||||
beforeEach(() => {
|
||||
useSettingsStore.setState({ allMailFolderIds: {} });
|
||||
});
|
||||
|
||||
it('defaults to an empty record (every account "not configured")', () => {
|
||||
expect(useSettingsStore.getState().allMailFolderIds).toEqual({});
|
||||
});
|
||||
|
||||
it('keeps each account selection independent', () => {
|
||||
useSettingsStore.setState({
|
||||
allMailFolderIds: { 'acct-1': ['inbox', 'archive'], 'acct-2': ['sent'] },
|
||||
});
|
||||
const map = useSettingsStore.getState().allMailFolderIds;
|
||||
expect(map['acct-1']).toEqual(['inbox', 'archive']);
|
||||
expect(map['acct-2']).toEqual(['sent']);
|
||||
// A third account remains unconfigured (no entry).
|
||||
expect(map['acct-3']).toBeUndefined();
|
||||
});
|
||||
|
||||
it('distinguishes explicit-empty ([] = no folders) from not-configured (undefined)', () => {
|
||||
useSettingsStore.setState({ allMailFolderIds: { 'acct-1': [] } });
|
||||
const map = useSettingsStore.getState().allMailFolderIds;
|
||||
expect(map['acct-1']).toEqual([]); // explicit "no folders"
|
||||
expect(map['acct-2']).toBeUndefined(); // never configured
|
||||
});
|
||||
|
||||
describe('importSettings legacy-shape guard', () => {
|
||||
it('ignores a legacy global array shape', () => {
|
||||
useSettingsStore.setState({ allMailFolderIds: { 'acct-1': ['inbox'] } });
|
||||
const ok = useSettingsStore.getState().importSettings(
|
||||
JSON.stringify({ allMailFolderIds: ['inbox', 'sent'] }),
|
||||
);
|
||||
expect(ok).toBe(true);
|
||||
// unchanged - the array shape was rejected
|
||||
expect(useSettingsStore.getState().allMailFolderIds).toEqual({ 'acct-1': ['inbox'] });
|
||||
});
|
||||
|
||||
it('ignores a null legacy value', () => {
|
||||
useSettingsStore.setState({ allMailFolderIds: { 'acct-1': ['inbox'] } });
|
||||
useSettingsStore.getState().importSettings(JSON.stringify({ allMailFolderIds: null }));
|
||||
expect(useSettingsStore.getState().allMailFolderIds).toEqual({ 'acct-1': ['inbox'] });
|
||||
});
|
||||
|
||||
it('accepts a proper per-account record', () => {
|
||||
useSettingsStore.getState().importSettings(
|
||||
JSON.stringify({ allMailFolderIds: { 'acct-9': ['inbox', 'spam'] } }),
|
||||
);
|
||||
expect(useSettingsStore.getState().allMailFolderIds).toEqual({ 'acct-9': ['inbox', 'spam'] });
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user