diff --git a/src/app/(inbox)/email/[id]/page.tsx b/src/app/(inbox)/email/[id]/page.tsx index 3bbb338..bf85706 100644 --- a/src/app/(inbox)/email/[id]/page.tsx +++ b/src/app/(inbox)/email/[id]/page.tsx @@ -3,7 +3,6 @@ import { getSession, getAccountId, getEmail } from "@/lib/jmap"; import { formatAddressList, formatFullDate } from "@/lib/format"; import { notFound } from "next/navigation"; import EmailBody from "@/components/EmailBody"; -import MarkAsRead from "@/components/MarkAsRead"; export const dynamic = "force-dynamic"; @@ -43,7 +42,6 @@ export default async function EmailPage({ params }: Props) { return (
-
{/* Subject */}

diff --git a/src/components/EmailListPanel.tsx b/src/components/EmailListPanel.tsx index fbe9348..6a3112c 100644 --- a/src/components/EmailListPanel.tsx +++ b/src/components/EmailListPanel.tsx @@ -1,9 +1,11 @@ "use client"; import Link from "next/link"; +import { useEffect, useState } from "react"; import { usePathname } from "next/navigation"; import { Email } from "@/lib/types"; import { formatAddressList, formatDate } from "@/lib/format"; +import { markEmailAsRead } from "@/app/(inbox)/email/[id]/actions"; interface Props { emails: Email[]; @@ -16,6 +18,21 @@ export default function EmailListPanel({ emails, unreadCount = 0 }: Props) { ? pathname.slice("/email/".length) : undefined; + // Track emails marked read this session so the list stays accurate + // even though the layout's server data is only fetched once. + const [clientReadIds, setClientReadIds] = useState(new Set()); + + useEffect(() => { + if (!selectedId) return; + const email = emails.find((e) => e.id === selectedId); + if (!email) return; + const alreadyRead = !!email.keywords?.["$seen"] || clientReadIds.has(selectedId); + if (!alreadyRead) { + setClientReadIds((prev) => new Set([...prev, selectedId])); + markEmailAsRead(selectedId); + } + }, [selectedId]); // eslint-disable-line react-hooks/exhaustive-deps + return (
{/* Header */} @@ -43,7 +60,10 @@ export default function EmailListPanel({ emails, unreadCount = 0 }: Props) { )} {emails.map((email) => { const isSelected = email.id === selectedId; - const isUnread = email.id !== selectedId && !email.keywords?.["$seen"]; + const isUnread = + !email.keywords?.["$seen"] && + !clientReadIds.has(email.id) && + email.id !== selectedId; return ( { - if (!alreadyRead) { - markEmailAsRead(emailId); - } - }, [emailId, alreadyRead]); - - return null; -}