import { useState, useEffect } from 'react' const TOAST_TTL = 7000 // ms before auto-dismiss; paused when detail is expanded export default function ToastStack({ toasts, onDismiss, onIgnoreUblock }) { if (!toasts.length) return null return (
{toasts.map(t => ( ))}
) } // For URLs: show hostname/…/tail (drops protocol + middle path, keeps domain + identifier). // For shorthands (yt:, x:, etc.): keep the tail since it's the whole identifier. // CSS text-overflow:ellipsis on .toast-locator handles any remaining overflow. function shortLocator(locator) { if (!locator) return null if (locator.length <= 52) return locator try { const { hostname, pathname, search } = new URL(locator) const segments = pathname.split('/').filter(Boolean) const tail = (segments[segments.length - 1] ?? '') + search const candidate = tail ? `${hostname}/\u2026/${tail}` : hostname return candidate.length <= 56 ? candidate : candidate.slice(0, 53) + '\u2026' } catch { return '\u2026' + locator.slice(-51) } } function Toast({ toast, onDismiss, onIgnoreUblock }) { const [expanded, setExpanded] = useState(false) const isWarning = toast.type === 'warning' const isSuccess = toast.type === 'success' // Auto-dismiss after TTL; paused while detail is expanded useEffect(() => { if (expanded) return const timer = setTimeout(() => onDismiss(toast.id), TOAST_TTL) return () => clearTimeout(timer) }, [expanded, toast.id, onDismiss]) const short = shortLocator(toast.locator) if (isSuccess) { return (
{toast.headline || 'Archived'} {short && {short}}
) } if (isWarning) { return (
{toast.headline || 'Archived with warnings'} {short && {short}}
{toast.text && ( )} {toast.locator && ( )}
{expanded && (

{toast.text || 'The page was captured but one or more browser extensions were unavailable (ad-blocking or cookie-consent). Check ARCHIVR_UBLOCK_EXT and ARCHIVR_COOKIE_EXT in your server config.'}

)}
) } return (
{toast.headline || 'Capture failed'} {short && {short}}
{toast.text && ( )}
{expanded && toast.text && (
{toast.text}
)}
) }