mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 08:13:50 +00:00
Expanding a conversation in the message list (row click, expand chevron, or the `x` shortcut) and clicking a row in a Pro folder tab marked the messages read straight away. They ignored "Mark as read: Never" and any delay, which the reading pane and the conversation view follow. Route them through one helper, scheduleAutoMarkAsRead: -1 never marks, 0 marks at once, any other value marks after that many milliseconds and returns a cancel function. - New store action autoMarkExpandedThreadAsRead keeps one pending timer per thread key. Collapsing the thread, or collapsing all threads, drops it. Both expansion paths (EmailList and the `x` handler in MailApp) use it. - MailApp's handleEmailSelect drops the pending mark of every expanded thread other than the one the newly opened message belongs to, through cancelAutoMarkThreadAsRead. Moving on with `j`/`k` or a click no longer lets the delayed mark land on a conversation the user has left. The thread stays expanded. - ProFolderTabBody schedules the row mark through the helper and drops a pending one when another row is opened or the tab unmounts.
44 lines
1.2 KiB
TypeScript
44 lines
1.2 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
import { scheduleAutoMarkAsRead } from '../mark-as-read-delay';
|
|
|
|
describe('scheduleAutoMarkAsRead', () => {
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
});
|
|
|
|
afterEach(() => {
|
|
vi.useRealTimers();
|
|
});
|
|
|
|
it('never marks with "Never" (-1)', () => {
|
|
const mark = vi.fn();
|
|
scheduleAutoMarkAsRead(-1, mark);
|
|
vi.advanceTimersByTime(60_000);
|
|
expect(mark).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it('marks synchronously with "Instantly" (0)', () => {
|
|
const mark = vi.fn();
|
|
scheduleAutoMarkAsRead(0, mark);
|
|
expect(mark).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('marks once the delay has passed', () => {
|
|
const mark = vi.fn();
|
|
scheduleAutoMarkAsRead(3000, mark);
|
|
vi.advanceTimersByTime(2999);
|
|
expect(mark).not.toHaveBeenCalled();
|
|
vi.advanceTimersByTime(1);
|
|
expect(mark).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('drops a pending delayed mark when cancelled', () => {
|
|
const mark = vi.fn();
|
|
const cancel = scheduleAutoMarkAsRead(3000, mark);
|
|
vi.advanceTimersByTime(1000);
|
|
cancel();
|
|
vi.advanceTimersByTime(10_000);
|
|
expect(mark).not.toHaveBeenCalled();
|
|
});
|
|
});
|