"use client"; import { useTranslations } from "next-intl"; import { Email, Mailbox } from "@/lib/jmap/types"; import { ContextMenu, ContextMenuItem, ContextMenuSeparator, ContextMenuSubMenu, ContextMenuHeader, } from "@/components/ui/context-menu"; import { Reply, ReplyAll, Forward, Mail, MailOpen, Star, Trash2, Archive, FolderInput, Palette, X, Inbox, Send, File, Folder, } from "lucide-react"; import { cn } from "@/lib/utils"; interface Position { x: number; y: number; } interface EmailContextMenuProps { email: Email; position: Position; isOpen: boolean; onClose: () => void; menuRef: React.RefObject; mailboxes: Mailbox[]; selectedMailbox: string; isMultiSelect?: boolean; selectedCount?: number; // Single email actions onReply?: () => void; onReplyAll?: () => void; onForward?: () => void; onMarkAsRead?: (read: boolean) => void; onToggleStar?: () => void; onDelete?: () => void; onArchive?: () => void; onSetColorTag?: (color: string | null) => void; onMoveToMailbox?: (mailboxId: string) => void; // Batch actions onBatchMarkAsRead?: (read: boolean) => void; onBatchDelete?: () => void; onBatchMoveToMailbox?: (mailboxId: string) => void; } // Color options for email tags const colorOptions = [ { name: "Red", value: "red", color: "bg-red-500" }, { name: "Orange", value: "orange", color: "bg-orange-500" }, { name: "Yellow", value: "yellow", color: "bg-yellow-500" }, { name: "Green", value: "green", color: "bg-green-500" }, { name: "Blue", value: "blue", color: "bg-blue-500" }, { name: "Purple", value: "purple", color: "bg-purple-500" }, { name: "Pink", value: "pink", color: "bg-pink-500" }, ]; // Get mailbox icon based on role const getMailboxIcon = (role?: string) => { switch (role) { case "inbox": return Inbox; case "sent": return Send; case "drafts": return File; case "trash": return Trash2; case "archive": return Archive; default: return Folder; } }; // Get current color from email keywords const getCurrentColor = (keywords: Record | undefined) => { if (!keywords) return null; for (const key of Object.keys(keywords)) { if (key.startsWith("$color:") && keywords[key] === true) { return key.replace("$color:", ""); } } return null; }; export function EmailContextMenu({ email, position, isOpen, onClose, menuRef, mailboxes, selectedMailbox, isMultiSelect = false, selectedCount = 1, onReply, onReplyAll, onForward, onMarkAsRead, onToggleStar, onDelete, onArchive, onSetColorTag, onMoveToMailbox, onBatchMarkAsRead, onBatchDelete, onBatchMoveToMailbox, }: EmailContextMenuProps) { const t = useTranslations("context_menu"); const isUnread = !email.keywords?.$seen; const isStarred = email.keywords?.$flagged; const currentColor = getCurrentColor(email.keywords); const showBatchActions = isMultiSelect && selectedCount > 1; // Filter mailboxes for move-to submenu (exclude current, drafts, virtual nodes) const moveTargets = mailboxes.filter( (m) => m.id !== selectedMailbox && m.role !== "drafts" && !m.id.startsWith("shared-") && m.myRights?.mayAddItems ); const handleAction = (action: () => void) => { action(); onClose(); }; return ( {/* Batch header */} {showBatchActions && ( {t("items_selected", { count: selectedCount })} )} {/* Single email actions - Reply, Reply All, Forward */} {!showBatchActions && ( <> handleAction(onReply!)} disabled={!onReply} /> handleAction(onReplyAll!)} disabled={!onReplyAll} /> handleAction(onForward!)} disabled={!onForward} /> )} {/* Mark as read/unread */} handleAction(() => showBatchActions ? onBatchMarkAsRead?.(isUnread) : onMarkAsRead?.(isUnread) ) } /> {/* Star/Unstar - only for single email */} {!showBatchActions && ( handleAction(onToggleStar!)} disabled={!onToggleStar} /> )} {/* Move to submenu */} {moveTargets.length > 0 && ( {moveTargets.map((mailbox) => { const Icon = getMailboxIcon(mailbox.role); return ( handleAction(() => showBatchActions ? onBatchMoveToMailbox?.(mailbox.id) : onMoveToMailbox?.(mailbox.id) ) } /> ); })} )} {/* Archive */} handleAction(onArchive!)} disabled={!onArchive} /> {/* Set color submenu - only for single email */} {!showBatchActions && (
{colorOptions.map((option) => (
{currentColor && ( <> handleAction(() => onSetColorTag?.(null))} /> )}
)} {/* Delete */} handleAction(showBatchActions ? onBatchDelete! : onDelete!) } disabled={showBatchActions ? !onBatchDelete : !onDelete} destructive />
); }