/** * Unified Toast System * * This module provides a comprehensive toast system that solves styling issues * and provides a single, flexible toast component for all use cases. * * Features: * - Proper background styling (no transparency issues) * - Loading states with spinners * - Progress bars for downloads/updates * - Success/error states * - Customizable icons and content * - Auto-update notifications * * Usage Examples: * * Simple loading toast: * ``` * import { showToast } from "./custom-toast"; * showToast({ * type: "loading", * title: "Loading...", * description: "Please wait..." * }); * ``` * * Auto-update toast: * ``` * showAutoUpdateToast("Firefox", "125.0.1"); * ``` * * Download progress toast: * ``` * showToast({ * type: "download", * title: "Downloading Firefox 123.0", * progress: { percentage: 45, speed: "2.5", eta: "30s" } * }); * ``` * * Version update progress: * ``` * showToast({ * type: "version-update", * title: "Updating browser versions", * progress: { current: 3, total: 5, found: 12 } * }); * ``` */ import { LuCheckCheck, LuDownload, LuRefreshCw, LuRocket, LuTriangleAlert, } from "react-icons/lu"; interface BaseToastProps { id?: string; title: string; description?: string; duration?: number; } interface LoadingToastProps extends BaseToastProps { type: "loading"; } interface SuccessToastProps extends BaseToastProps { type: "success"; } interface ErrorToastProps extends BaseToastProps { type: "error"; } interface DownloadToastProps extends BaseToastProps { type: "download"; stage?: | "downloading" | "extracting" | "verifying" | "completed" | "downloading (twilight rolling release)"; progress?: { percentage: number; speed?: string; eta?: string; }; } interface VersionUpdateToastProps extends BaseToastProps { type: "version-update"; progress?: { current: number; total: number; found: number; current_browser?: string; }; } interface FetchingToastProps extends BaseToastProps { type: "fetching"; browserName?: string; } interface TwilightUpdateToastProps extends BaseToastProps { type: "twilight-update"; browserName?: string; hasUpdate?: boolean; } interface AppUpdateToastProps extends BaseToastProps { type: "app-update"; stage?: "downloading" | "extracting" | "installing" | "completed"; progress?: { percentage: number; speed?: string; eta?: string; }; } type ToastProps = | LoadingToastProps | SuccessToastProps | ErrorToastProps | DownloadToastProps | VersionUpdateToastProps | FetchingToastProps | TwilightUpdateToastProps | AppUpdateToastProps; function getToastIcon(type: ToastProps["type"], stage?: string) { switch (type) { case "success": return ; case "error": return ; case "download": if (stage === "completed") { return ( ); } return ; case "app-update": if (stage === "completed") { return ( ); } else if (stage === "downloading") { return ; } else if (stage === "installing") { return ( ); } return ( ); case "version-update": return ( ); case "fetching": return ( ); case "twilight-update": return ( ); case "loading": return (
); default: return (
); } } export function UnifiedToast(props: ToastProps) { const { title, description, type } = props; const stage = "stage" in props ? props.stage : undefined; const progress = "progress" in props ? props.progress : undefined; // Check if this is an auto-update toast const isAutoUpdate = title.includes("update started"); return (
{isAutoUpdate ? ( ) : ( getToastIcon(type, stage) )}

{title}

{/* Download progress */} {type === "download" && progress && "percentage" in progress && stage === "downloading" && (

{progress.percentage.toFixed(1)}% {progress.speed && ` • ${progress.speed} MB/s`} {progress.eta && ` • ${progress.eta} remaining`}

)} {/* App update progress */} {type === "app-update" && (
{/* Download progress with percentage */} {progress && "percentage" in progress && stage === "downloading" && ( <>

{progress.percentage.toFixed(1)}% {progress.speed && ` • ${progress.speed} MB/s`} {progress.eta && ` • ${progress.eta} remaining`}

)} {/* Progress indicator for other stages */} {(stage === "extracting" || stage === "installing" || stage === "completed") && (
)}
)} {/* Version update progress */} {type === "version-update" && progress && "current_browser" in progress && (

{progress.current_browser && ( <>Looking for updates for {progress.current_browser} )}

{progress.current}/{progress.total}
)} {/* Twilight update progress */} {type === "twilight-update" && (

{"hasUpdate" in props && props.hasUpdate ? "New twilight build available for download" : "Checking for twilight updates..."}

{props.browserName && (

{props.browserName} • Rolling Release

)}
)} {/* Description */} {description && (

{description}

)} {/* Stage-specific descriptions for downloads */} {type === "download" && !description && ( <> {stage === "extracting" && (

Extracting browser files...

)} {stage === "verifying" && (

Verifying browser files...

)} {stage === "downloading (twilight rolling release)" && (

Downloading rolling release build...

)} )} {/* Stage-specific descriptions for app updates */} {type === "app-update" && !description && ( <> {stage === "extracting" && (

Preparing update files...

)} {stage === "installing" && (

Installing new version...

)} {stage === "completed" && (

Update completed! Restarting application...

)} )}
); }