fix bugs
This commit is contained in:
@@ -2593,7 +2593,7 @@ export default function Home() {
|
|||||||
isScheduledView={isScheduledView}
|
isScheduledView={isScheduledView}
|
||||||
onLoadMoreScheduled={() => client && loadMoreScheduledEmails(client)}
|
onLoadMoreScheduled={() => client && loadMoreScheduledEmails(client)}
|
||||||
onCancelScheduled={async (email) => {
|
onCancelScheduled={async (email) => {
|
||||||
if (client && email.emailSubmissionId) await cancelScheduledEmail(client, email.emailSubmissionId);
|
if (client && email.emailSubmissionId) await cancelScheduledEmail(client, email.emailSubmissionId, email.id);
|
||||||
}}
|
}}
|
||||||
onCancelScheduledForEdit={async (email) => {
|
onCancelScheduledForEdit={async (email) => {
|
||||||
if (!client) return;
|
if (!client) return;
|
||||||
@@ -2878,7 +2878,7 @@ export default function Home() {
|
|||||||
onShowShortcuts={() => setShowShortcutsModal(true)}
|
onShowShortcuts={() => setShowShortcutsModal(true)}
|
||||||
onEditDraft={handleEditDraft}
|
onEditDraft={handleEditDraft}
|
||||||
onCancelScheduled={async () => {
|
onCancelScheduled={async () => {
|
||||||
if (client && selectedEmail?.emailSubmissionId) await cancelScheduledEmail(client, selectedEmail.emailSubmissionId);
|
if (client && selectedEmail?.emailSubmissionId) await cancelScheduledEmail(client, selectedEmail.emailSubmissionId, selectedEmail.id);
|
||||||
}}
|
}}
|
||||||
onCancelScheduledForEdit={async () => {
|
onCancelScheduledForEdit={async () => {
|
||||||
if (!client || !selectedEmail) return;
|
if (!client || !selectedEmail) return;
|
||||||
|
|||||||
@@ -1822,7 +1822,7 @@ export async function GET(request: NextRequest, { params }: { params: Promise<{
|
|||||||
isReadOnly: false,
|
isReadOnly: false,
|
||||||
accountCapabilities: {
|
accountCapabilities: {
|
||||||
'urn:ietf:params:jmap:mail': {},
|
'urn:ietf:params:jmap:mail': {},
|
||||||
'urn:ietf:params:jmap:submission': { maxDelayedSend: 2592000 },
|
'urn:ietf:params:jmap:submission': { maxDelayedSend: 2592000, submissionExtensions: { FUTURERELEASE: true } },
|
||||||
'urn:ietf:params:jmap:quota': {},
|
'urn:ietf:params:jmap:quota': {},
|
||||||
'urn:ietf:params:jmap:vacationresponse': {},
|
'urn:ietf:params:jmap:vacationresponse': {},
|
||||||
'urn:ietf:params:jmap:contacts': {},
|
'urn:ietf:params:jmap:contacts': {},
|
||||||
|
|||||||
+45
-33
@@ -5582,43 +5582,56 @@ export class JMAPClient implements IJMAPClient {
|
|||||||
return { emails: [], hasMore: false, total: 0 };
|
return { emails: [], hasMore: false, total: 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryResponse = await this.request([
|
|
||||||
['EmailSubmission/query', {
|
|
||||||
accountId: this.getSubmissionAccountId(),
|
|
||||||
limit,
|
|
||||||
position,
|
|
||||||
}, '0'],
|
|
||||||
]);
|
|
||||||
|
|
||||||
const query = queryResponse.methodResponses?.[0]?.[1] as { ids?: string[]; total?: number; position?: number } | undefined;
|
|
||||||
const ids = query?.ids ?? [];
|
|
||||||
if (ids.length === 0) {
|
|
||||||
return { emails: [], hasMore: false, total: query?.total ?? 0 };
|
|
||||||
}
|
|
||||||
|
|
||||||
const submissionResponse = await this.request([
|
|
||||||
['EmailSubmission/get', {
|
|
||||||
accountId: this.getSubmissionAccountId(),
|
|
||||||
ids,
|
|
||||||
properties: ['id', 'emailId', 'identityId', 'threadId', 'sendAt', 'undoStatus', 'deliveryStatus'],
|
|
||||||
}, '0'],
|
|
||||||
]);
|
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
const submissions = ((submissionResponse.methodResponses?.[0]?.[1]?.list ?? []) as EmailSubmission[])
|
const pageSize = Math.max(limit, 50);
|
||||||
.filter(submission => {
|
const submissions: EmailSubmission[] = [];
|
||||||
if (!submission.sendAt) return false;
|
let rawPosition = 0;
|
||||||
const sendAtTime = new Date(submission.sendAt).getTime();
|
let rawTotal = 0;
|
||||||
return Number.isFinite(sendAtTime) && sendAtTime > now;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (submissions.length === 0) {
|
do {
|
||||||
return { emails: [], hasMore: false, total: query?.total ?? 0 };
|
const queryResponse = await this.request([
|
||||||
|
['EmailSubmission/query', {
|
||||||
|
accountId: this.getSubmissionAccountId(),
|
||||||
|
limit: pageSize,
|
||||||
|
position: rawPosition,
|
||||||
|
}, '0'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
const query = queryResponse.methodResponses?.[0]?.[1] as { ids?: string[]; total?: number; position?: number } | undefined;
|
||||||
|
const ids = query?.ids ?? [];
|
||||||
|
rawTotal = query?.total ?? rawPosition + ids.length;
|
||||||
|
if (ids.length === 0) break;
|
||||||
|
|
||||||
|
const submissionResponse = await this.request([
|
||||||
|
['EmailSubmission/get', {
|
||||||
|
accountId: this.getSubmissionAccountId(),
|
||||||
|
ids,
|
||||||
|
properties: ['id', 'emailId', 'identityId', 'threadId', 'sendAt', 'undoStatus', 'deliveryStatus'],
|
||||||
|
}, '0'],
|
||||||
|
]);
|
||||||
|
|
||||||
|
submissions.push(...((submissionResponse.methodResponses?.[0]?.[1]?.list ?? []) as EmailSubmission[])
|
||||||
|
.filter(submission => {
|
||||||
|
if (submission.undoStatus !== 'pending' || !submission.sendAt) return false;
|
||||||
|
const sendAtTime = new Date(submission.sendAt).getTime();
|
||||||
|
return Number.isFinite(sendAtTime) && sendAtTime > now;
|
||||||
|
}));
|
||||||
|
|
||||||
|
rawPosition += ids.length;
|
||||||
|
} while (rawPosition < rawTotal);
|
||||||
|
|
||||||
|
submissions.sort((a, b) => new Date(a.sendAt || '').getTime() - new Date(b.sendAt || '').getTime());
|
||||||
|
const total = submissions.length;
|
||||||
|
const pageSubmissions = submissions.slice(position, position + limit);
|
||||||
|
|
||||||
|
if (pageSubmissions.length === 0) {
|
||||||
|
return { emails: [], hasMore: false, total };
|
||||||
}
|
}
|
||||||
|
|
||||||
const emailResponse = await this.request([
|
const emailResponse = await this.request([
|
||||||
['Email/get', {
|
['Email/get', {
|
||||||
accountId: this.accountId,
|
accountId: this.accountId,
|
||||||
ids: submissions.map(submission => submission.emailId),
|
ids: pageSubmissions.map(submission => submission.emailId),
|
||||||
properties: [
|
properties: [
|
||||||
'id', 'threadId', 'mailboxIds', 'keywords', 'size', 'receivedAt', 'from', 'to', 'cc', 'bcc', 'replyTo',
|
'id', 'threadId', 'mailboxIds', 'keywords', 'size', 'receivedAt', 'from', 'to', 'cc', 'bcc', 'replyTo',
|
||||||
'subject', 'preview', 'textBody', 'htmlBody', 'bodyValues', 'attachments', 'hasAttachment', 'sentAt',
|
'subject', 'preview', 'textBody', 'htmlBody', 'bodyValues', 'attachments', 'hasAttachment', 'sentAt',
|
||||||
@@ -5632,7 +5645,7 @@ export class JMAPClient implements IJMAPClient {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
const emailById = new Map(((emailResponse.methodResponses?.[0]?.[1]?.list ?? []) as Email[]).map(email => [email.id, email]));
|
const emailById = new Map(((emailResponse.methodResponses?.[0]?.[1]?.list ?? []) as Email[]).map(email => [email.id, email]));
|
||||||
const emails = submissions
|
const emails = pageSubmissions
|
||||||
.map((submission): ScheduledEmail | null => {
|
.map((submission): ScheduledEmail | null => {
|
||||||
const email = emailById.get(submission.emailId);
|
const email = emailById.get(submission.emailId);
|
||||||
if (!email || !submission.sendAt) return null;
|
if (!email || !submission.sendAt) return null;
|
||||||
@@ -5651,8 +5664,7 @@ export class JMAPClient implements IJMAPClient {
|
|||||||
.filter((email): email is ScheduledEmail => email !== null)
|
.filter((email): email is ScheduledEmail => email !== null)
|
||||||
.sort((a, b) => new Date(a.scheduledSendAt).getTime() - new Date(b.scheduledSendAt).getTime());
|
.sort((a, b) => new Date(a.scheduledSendAt).getTime() - new Date(b.scheduledSendAt).getTime());
|
||||||
|
|
||||||
const total = query?.total ?? emails.length;
|
return { emails, hasMore: position + emails.length < total, total };
|
||||||
return { emails, hasMore: computeHasMore(position, ids.length, total, limit), total };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async cancelEmailSubmission(submissionId: string): Promise<void> {
|
async cancelEmailSubmission(submissionId: string): Promise<void> {
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ interface EmailStore {
|
|||||||
|
|
||||||
fetchScheduledEmails: (client: IJMAPClient) => Promise<void>;
|
fetchScheduledEmails: (client: IJMAPClient) => Promise<void>;
|
||||||
loadMoreScheduledEmails: (client: IJMAPClient) => Promise<void>;
|
loadMoreScheduledEmails: (client: IJMAPClient) => Promise<void>;
|
||||||
cancelScheduledEmail: (client: IJMAPClient, submissionId: string) => Promise<void>;
|
cancelScheduledEmail: (client: IJMAPClient, submissionId: string, emailId?: string) => Promise<void>;
|
||||||
cancelScheduledEmailForEdit: (client: IJMAPClient, email: ScheduledEmail | Email) => Promise<Email | null>;
|
cancelScheduledEmailForEdit: (client: IJMAPClient, email: ScheduledEmail | Email) => Promise<Email | null>;
|
||||||
rescheduleScheduledEmail: (client: IJMAPClient, submissionId: string, emailId: string, identityId: string, delayedUntil: string) => Promise<SendEmailResult>;
|
rescheduleScheduledEmail: (client: IJMAPClient, submissionId: string, emailId: string, identityId: string, delayedUntil: string) => Promise<SendEmailResult>;
|
||||||
cancelUndoSend: (client: IJMAPClient, pending: PendingUndoSend) => Promise<Email | null>;
|
cancelUndoSend: (client: IJMAPClient, pending: PendingUndoSend) => Promise<Email | null>;
|
||||||
@@ -2182,8 +2182,11 @@ export const useEmailStore = create<EmailStore>((set, get) => ({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
cancelScheduledEmail: async (client, submissionId) => {
|
cancelScheduledEmail: async (client, submissionId, emailId) => {
|
||||||
await client.cancelEmailSubmission(submissionId);
|
await client.cancelEmailSubmission(submissionId);
|
||||||
|
if (emailId) {
|
||||||
|
await client.deleteEmail(emailId);
|
||||||
|
}
|
||||||
if (get().pendingUndoSend?.submissionId === submissionId) {
|
if (get().pendingUndoSend?.submissionId === submissionId) {
|
||||||
set({ pendingUndoSend: null });
|
set({ pendingUndoSend: null });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -494,7 +494,6 @@ export const useSettingsStore = create<SettingsState>()(
|
|||||||
plainTextMode: state.plainTextMode,
|
plainTextMode: state.plainTextMode,
|
||||||
subAddressDelimiter: state.subAddressDelimiter,
|
subAddressDelimiter: state.subAddressDelimiter,
|
||||||
sendDelaySeconds: state.sendDelaySeconds,
|
sendDelaySeconds: state.sendDelaySeconds,
|
||||||
sendDelaySeconds: state.sendDelaySeconds,
|
|
||||||
signaturePosition: state.signaturePosition,
|
signaturePosition: state.signaturePosition,
|
||||||
signatureSeparatorEnabled: state.signatureSeparatorEnabled,
|
signatureSeparatorEnabled: state.signatureSeparatorEnabled,
|
||||||
sessionTimeout: state.sessionTimeout,
|
sessionTimeout: state.sessionTimeout,
|
||||||
|
|||||||
Reference in New Issue
Block a user