diff --git a/src/app/(inbox)/email/[id]/error.tsx b/src/app/(inbox)/email/[id]/error.tsx new file mode 100644 index 0000000..53a2efe --- /dev/null +++ b/src/app/(inbox)/email/[id]/error.tsx @@ -0,0 +1,18 @@ +"use client"; + +export default function EmailError() { + return ( +
+
+
+

+ Unable to load this email +

+

+ There was a problem fetching this email from the server. Refresh to try again. +

+
+
+
+ ); +} diff --git a/src/app/(inbox)/layout.tsx b/src/app/(inbox)/layout.tsx index f97dd93..100d9bb 100644 --- a/src/app/(inbox)/layout.tsx +++ b/src/app/(inbox)/layout.tsx @@ -12,27 +12,57 @@ export default async function InboxLayout({ children: React.ReactNode; }) { const t = Date.now(); - const session = await getSession(); - const accountId = getAccountId(session); - const mailboxes = await getMailboxes(session.apiUrl, accountId); + + let session, accountId, mailboxes; + try { + session = await getSession(); + accountId = getAccountId(session); + mailboxes = await getMailboxes(session.apiUrl, accountId); + } catch (err) { + log.error({ err, duration_ms: Date.now() - t }, "layout.inbox.session_error"); + return ( +
+
+

+ Unable to connect to mail server +

+

+ Check your connection and refresh to try again. +

+
+
+ ); + } + const inbox = mailboxes.find((m) => m.role === "inbox"); const draftsMailbox = mailboxes.find((m) => m.role === "drafts"); const sentMailbox = mailboxes.find((m) => m.role === "sent"); const archiveMailbox = mailboxes.find((m) => m.role === "archive"); const trashMailbox = mailboxes.find((m) => m.role === "trash"); - const [inbox_emails, drafts, pinned, sentResult] = await Promise.all([ - inbox - ? listInboxEmails(session.apiUrl, accountId, inbox.id) - : Promise.resolve({ unreads: [], unreadTotal: 0, reads: [], readTotal: 0 }), - draftsMailbox - ? listDrafts(session.apiUrl, accountId, draftsMailbox.id) - : Promise.resolve([]), - listPinnedEmails(session.apiUrl, accountId), - sentMailbox - ? listSentEmails(session.apiUrl, accountId, sentMailbox.id) - : Promise.resolve({ emails: [], total: 0 }), - ]); + let inbox_emails = { unreads: [] as Awaited>["unreads"], unreadTotal: 0, reads: [] as Awaited>["reads"], readTotal: 0 }; + let drafts: Awaited> = []; + let pinned: Awaited> = []; + let sentResult: Awaited> = { emails: [], total: 0 }; + + try { + [inbox_emails, drafts, pinned, sentResult] = await Promise.all([ + inbox + ? listInboxEmails(session.apiUrl, accountId, inbox.id) + : Promise.resolve({ unreads: [], unreadTotal: 0, reads: [], readTotal: 0 }), + draftsMailbox + ? listDrafts(session.apiUrl, accountId, draftsMailbox.id) + : Promise.resolve([]), + listPinnedEmails(session.apiUrl, accountId), + sentMailbox + ? listSentEmails(session.apiUrl, accountId, sentMailbox.id) + : Promise.resolve({ emails: [], total: 0 }), + ]); + } catch (err) { + log.error({ err, duration_ms: Date.now() - t }, "layout.inbox.fetch_error"); + // Fall through with empty data — the panel will render with a refresh prompt + } + const { unreads, unreadTotal, reads, readTotal } = inbox_emails; log.info({ diff --git a/src/app/(inbox)/thread/[threadId]/error.tsx b/src/app/(inbox)/thread/[threadId]/error.tsx new file mode 100644 index 0000000..f6725aa --- /dev/null +++ b/src/app/(inbox)/thread/[threadId]/error.tsx @@ -0,0 +1,18 @@ +"use client"; + +export default function ThreadError() { + return ( +
+
+
+

+ Unable to load this thread +

+

+ There was a problem fetching this email from the server. Refresh to try again. +

+
+
+
+ ); +}