diff --git a/components/email/__tests__/email-list-paged.test.tsx b/components/email/__tests__/email-list-paged.test.tsx index 5742d8bb0..36097eeda 100644 --- a/components/email/__tests__/email-list-paged.test.tsx +++ b/components/email/__tests__/email-list-paged.test.tsx @@ -19,7 +19,7 @@ vi.mock('@/stores/auth-store', async () => { }; }); vi.mock('@/stores/account-store', () => { - const state = { getAccountById: () => undefined }; + const state = { accounts: [], getAccountById: () => undefined }; return { useAccountStore: Object.assign( (selector?: (s: typeof state) => unknown) => (selector ? selector(state) : state), diff --git a/components/email/__tests__/email-list-plugin-filters.test.tsx b/components/email/__tests__/email-list-plugin-filters.test.tsx index 4e9c534b0..4bac6c7e3 100644 --- a/components/email/__tests__/email-list-plugin-filters.test.tsx +++ b/components/email/__tests__/email-list-plugin-filters.test.tsx @@ -35,7 +35,7 @@ vi.mock('@/stores/auth-store', async () => { }; }); vi.mock('@/stores/account-store', () => { - const state = { getAccountById: () => undefined }; + const state = { accounts: [], getAccountById: () => undefined }; return { useAccountStore: Object.assign( (selector?: (s: typeof state) => unknown) => (selector ? selector(state) : state), diff --git a/components/email/__tests__/email-list-range-rows.test.tsx b/components/email/__tests__/email-list-range-rows.test.tsx index 40d364f1c..b9f767980 100644 --- a/components/email/__tests__/email-list-range-rows.test.tsx +++ b/components/email/__tests__/email-list-range-rows.test.tsx @@ -21,7 +21,7 @@ vi.mock('@/stores/auth-store', async () => { }; }); vi.mock('@/stores/account-store', () => { - const state = { getAccountById: () => undefined }; + const state = { accounts: [], getAccountById: () => undefined }; return { useAccountStore: Object.assign( (selector?: (s: typeof state) => unknown) => (selector ? selector(state) : state), diff --git a/components/email/__tests__/email-list-scroll-reset.test.tsx b/components/email/__tests__/email-list-scroll-reset.test.tsx index 0ce74a5ed..6ee4ca167 100644 --- a/components/email/__tests__/email-list-scroll-reset.test.tsx +++ b/components/email/__tests__/email-list-scroll-reset.test.tsx @@ -19,7 +19,7 @@ vi.mock('@/stores/auth-store', async () => { }; }); vi.mock('@/stores/account-store', () => { - const state = { getAccountById: () => undefined }; + const state = { accounts: [], getAccountById: () => undefined }; return { useAccountStore: Object.assign( (selector?: (s: typeof state) => unknown) => (selector ? selector(state) : state), diff --git a/components/email/__tests__/email-list-skeleton.test.tsx b/components/email/__tests__/email-list-skeleton.test.tsx index 52cdb77c6..bdf68953c 100644 --- a/components/email/__tests__/email-list-skeleton.test.tsx +++ b/components/email/__tests__/email-list-skeleton.test.tsx @@ -15,7 +15,7 @@ vi.mock('@/stores/auth-store', async () => { }; }); vi.mock('@/stores/account-store', () => { - const state = { getAccountById: () => undefined }; + const state = { accounts: [], getAccountById: () => undefined }; return { useAccountStore: Object.assign( (selector?: (s: typeof state) => unknown) => (selector ? selector(state) : state), diff --git a/components/email/__tests__/email-list-thread-expand-mark-read.test.tsx b/components/email/__tests__/email-list-thread-expand-mark-read.test.tsx index c605a2e03..4eea6d0c7 100644 --- a/components/email/__tests__/email-list-thread-expand-mark-read.test.tsx +++ b/components/email/__tests__/email-list-thread-expand-mark-read.test.tsx @@ -47,7 +47,7 @@ vi.mock('@/stores/auth-store', async () => { }; }); vi.mock('@/stores/account-store', () => { - const state = { getAccountById: () => undefined }; + const state = { accounts: [], getAccountById: () => undefined }; return { useAccountStore: Object.assign( (selector?: (s: typeof state) => unknown) => (selector ? selector(state) : state), diff --git a/components/email/__tests__/email-list-unread-first.test.tsx b/components/email/__tests__/email-list-unread-first.test.tsx index 173dc18e9..80c0aefec 100644 --- a/components/email/__tests__/email-list-unread-first.test.tsx +++ b/components/email/__tests__/email-list-unread-first.test.tsx @@ -21,7 +21,7 @@ vi.mock('@/stores/auth-store', async () => { }; }); vi.mock('@/stores/account-store', () => { - const state = { getAccountById: () => undefined }; + const state = { accounts: [], getAccountById: () => undefined }; return { useAccountStore: Object.assign( (selector?: (s: typeof state) => unknown) => (selector ? selector(state) : state), diff --git a/components/email/__tests__/plugin-row-badges.test.tsx b/components/email/__tests__/plugin-row-badges.test.tsx index 8ac012a9a..eafb2c6ed 100644 --- a/components/email/__tests__/plugin-row-badges.test.tsx +++ b/components/email/__tests__/plugin-row-badges.test.tsx @@ -24,7 +24,7 @@ vi.mock('@/stores/auth-store', () => { }); vi.mock('@/stores/account-store', () => { - const state = { getAccountById: () => undefined }; + const state = { accounts: [], getAccountById: () => undefined }; return { useAccountStore: Object.assign( // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/components/email/__tests__/thread-list-item-account-dot.test.tsx b/components/email/__tests__/thread-list-item-account-dot.test.tsx index 482048d1f..53678ca47 100644 --- a/components/email/__tests__/thread-list-item-account-dot.test.tsx +++ b/components/email/__tests__/thread-list-item-account-dot.test.tsx @@ -19,7 +19,9 @@ vi.mock('@/stores/auth-store', () => { }); const ACCOUNT_TEAL = { id: 'acct-teal', avatarColor: '#0d9488', label: 'Teal account' }; +const ACCOUNT_OTHER = { id: 'acct-other', avatarColor: '#dc2626', label: 'Other account' }; const accountState = { + accounts: [ACCOUNT_TEAL, ACCOUNT_OTHER] as { id: string }[], getAccountById: (id: string) => (id === ACCOUNT_TEAL.id ? ACCOUNT_TEAL : undefined), }; vi.mock('@/stores/account-store', () => ({ @@ -65,6 +67,7 @@ const accountDot = (c: HTMLElement) => describe('ThreadListItem account dot (#912)', () => { beforeEach(() => { + accountState.accounts = [ACCOUNT_TEAL, ACCOUNT_OTHER]; useUIStore.setState({ isMobile: false, isTablet: false, isDesktop: true }); useSettingsStore.setState({ emailKeywords: [...DEFAULT_KEYWORDS], @@ -105,6 +108,13 @@ describe('ThreadListItem account dot (#912)', () => { // The rest of the row still renders. expect(container.textContent).toContain('Test Subject'); }); + + it('hides the dot with only one account signed in', () => { + accountState.accounts = [ACCOUNT_TEAL]; + const { container } = renderEmails(emails()); + expect(accountDot(container)).toBeNull(); + expect(container.textContent).toContain('Test Subject'); + }); }); }); }); diff --git a/components/email/__tests__/thread-list-item-source-folder.test.tsx b/components/email/__tests__/thread-list-item-source-folder.test.tsx index 672aad8da..debaad59e 100644 --- a/components/email/__tests__/thread-list-item-source-folder.test.tsx +++ b/components/email/__tests__/thread-list-item-source-folder.test.tsx @@ -21,7 +21,7 @@ vi.mock('@/stores/auth-store', () => { }; }); -const accountState = { getAccountById: () => undefined }; +const accountState = { accounts: [], getAccountById: () => undefined }; vi.mock('@/stores/account-store', () => ({ useAccountStore: Object.assign( // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/components/email/__tests__/thread-list-item.test.tsx b/components/email/__tests__/thread-list-item.test.tsx index 64210cc04..00ccb6845 100644 --- a/components/email/__tests__/thread-list-item.test.tsx +++ b/components/email/__tests__/thread-list-item.test.tsx @@ -23,6 +23,7 @@ vi.mock('@/stores/auth-store', () => { const ACCOUNT_TEAL = { id: 'acct-teal', avatarColor: '#0d9488', label: 'Teal account' }; const accountState = { + accounts: [ACCOUNT_TEAL], getAccountById: (id: string) => (id === ACCOUNT_TEAL.id ? ACCOUNT_TEAL : undefined), }; vi.mock('@/stores/account-store', () => ({ diff --git a/components/email/thread-list-item.tsx b/components/email/thread-list-item.tsx index f13bc0980..366647703 100644 --- a/components/email/thread-list-item.tsx +++ b/components/email/thread-list-item.tsx @@ -84,6 +84,16 @@ export function listMailboxRole(state: { ?? (state.isUnifiedView ? (state.unifiedRole ?? undefined) : undefined); } +/** + * The account dot tells signed-in accounts apart. With a single account every + * row would carry the same dot, so it only shows once there are two or more. + */ +function useShowAccountDot(tintListRowsByAccount: boolean): boolean { + const enabled = useSettingsStore((state) => state.showAccountDot); + const severalAccounts = useAccountStore((state) => state.accounts.length > 1); + return enabled && severalAccounts && !tintListRowsByAccount; +} + /** Hover actions mount on the first pointerover or keyboard focus in the row. */ function useArmOnPointerOver(): [boolean, () => void] { const [armed, setArmed] = React.useState(false); @@ -445,7 +455,7 @@ const SingleEmailItem = React.forwardRef( const tintListRowsByTag = useSettingsStore((state) => state.tintListRowsByTag); const tintListRowsByAccount = useSettingsStore((state) => state.tintListRowsByAccount); // The tint replaces the dot, and the dot can be switched off on its own (#912). - const showAccountDot = useSettingsStore((state) => state.showAccountDot) && !tintListRowsByAccount; + const showAccountDot = useShowAccountDot(tintListRowsByAccount); const density = useSettingsStore((state) => state.density); const timeFormat = useSettingsStore((state) => state.timeFormat); const showAvatarsInJunk = useSettingsStore((state) => state.showAvatarsInJunk); @@ -1175,7 +1185,7 @@ export const ThreadListItem = React.forwardRef state.tintListRowsByTag); const tintListRowsByAccount = useSettingsStore((state) => state.tintListRowsByAccount); // The tint replaces the dot, and the dot can be switched off on its own (#912). - const showAccountDot = useSettingsStore((state) => state.showAccountDot) && !tintListRowsByAccount; + const showAccountDot = useShowAccountDot(tintListRowsByAccount); // A collapsed row speaks for every message under it, so it carries their tags too. const tagIds = sortTagIds(getThreadTagIds(thread.emails)); const threadTintSource = threadAccountColor