mirror of
https://github.com/bulwarkmail/native.git
synced 2026-10-31 00:06:17 +00:00
fix: leave a message unread when the server refuses to move it to trash across accounts
This commit is contained in:
@@ -481,6 +481,25 @@ describe('opening and acting on "All folders" rows (#1082)', () => {
|
||||
expect(useEmailStore.getState().pendingUndo?.items.map((it) => it.email.id).sort()).toEqual(['m1', 'o1']);
|
||||
});
|
||||
|
||||
// "Move to Trash and mark as read": a message the server refused to move
|
||||
// stays in its folder, so it must not be marked read either.
|
||||
it('marks only the moved rows read when the server refuses one of them', async () => {
|
||||
settings.deleteAction = 'trash-and-read';
|
||||
await search('zephyr');
|
||||
server.current!.refusing.set('team', new Set(['m2']));
|
||||
|
||||
await useEmailStore.getState()
|
||||
.deleteEmailsBatch(['team:m1', 'team:m2'], 'trash', 'inbox')
|
||||
.catch(() => undefined);
|
||||
|
||||
const seenPatches = server.current!.callsOf('Email/set')
|
||||
.flatMap(([, a]) => Object.entries((a.update ?? {}) as Record<string, Record<string, unknown>>))
|
||||
.filter(([, patch]) => Object.keys(patch).some((k) => k.startsWith('keywords')))
|
||||
.map(([id]) => id);
|
||||
expect(seenPatches).toEqual(['m1']);
|
||||
expect(server.current!.accounts.team.find((e) => e.id === 'm1')!.keywords).toEqual({ $seen: true });
|
||||
});
|
||||
|
||||
it('files the rest when one account refuses a whole move', async () => {
|
||||
await search('zephyr');
|
||||
server.current!.failing.set('team', 'forbidden');
|
||||
|
||||
@@ -2400,6 +2400,8 @@ async function fileAcrossAccounts(action: SpanningAction, targets: Email[], toMa
|
||||
const items: UndoEntry['items'] = [];
|
||||
const gone: Array<{ email: Email; key: string }> = [];
|
||||
const keyOf = (accountId: string | undefined, id: string) => `${accountId ?? ''}:${id}`;
|
||||
// Rows a server refused to file (see the runs below), by `keyOf`.
|
||||
const refused = new Set<string>();
|
||||
const copies: Array<{ accountId?: string; emails: Email[] }> = [];
|
||||
let missing: string | null = null;
|
||||
let refreshFolders = false;
|
||||
@@ -2489,7 +2491,12 @@ async function fileAcrossAccounts(action: SpanningAction, targets: Email[], toMa
|
||||
});
|
||||
if (unread.length > 0) {
|
||||
runs.push({
|
||||
run: () => patchKeywordsForEmails(ids(unread), { $seen: true }, accountId),
|
||||
// Runs after the move: a row the server refused to move stays
|
||||
// where it is, unread, as in the single-account delete.
|
||||
run: async () => {
|
||||
const moved = ids(unread).filter((id) => !refused.has(keyOf(accountId, id)));
|
||||
if (moved.length > 0) await patchKeywordsForEmails(moved, { $seen: true }, accountId);
|
||||
},
|
||||
accountId,
|
||||
ids: ids(unread),
|
||||
keeps: false,
|
||||
@@ -2536,7 +2543,6 @@ async function fileAcrossAccounts(action: SpanningAction, targets: Email[], toMa
|
||||
// account may refuse what another takes (a read-only share): the refused
|
||||
// rows stay, the others are filed, and the first refusal is reported once
|
||||
// the list shows the rest. Before, one refused message kept every row.
|
||||
const refused = new Set<string>();
|
||||
const unpatched = new Set<string>();
|
||||
let refusal: unknown = null;
|
||||
if (ops.length > 0) {
|
||||
|
||||
Reference in New Issue
Block a user