import { ActionIcon, Box, Button, Group, Paper, Portal, ScrollArea, Stack, Text, Tooltip } from "@mantine/core"; import { IconBell, IconX } from "@tabler/icons-react"; import { notificationDismissLabel, notificationOpenLabel, notificationTitle } from "../../state.js"; import { formatExactTime, formatRelativeTime } from "../../time.js"; import type { NotificationSnapshot, Task } from "../types"; import { StatusBadge } from "./StatusBadge"; export function NotificationCenter({ notifications, announcements = notifications, onClear, onDismiss, onOpen, tasks, withinPortal = true, }: { announcements?: NotificationSnapshot[]; notifications: NotificationSnapshot[]; onClear: () => void; onDismiss: (notification: NotificationSnapshot) => void; onOpen: (notification: NotificationSnapshot) => void; tasks: Task[]; withinPortal?: boolean; }) { if (notifications.length === 0) return null; const content = ( <> Updates {notifications.map((notification) => { const available = tasks.some((task) => task.id === notification.taskId); const descriptionId = `notification-${Math.abs(hash(notification.id))}`; const summaryId = `${descriptionId}-summary`; const metadataId = `${descriptionId}-metadata`; return ( onDismiss(notification)} size="compact-sm" variant="subtle" > ); })} {announcements.map(notificationAnnouncement).join(" ")} ); return withinPortal ? {content} : content; } function notificationAnnouncement(notification: NotificationSnapshot) { return [ notificationTitle(notification), notification.title, notification.summary, notification.turnRef ? `Turn ref ${notification.turnRef}` : null, formatRelativeTime(notification.timestamp), ].filter(Boolean).map((part) => String(part).replace(/[.\s]+$/, "")).join(". ") + "."; } function hash(value: string) { let result = 0; for (const character of value) result = ((result << 5) - result + character.charCodeAt(0)) | 0; return result; }