"use client"; import React from "react"; import { formatDate } from "@/lib/utils"; import { Email, ThreadGroup } from "@/lib/jmap/types"; import { cn } from "@/lib/utils"; import { Avatar } from "@/components/ui/avatar"; import { Paperclip, Star, Circle, ChevronRight, ChevronDown, Loader2 } from "lucide-react"; import { useSettingsStore } from "@/stores/settings-store"; import { useUIStore } from "@/stores/ui-store"; import { getThreadColorTag } from "@/lib/thread-utils"; import { ThreadEmailItem } from "./thread-email-item"; import { useTranslations } from "next-intl"; interface ThreadListItemProps { thread: ThreadGroup; isExpanded: boolean; selectedEmailId?: string; isLoading?: boolean; expandedEmails?: Email[]; onToggleExpand: () => void; onEmailSelect: (email: Email) => void; onContextMenu?: (e: React.MouseEvent, email: Email) => void; onOpenConversation?: (thread: ThreadGroup) => void; } const colorTags = { red: "bg-red-50 dark:bg-red-950/30", orange: "bg-orange-50 dark:bg-orange-950/30", yellow: "bg-yellow-50 dark:bg-yellow-950/30", green: "bg-green-50 dark:bg-green-950/30", blue: "bg-blue-50 dark:bg-blue-950/30", purple: "bg-purple-50 dark:bg-purple-950/30", pink: "bg-pink-50 dark:bg-pink-950/30", } as const; interface SingleEmailItemProps { email: Email; selected: boolean; onClick: () => void; onContextMenu?: (e: React.MouseEvent, email: Email) => void; showPreview: boolean; colorTag: string | null; } const SingleEmailItem = React.forwardRef( function SingleEmailItem({ email, selected, onClick, onContextMenu, showPreview, colorTag }, ref) { const isUnread = !email.keywords?.$seen; const isStarred = email.keywords?.$flagged; const sender = email.from?.[0]; const handleContextMenu = (e: React.MouseEvent) => { onContextMenu?.(e, email); }; return (
{isUnread && (
)}
{sender?.name || sender?.email || "Unknown"}
{isStarred && ( )} {email.hasAttachment && ( )}
{formatDate(email.receivedAt)}
{email.subject || "(no subject)"}
{showPreview && (

{email.preview || "No preview available"}

)}
); } ); export const ThreadListItem = React.forwardRef( function ThreadListItem({ thread, isExpanded, selectedEmailId, isLoading = false, expandedEmails, onToggleExpand, onEmailSelect, onContextMenu, onOpenConversation, }, ref) { const t = useTranslations('threads'); const showPreview = useSettingsStore((state) => state.showPreview); const isMobile = useUIStore((state) => state.isMobile); const { latestEmail, participantNames, hasUnread, hasStarred, hasAttachment, emailCount } = thread; const threadColor = getThreadColorTag(thread.emails); const colorTag = threadColor ? colorTags[threadColor as keyof typeof colorTags] : null; const isSelected = selectedEmailId === latestEmail.id || thread.emails.some(e => e.id === selectedEmailId); if (emailCount === 1) { return ( onEmailSelect(latestEmail)} onContextMenu={onContextMenu} showPreview={showPreview} colorTag={colorTag} /> ); } const emailsToShow = expandedEmails || thread.emails; const handleHeaderClick = (e: React.MouseEvent) => { if (isMobile && onOpenConversation) { onOpenConversation(thread); return; } const target = e.target as HTMLElement; if (target.closest('[data-expand-toggle]')) { onToggleExpand(); } else { if (!isExpanded) { onToggleExpand(); } onEmailSelect(latestEmail); } }; const handleContextMenu = (e: React.MouseEvent) => { onContextMenu?.(e, latestEmail); }; return (
{!isMobile && ( )} {hasUnread && (
)}
{participantNames.join(", ")} {emailCount}
{hasStarred && ( )} {hasAttachment && ( )}
{formatDate(latestEmail.receivedAt)}
{latestEmail.subject || "(no subject)"}
{showPreview && (

{latestEmail.preview || "No preview available"}

)}
{isExpanded && !isMobile && (
{isLoading ? (
{t('loading')}
) : ( emailsToShow.map((email, index) => ( onEmailSelect(email)} onContextMenu={onContextMenu} /> )) )}
)}
); } );