mirror of
https://github.com/bulwarkmail/native.git
synced 2026-10-31 08:06:36 +00:00
fix: mark a message read when the notification's Delete moves it to Trash and the delete action says so #86
This commit is contained in:
@@ -288,6 +288,40 @@ describe('pushBackgroundTask notifications', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each([
|
||||||
|
['trash-and-read', { mailboxIds: { 'trash-box': true }, 'keywords/$seen': true }],
|
||||||
|
['trash', { mailboxIds: { 'trash-box': true } }],
|
||||||
|
// Never destroyed from a notification (#68), but not marked read either.
|
||||||
|
['permanent', { mailboxIds: { 'trash-box': true } }],
|
||||||
|
])('follows the delete action setting "%s" (#86)', async (deleteAction, patch) => {
|
||||||
|
await AsyncStorage.setItem('webmail:settings:v1', JSON.stringify({ deleteAction }));
|
||||||
|
const postCalls: any[] = [];
|
||||||
|
(secureFetch as ReturnType<typeof vi.fn>).mockImplementation(async (url: string, opts?: any) => {
|
||||||
|
if (opts?.body) postCalls.push(JSON.parse(opts.body));
|
||||||
|
return {
|
||||||
|
ok: true,
|
||||||
|
json: async () => (url.endsWith('/.well-known/jmap')
|
||||||
|
? {
|
||||||
|
apiUrl: 'https://mail.example.com/jmap/',
|
||||||
|
primaryAccounts: { 'urn:ietf:params:jmap:mail': 'jmap-primary' },
|
||||||
|
accounts: { 'jmap-primary': {} },
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
methodResponses: [
|
||||||
|
['Mailbox/get', { list: [{ id: 'trash-box', role: 'trash' }] }, '0'],
|
||||||
|
['Email/set', { updated: { m1: {} } }, '0'],
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
await handleNotificationAction({ action: 'delete', emailId: 'm1', accountId: LOCAL });
|
||||||
|
|
||||||
|
expect(postCalls[1].methodCalls).toEqual([
|
||||||
|
['Email/set', { accountId: 'jmap-primary', update: { m1: patch } }, '0'],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
it.each([
|
it.each([
|
||||||
['has no trash mailbox', ['Mailbox/get', { list: [{ id: 'inbox', role: 'inbox' }] }, '0']],
|
['has no trash mailbox', ['Mailbox/get', { list: [{ id: 'inbox', role: 'inbox' }] }, '0']],
|
||||||
['cannot list mailboxes', ['error', { type: 'accountNotFound' }, '0']],
|
['cannot list mailboxes', ['error', { type: 'accountNotFound' }, '0']],
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ const EMAIL_PROPERTIES = [
|
|||||||
interface PushPersistedSettings {
|
interface PushPersistedSettings {
|
||||||
emailNotificationsEnabled?: boolean;
|
emailNotificationsEnabled?: boolean;
|
||||||
senderFavicons?: boolean;
|
senderFavicons?: boolean;
|
||||||
|
deleteAction?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function emailNotificationsAllowed(): Promise<boolean> {
|
async function emailNotificationsAllowed(): Promise<boolean> {
|
||||||
@@ -78,6 +79,20 @@ export async function senderFaviconsAllowed(): Promise<boolean> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The "Delete Action" setting, as far as a notification's Delete honours it:
|
||||||
|
// "Move to Trash and mark as read" marks the message read on the way (#86).
|
||||||
|
// "Delete Permanently" still only moves to Trash: a notification never
|
||||||
|
// destroys mail (#68).
|
||||||
|
async function notificationDeleteMarksRead(): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const raw = await AsyncStorage.getItem(SETTINGS_STORAGE_KEY);
|
||||||
|
if (!raw) return false;
|
||||||
|
return (JSON.parse(raw) as PushPersistedSettings).deleteAction === 'trash-and-read';
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** The app's language: the in-app override, else the device's. */
|
/** The app's language: the in-app override, else the device's. */
|
||||||
export async function notificationLocale(): Promise<LocaleCode> {
|
export async function notificationLocale(): Promise<LocaleCode> {
|
||||||
try {
|
try {
|
||||||
@@ -665,13 +680,15 @@ export async function handleNotificationAction(data: unknown): Promise<void> {
|
|||||||
console.warn('[push] no trash mailbox for notification delete', emailAccountId);
|
console.warn('[push] no trash mailbox for notification delete', emailAccountId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const patch: Record<string, unknown> = { mailboxIds: { [trash.id]: true } };
|
||||||
|
if (await notificationDeleteMarksRead()) patch['keywords/$seen'] = true;
|
||||||
const res = await jmapPost(session, [
|
const res = await jmapPost(session, [
|
||||||
[
|
[
|
||||||
'Email/set',
|
'Email/set',
|
||||||
{
|
{
|
||||||
accountId: emailAccountId,
|
accountId: emailAccountId,
|
||||||
update: {
|
update: {
|
||||||
[emailId]: { mailboxIds: { [trash.id]: true } },
|
[emailId]: patch,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
'0',
|
'0',
|
||||||
|
|||||||
Reference in New Issue
Block a user