mirror of
https://github.com/rowboatlabs/rowboat.git
synced 2026-07-12 21:02:17 +02:00
Merge pull request #650 from rowboatlabs/mail-enhancements
feat(email): drafts, search, read-state controls & Superhuman-style shortcuts
This commit is contained in:
commit
3ba94402d3
8 changed files with 2064 additions and 259 deletions
|
|
@ -107,6 +107,10 @@ export const GmailAttachmentSchema = z.object({
|
|||
mimeType: z.string().optional(),
|
||||
sizeBytes: z.number().int().nonnegative().optional(),
|
||||
savedPath: z.string(),
|
||||
// Gmail identifiers used to fetch the attachment on demand when it hasn't
|
||||
// been downloaded to disk yet (e.g. attachments on search results).
|
||||
messageId: z.string().optional(),
|
||||
attachmentId: z.string().optional(),
|
||||
});
|
||||
|
||||
export type GmailAttachment = z.infer<typeof GmailAttachmentSchema>;
|
||||
|
|
@ -124,6 +128,14 @@ export const GmailThreadMessageSchema = z.object({
|
|||
bodyHeight: z.number().int().positive().optional(),
|
||||
attachments: z.array(GmailAttachmentSchema).optional(),
|
||||
messageIdHeader: z.string().optional(),
|
||||
// Set on the unsent draft message within a thread (used by the Drafts view).
|
||||
isDraft: z.boolean().optional(),
|
||||
// The draft's own stored In-Reply-To / References headers. Only set on
|
||||
// draft messages: a Drafts-view pseudo-thread contains just the draft, so
|
||||
// the composer can't rebuild the reply chain from thread messages and must
|
||||
// reuse what the draft already carries.
|
||||
inReplyToHeader: z.string().optional(),
|
||||
referencesHeader: z.string().optional(),
|
||||
});
|
||||
|
||||
export type GmailThreadMessage = z.infer<typeof GmailThreadMessageSchema>;
|
||||
|
|
@ -134,6 +146,9 @@ export const GmailThreadSchema = EmailBlockSchema.extend({
|
|||
unread: z.boolean().optional(),
|
||||
importance: z.enum(['important', 'other']).optional(),
|
||||
gmail_draft: z.string().optional(),
|
||||
// Gmail-side draft id, present on entries returned by the Drafts list so the
|
||||
// composer can update/delete that exact draft.
|
||||
draftId: z.string().optional(),
|
||||
messages: z.array(GmailThreadMessageSchema),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -207,6 +207,56 @@ const ipcSchemas = {
|
|||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'gmail:saveDraft': {
|
||||
req: z.object({
|
||||
// Existing Gmail draft to update; omitted on first save (creates a new one).
|
||||
draftId: z.string().min(1).optional(),
|
||||
threadId: z.string().min(1).optional(),
|
||||
// Recipients may be blank for a draft (unlike a send).
|
||||
to: z.string().optional(),
|
||||
cc: z.string().optional(),
|
||||
bcc: z.string().optional(),
|
||||
subject: z.string(),
|
||||
bodyHtml: z.string(),
|
||||
bodyText: z.string(),
|
||||
inReplyTo: z.string().optional(),
|
||||
references: z.string().optional(),
|
||||
attachments: z
|
||||
.array(
|
||||
z.object({
|
||||
filename: z.string(),
|
||||
mimeType: z.string(),
|
||||
contentBase64: z.string(),
|
||||
}),
|
||||
)
|
||||
.optional(),
|
||||
}),
|
||||
res: z.object({
|
||||
draftId: z.string().optional(),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'gmail:deleteDraft': {
|
||||
req: z.object({ draftId: z.string().min(1) }),
|
||||
res: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
||||
},
|
||||
'gmail:getDrafts': {
|
||||
req: z.object({}),
|
||||
res: z.object({
|
||||
threads: z.array(GmailThreadSchema),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'gmail:search': {
|
||||
req: z.object({
|
||||
query: z.string(),
|
||||
limit: z.number().int().positive().optional(),
|
||||
}),
|
||||
res: z.object({
|
||||
threads: z.array(GmailThreadSchema),
|
||||
error: z.string().optional(),
|
||||
}),
|
||||
},
|
||||
'gmail:getConnectionStatus': {
|
||||
req: z.object({}),
|
||||
res: z.object({
|
||||
|
|
@ -237,7 +287,15 @@ const ipcSchemas = {
|
|||
res: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
||||
},
|
||||
'gmail:markThreadRead': {
|
||||
req: z.object({ threadId: z.string().min(1) }),
|
||||
req: z.object({ threadId: z.string().min(1), read: z.boolean().optional() }),
|
||||
res: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
||||
},
|
||||
'gmail:downloadAttachment': {
|
||||
req: z.object({
|
||||
messageId: z.string().min(1),
|
||||
savedPath: z.string().min(1),
|
||||
attachmentId: z.string().optional(),
|
||||
}),
|
||||
res: z.object({ ok: z.boolean(), error: z.string().optional() }),
|
||||
},
|
||||
'gmail:saveMessageHeight': {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue