toast.ts RawHistoryFolder
1/**
2 * Toast System Module
3 *
4 * Provides toast notification functionality using Svelte 5 components
5 * with proper DOM ready checking and theme support.
6 */
7
8import { mount, flushSync } from "svelte";
9import ToastContainer from "$components/toast/ToastContainer.svelte";
10import { ensureShadowMount } from "./shadowHost";
11
12export interface ToastConfig {
13 theme?: "light" | "dark";
14}
15
16// Type definitions for window globals
17declare global {
18 interface Window {
19 __dumber_toast_loaded?: boolean;
20 __dumber_initial_theme?: string;
21 }
22}
23
24let toastInitialized = false;
25
26// Apply theme based on current system/GTK preference
27function updateTheme(isDark: boolean): void {
28 if (isDark) {
29 document.documentElement.classList.add("dark");
30 } else {
31 document.documentElement.classList.remove("dark");
32 }
33}
34
35export async function initializeToast(config?: ToastConfig): Promise<void> {
36 if (toastInitialized || window.__dumber_toast_loaded) {
37 // Verify functions still exist - if not, reinitialize
38 if (
39 typeof window.__dumber_showToast === "function" &&
40 typeof window.__dumber_showZoomToast === "function"
41 ) {
42 console.log("✅ Toast system already initialized and functional");
43 return;
44 }
45 // If functions are missing, reinitialize
46 console.log("⚠️ Toast functions missing, reinitializing...");
47 toastInitialized = false;
48 window.__dumber_toast_loaded = false;
49 }
50
51 console.log("🚀 Initializing Svelte toast system at:", document.readyState);
52 console.log(
53 "📊 DOM state check - head:",
54 !!document.head,
55 "body:",
56 !!document.body,
57 );
58 window.__dumber_toast_loaded = true;
59
60 // Ensure DOM is ready
61 if (document.readyState === "loading") {
62 return new Promise((resolve) => {
63 document.addEventListener("DOMContentLoaded", async () => {
64 await initializeToast(config);
65 resolve();
66 });
67 });
68 }
69
70 if (!document.head || !document.body) {
71 console.warn(
72 "❌ DOM structure not ready, deferring toast initialization. Retrying...",
73 );
74 window.__dumber_toast_loaded = false; // Reset the flag so we can try again
75 return new Promise((resolve) => {
76 const checkDOM = () => {
77 if (document.head && document.body) {
78 console.log("✅ DOM structure now ready, initializing toast system");
79 initializeToast(config).then(() => resolve());
80 } else {
81 console.log("⏳ DOM still not ready, retrying in 50ms...");
82 setTimeout(checkDOM, 50);
83 }
84 };
85 setTimeout(checkDOM, 100);
86 });
87 }
88
89 try {
90 // Use the global Shadow DOM host for isolation
91 const rootElement = ensureShadowMount("dumber-toast");
92
93 // Initialize theme
94 const initialTheme = config?.theme || window.__dumber_initial_theme;
95 if (initialTheme !== undefined) {
96 updateTheme(initialTheme === "dark");
97 }
98
99 // Mount the Svelte toast container - this exposes all toast functions to window
100 mount(ToastContainer, {
101 target: rootElement as unknown as Element,
102 });
103
104 // Force immediate effect execution to ensure component functions are exposed
105 flushSync();
106
107 toastInitialized = true;
108 console.log("✅ Toast system initialized - functions exposed by ToastContainer");
109 } catch (error) {
110 console.error("❌ Failed to initialize toast system:", error);
111 throw error;
112 }
113}