feat: add support for marking emails as answered or forwarded and update UI accordingly
This commit is contained in:
@@ -89,6 +89,22 @@ describe('groupEmailsByThread', () => {
|
||||
expect(groupEmailsByThread(emails)[0].hasAttachment).toBe(true);
|
||||
});
|
||||
|
||||
it('detects hasAnswered when an email has $answered', () => {
|
||||
const emails = [
|
||||
makeEmail({ id: 'e1', keywords: { $seen: true } }),
|
||||
makeEmail({ id: 'e2', keywords: { $seen: true, $answered: true } }),
|
||||
];
|
||||
expect(groupEmailsByThread(emails)[0].hasAnswered).toBe(true);
|
||||
});
|
||||
|
||||
it('detects hasForwarded when an email has $forwarded', () => {
|
||||
const emails = [
|
||||
makeEmail({ id: 'e1', keywords: { $seen: true } }),
|
||||
makeEmail({ id: 'e2', keywords: { $seen: true, $forwarded: true } }),
|
||||
];
|
||||
expect(groupEmailsByThread(emails)[0].hasForwarded).toBe(true);
|
||||
});
|
||||
|
||||
it('returns empty array for empty input', () => {
|
||||
expect(groupEmailsByThread([])).toEqual([]);
|
||||
});
|
||||
@@ -110,6 +126,8 @@ describe('sortThreadGroups', () => {
|
||||
hasUnread: false,
|
||||
hasStarred: false,
|
||||
hasAttachment: false,
|
||||
hasAnswered: false,
|
||||
hasForwarded: false,
|
||||
emailCount: 1,
|
||||
},
|
||||
{
|
||||
@@ -120,6 +138,8 @@ describe('sortThreadGroups', () => {
|
||||
hasUnread: false,
|
||||
hasStarred: false,
|
||||
hasAttachment: false,
|
||||
hasAnswered: false,
|
||||
hasForwarded: false,
|
||||
emailCount: 1,
|
||||
},
|
||||
];
|
||||
@@ -169,6 +189,8 @@ describe('mergeThreadEmails', () => {
|
||||
hasUnread: false,
|
||||
hasStarred: false,
|
||||
hasAttachment: false,
|
||||
hasAnswered: false,
|
||||
hasForwarded: false,
|
||||
emailCount: 2,
|
||||
};
|
||||
const fetched = [
|
||||
@@ -189,6 +211,8 @@ describe('mergeThreadEmails', () => {
|
||||
hasUnread: false,
|
||||
hasStarred: false,
|
||||
hasAttachment: false,
|
||||
hasAnswered: false,
|
||||
hasForwarded: false,
|
||||
emailCount: 1,
|
||||
};
|
||||
const fetched = [
|
||||
|
||||
@@ -216,6 +216,11 @@ export class DemoJMAPClient implements IJMAPClient {
|
||||
if (email) email.keywords = { ...email.keywords, ...keywords };
|
||||
}
|
||||
|
||||
async setKeyword(emailId: string, keyword: string): Promise<void> {
|
||||
const email = this.data.emails.find(e => e.id === emailId);
|
||||
if (email) email.keywords[keyword] = true;
|
||||
}
|
||||
|
||||
async migrateKeyword(oldKeyword: string, newKeyword: string): Promise<number> {
|
||||
let count = 0;
|
||||
for (const email of this.data.emails) {
|
||||
|
||||
@@ -72,6 +72,7 @@ export interface IJMAPClient {
|
||||
batchMarkAsRead(emailIds: string[], read?: boolean): Promise<void>;
|
||||
toggleStar(emailId: string, starred: boolean): Promise<void>;
|
||||
updateEmailKeywords(emailId: string, keywords: Record<string, boolean>): Promise<void>;
|
||||
setKeyword(emailId: string, keyword: string): Promise<void>;
|
||||
migrateKeyword(oldKeyword: string, newKeyword: string): Promise<number>;
|
||||
deleteEmail(emailId: string): Promise<void>;
|
||||
moveToTrash(emailId: string, trashMailboxId: string, accountId?: string): Promise<void>;
|
||||
|
||||
@@ -763,6 +763,19 @@ export class JMAPClient implements IJMAPClient {
|
||||
]);
|
||||
}
|
||||
|
||||
async setKeyword(emailId: string, keyword: string): Promise<void> {
|
||||
await this.request([
|
||||
["Email/set", {
|
||||
accountId: this.accountId,
|
||||
update: {
|
||||
[emailId]: {
|
||||
[`keywords/${keyword}`]: true,
|
||||
},
|
||||
},
|
||||
}, "0"],
|
||||
]);
|
||||
}
|
||||
|
||||
async migrateKeyword(oldKeyword: string, newKeyword: string): Promise<number> {
|
||||
// Query all email IDs that have the old keyword
|
||||
const allIds: string[] = [];
|
||||
|
||||
@@ -142,6 +142,8 @@ export interface ThreadGroup {
|
||||
hasUnread: boolean; // Any unread emails in thread
|
||||
hasStarred: boolean; // Any starred emails in thread
|
||||
hasAttachment: boolean; // Any email has attachment
|
||||
hasAnswered: boolean; // Any email has been replied to
|
||||
hasForwarded: boolean; // Any email has been forwarded
|
||||
emailCount: number; // Total emails in thread
|
||||
}
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ export function groupEmailsByThread(emails: Email[]): ThreadGroup[] {
|
||||
const hasUnread = sortedEmails.some(e => !e.keywords?.$seen);
|
||||
const hasStarred = sortedEmails.some(e => e.keywords?.$flagged);
|
||||
const hasAttachment = sortedEmails.some(e => e.hasAttachment);
|
||||
const hasAnswered = sortedEmails.some(e => e.keywords?.$answered);
|
||||
const hasForwarded = sortedEmails.some(e => e.keywords?.$forwarded);
|
||||
|
||||
threadGroups.push({
|
||||
threadId,
|
||||
@@ -47,6 +49,8 @@ export function groupEmailsByThread(emails: Email[]): ThreadGroup[] {
|
||||
hasUnread,
|
||||
hasStarred,
|
||||
hasAttachment,
|
||||
hasAnswered,
|
||||
hasForwarded,
|
||||
emailCount: sortedEmails.length,
|
||||
});
|
||||
}
|
||||
@@ -123,6 +127,8 @@ export function mergeThreadEmails(
|
||||
const hasUnread = mergedEmails.some(e => !e.keywords?.$seen);
|
||||
const hasStarred = mergedEmails.some(e => e.keywords?.$flagged);
|
||||
const hasAttachment = mergedEmails.some(e => e.hasAttachment);
|
||||
const hasAnswered = mergedEmails.some(e => e.keywords?.$answered);
|
||||
const hasForwarded = mergedEmails.some(e => e.keywords?.$forwarded);
|
||||
|
||||
return {
|
||||
threadId: existingGroup.threadId,
|
||||
@@ -132,6 +138,8 @@ export function mergeThreadEmails(
|
||||
hasUnread,
|
||||
hasStarred,
|
||||
hasAttachment,
|
||||
hasAnswered,
|
||||
hasForwarded,
|
||||
emailCount: mergedEmails.length,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user