2026-07-17 23:20:34 +02:00
|
|
|
import { useT } from "../../i18n";
|
2026-07-18 15:27:09 +02:00
|
|
|
import type { DraftOut, RemoteDraftOut } from "../../lib/types";
|
2026-07-17 23:20:34 +02:00
|
|
|
|
|
|
|
|
function timeLabel(iso: string): string {
|
|
|
|
|
const d = new Date(iso);
|
|
|
|
|
const now = new Date();
|
|
|
|
|
if (d.toDateString() === now.toDateString())
|
|
|
|
|
return d.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
|
|
|
return d.toLocaleDateString([], { month: "short", day: "numeric" });
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-18 15:27:09 +02:00
|
|
|
function DraftRow({
|
|
|
|
|
recipients,
|
|
|
|
|
subject,
|
|
|
|
|
preview,
|
|
|
|
|
time,
|
|
|
|
|
badge,
|
|
|
|
|
onClick,
|
|
|
|
|
}: {
|
|
|
|
|
recipients: string;
|
|
|
|
|
subject: string;
|
|
|
|
|
preview: string;
|
|
|
|
|
time: string;
|
|
|
|
|
badge?: string;
|
|
|
|
|
onClick: () => void;
|
|
|
|
|
}) {
|
|
|
|
|
return (
|
|
|
|
|
<button
|
|
|
|
|
onClick={onClick}
|
|
|
|
|
className="flex w-full flex-col gap-1 border-b border-app-border px-6 py-2.5 text-left hover:bg-app-hover"
|
|
|
|
|
>
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
|
|
<span className="flex-1 truncate text-sm text-app-fg">{recipients}</span>
|
|
|
|
|
{badge && (
|
|
|
|
|
<span className="shrink-0 rounded bg-app-hover px-1.5 text-[10px] text-app-muted">
|
|
|
|
|
{badge}
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
|
|
|
|
<span className="shrink-0 text-[11px] text-app-faint">{time}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="truncate text-[13px] font-medium text-app-fg">{subject}</div>
|
|
|
|
|
{preview && <div className="truncate text-xs text-app-faint">{preview}</div>}
|
|
|
|
|
</button>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The Drafts folder lists local drafts (the `drafts` table) plus drafts found in
|
|
|
|
|
// the account's IMAP Drafts folder that were created on another client.
|
2026-07-17 23:20:34 +02:00
|
|
|
export function DraftsList({
|
|
|
|
|
drafts,
|
2026-07-18 15:27:09 +02:00
|
|
|
remoteDrafts,
|
2026-07-17 23:20:34 +02:00
|
|
|
onOpen,
|
2026-07-18 15:27:09 +02:00
|
|
|
onOpenRemote,
|
2026-07-17 23:20:34 +02:00
|
|
|
}: {
|
|
|
|
|
drafts: DraftOut[];
|
2026-07-18 15:27:09 +02:00
|
|
|
remoteDrafts: RemoteDraftOut[];
|
2026-07-17 23:20:34 +02:00
|
|
|
onOpen: (draft: DraftOut) => void;
|
2026-07-18 15:27:09 +02:00
|
|
|
onOpenRemote: (draft: RemoteDraftOut) => void;
|
2026-07-17 23:20:34 +02:00
|
|
|
}) {
|
|
|
|
|
const t = useT();
|
2026-07-18 15:27:09 +02:00
|
|
|
if (drafts.length === 0 && remoteDrafts.length === 0) {
|
2026-07-17 23:20:34 +02:00
|
|
|
return <div className="p-6 text-sm text-app-faint">{t("compose.noDrafts")}</div>;
|
|
|
|
|
}
|
2026-07-18 15:27:09 +02:00
|
|
|
|
|
|
|
|
// Merge local + remote drafts into one list sorted by date (newest first).
|
|
|
|
|
type Row = {
|
|
|
|
|
key: string;
|
|
|
|
|
date: string;
|
|
|
|
|
recipients: string;
|
|
|
|
|
subject: string;
|
|
|
|
|
preview: string;
|
|
|
|
|
badge?: string;
|
|
|
|
|
onClick: () => void;
|
|
|
|
|
};
|
|
|
|
|
const rows: Row[] = [
|
|
|
|
|
...drafts.map((d) => ({
|
|
|
|
|
key: `l-${d.id}`,
|
|
|
|
|
date: d.updated_at,
|
|
|
|
|
recipients: d.payload.to.join(", ") || t("compose.noRecipient"),
|
|
|
|
|
subject: d.payload.subject || t("compose.noSubject"),
|
|
|
|
|
preview: d.payload.text.trim(),
|
|
|
|
|
onClick: () => onOpen(d),
|
|
|
|
|
})),
|
|
|
|
|
...remoteDrafts.map((d) => ({
|
|
|
|
|
key: `r-${d.message_id}`,
|
|
|
|
|
date: d.updated_at,
|
|
|
|
|
recipients: d.to.join(", ") || t("compose.noRecipient"),
|
|
|
|
|
subject: d.subject || t("compose.noSubject"),
|
|
|
|
|
preview: d.snippet.trim(),
|
|
|
|
|
badge: t("compose.otherClient"),
|
|
|
|
|
onClick: () => onOpenRemote(d),
|
|
|
|
|
})),
|
|
|
|
|
].sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime());
|
|
|
|
|
|
2026-07-17 23:20:34 +02:00
|
|
|
return (
|
|
|
|
|
<div className="h-full overflow-y-auto" data-testid="drafts-list">
|
2026-07-18 15:27:09 +02:00
|
|
|
{rows.map((row) => (
|
|
|
|
|
<DraftRow
|
|
|
|
|
key={row.key}
|
|
|
|
|
recipients={row.recipients}
|
|
|
|
|
subject={row.subject}
|
|
|
|
|
preview={row.preview}
|
|
|
|
|
time={timeLabel(row.date)}
|
|
|
|
|
badge={row.badge}
|
|
|
|
|
onClick={row.onClick}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
2026-07-17 23:20:34 +02:00
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|