function Sidebar({ view, tagView, setView, tags, unread, total, status, onCreateTag }) {
const [newTag, setNewTag] = React.useState("");
const [tagBusy, setTagBusy] = React.useState(false);
const navBtn = (active, hasUnread) =>
"w-full text-left px-3 py-2 rounded-md text-sm mb-0.5 " +
(active
? "bg-accent-soft text-accent"
: hasUnread
? "text-ink font-semibold hover:bg-paper-line/50"
: "text-ink-muted hover:bg-paper-line/50 hover:text-ink");
const userTags = (tags || []).filter((t) => t !== "archive");
const label = (name, n) => (n > 0 ? name + " (" + n + ")" : name);
const submitTag = (e) => {
e.preventDefault();
const name = (newTag || "").trim();
if (!name || tagBusy) return;
setTagBusy(true);
onCreateTag(name)
.then(() => setNewTag(""))
.catch((err) => console.error(err))
.finally(() => setTagBusy(false));
};
return (
);
}
function Toolbar({ q, setQ, onSearch, selCount, onBulk, onMarkAll, view, tags, busy }) {
const n = selCount;
const btn =
"text-xs px-2.5 py-1 rounded border border-paper-line text-ink-muted hover:border-accent hover:text-accent disabled:opacity-30";
const userTags = (tags || []).filter((t) => t !== "archive");
return (
{view === "archive" ? (
) : (
)}
{n > 0 && userTags.length > 0 && (
)}
);
}
function MessageList({
items,
selected,
onSelect,
loading,
checked,
setChecked,
total,
selectAllPages,
setSelectAllPages,
}) {
const allIds = items.map((m) => m.id);
const pageOn = allIds.length > 0 && allIds.every((id) => checked.includes(id));
const multiPage = total > allIds.length && allIds.length > 0;
if (loading) return Loading…
;
if (!items.length) {
return No messages in this view.
;
}
return (
{items.map((m) => {
const active = selected === m.id;
const on = selectAllPages || checked.includes(m.id);
return (
{
e.stopPropagation();
setSelectAllPages(false);
setChecked(
e.target.checked ? checked.concat([m.id]) : checked.filter((x) => x !== m.id)
);
}}
/>
);
})}
);
}
function MessagePane({
msg,
msgTags,
attachments,
token,
onToggleUnread,
onArchive,
onUnarchive,
onDelete,
onReply,
archived,
busy,
}) {
const [reply, setReply] = React.useState("");
React.useEffect(() => {
setReply("");
}, [msg?.id]);
if (!msg) {
return (
Select a message
);
}
const html = decodeBodyHtml(msg.body_html) || "" + (msg.body_text || "") + "
";
const btn =
"text-xs px-2.5 py-1 rounded border border-paper-line text-ink-muted hover:border-accent hover:text-accent";
const chips = (msgTags || []).filter((t) => t !== "archive");
return (
{msg.subject}
From
{msg.from_addr}
To
{msg.to_addr}
{formatWhen(msg.created_at)}
{chips.length > 0 && (
{chips.map((t) => (
#{t}
))}
)}
{(attachments || []).length > 0 && (
)}
{archived ? (
) : (
)}
{msg.direction !== "out" && (
)}
);
}