diff --git a/feature-list.md b/feature-list.md index e8c605e..b6c9aef 100644 --- a/feature-list.md +++ b/feature-list.md @@ -6,6 +6,7 @@ Features to implement over time, roughly in priority order. - **Calendar event responses** — parse `text/calendar` parts from incoming emails and surface Accept / Decline / Tentative actions inline in the email view - **Paste images into composer** — handle `paste` events in the composer, upload the image blob to Fastmail via JMAP `Upload`, insert a `![](cid:...)` reference or inline data URL into the markdown, and embed it correctly in the outgoing multipart email +- **Mark as unread** — button in the email detail view that removes `$seen` via `Email/set` and returns to inbox ## Ideas (not yet prioritized) @@ -17,7 +18,7 @@ Features to implement over time, roughly in priority order. - Draft auto-save - Multiple account support (Gmail, Outlook via IMAP bridge or OAuth) - Unread count badge in sidebar -- Mark as read / unread / starred +- Mark as starred - Archive and delete actions - Mobile-responsive layout - Dark mode diff --git a/src/app/email/[id]/page.tsx b/src/app/email/[id]/page.tsx index ad73cbd..3994fbd 100644 --- a/src/app/email/[id]/page.tsx +++ b/src/app/email/[id]/page.tsx @@ -1,5 +1,5 @@ import Link from "next/link"; -import { getSession, getAccountId, getEmail } from "@/lib/jmap"; +import { getSession, getAccountId, getEmail, markAsRead } from "@/lib/jmap"; import { formatAddressList, formatFullDate } from "@/lib/format"; import { notFound } from "next/navigation"; import EmailBody from "@/components/EmailBody"; @@ -18,6 +18,11 @@ export default async function EmailPage({ params }: Props) { if (!email) return notFound(); + // Mark as read if not already seen — fire-and-forget, don't block render + if (!email.keywords?.["$seen"]) { + void markAsRead(session.apiUrl, accountId, id); + } + let body: string | null = null; let bodyType: "html" | "text" = "text"; diff --git a/src/lib/jmap.ts b/src/lib/jmap.ts index 31aefdf..7724f33 100644 --- a/src/lib/jmap.ts +++ b/src/lib/jmap.ts @@ -153,6 +153,23 @@ export async function getIdentities( return (result.list as Identity[]) ?? []; } +export async function markAsRead( + apiUrl: string, + accountId: string, + emailId: string +): Promise { + await jmapCall(apiUrl, [ + [ + "Email/set", + { + accountId, + update: { [emailId]: { "keywords/$seen": true } }, + }, + "0", + ], + ]); +} + export async function sendEmail( apiUrl: string, accountId: string,