@@ -35,13 +35,22 @@ class ToastWindowManager: ObservableObject {
3535 }
3636
3737 func showToast( _ toast: Toast ) {
38+ // Ensure window is set up before showing toast
39+ ensureWindowExists ( )
40+
41+ // If window still doesn't exist after trying to set it up, log and return
42+ guard let window = toastWindow else {
43+ Logger . error ( " ToastWindowManager: Cannot show toast - window not available " )
44+ return
45+ }
46+
3847 // Dismiss any existing toast first
3948 cancelAutoHide ( )
40- toastWindow ? . hasToast = false
41- toastWindow ? . toastFrame = . zero
49+ window . hasToast = false
50+ window . toastFrame = . zero
4251
4352 // Update window's toast state for hit testing
44- toastWindow ? . hasToast = true
53+ window . hasToast = true
4554
4655 // Show the toast with animation
4756 withAnimation ( . easeInOut( duration: 0.4 ) ) {
@@ -68,7 +77,7 @@ class ToastWindowManager: ObservableObject {
6877 }
6978
7079 func pauseAutoHide( ) {
71- guard autoHideStartTime != nil else { return } // Already paused or no auto-hide
80+ guard autoHideStartTime != nil else { return } // No active auto-hide to pause
7281 cancelAutoHide ( )
7382
7483 // Calculate remaining time
@@ -124,11 +133,32 @@ class ToastWindowManager: ObservableObject {
124133 autoHideDuration = 0
125134 }
126135
136+ private func ensureWindowExists( ) {
137+ // Check if window already exists and is still valid
138+ if let existingWindow = toastWindow,
139+ existingWindow. windowScene != nil ,
140+ !existingWindow. isHidden
141+ {
142+ return
143+ }
144+
145+ // Window doesn't exist or is invalid, try to set it up
146+ setupToastWindow ( )
147+ }
148+
127149 private func setupToastWindow( ) {
128- guard let windowScene = UIApplication . shared. connectedScenes. first as? UIWindowScene else {
150+ // Try to find an active window scene
151+ guard let windowScene = findActiveWindowScene ( ) else {
152+ Logger . warn ( " ToastWindowManager: No active window scene available " )
129153 return
130154 }
131155
156+ // Clean up old window if it exists
157+ if let oldWindow = toastWindow {
158+ oldWindow. isHidden = true
159+ oldWindow. rootViewController = nil
160+ }
161+
132162 let window = PassThroughWindow ( windowScene: windowScene)
133163 window. windowLevel = UIWindow . Level. alert + 1 // Above alerts and sheets
134164 window. backgroundColor = . clear
@@ -143,6 +173,20 @@ class ToastWindowManager: ObservableObject {
143173 toastWindow = window
144174 toastHostingController = hostingController
145175 }
176+
177+ private func findActiveWindowScene( ) -> UIWindowScene ? {
178+ // Try to find an active window scene from connected scenes
179+ for scene in UIApplication . shared. connectedScenes {
180+ if let windowScene = scene as? UIWindowScene ,
181+ windowScene. activationState == . foregroundActive || windowScene. activationState == . foregroundInactive
182+ {
183+ return windowScene
184+ }
185+ }
186+
187+ // Fallback to any window scene if no active one found
188+ return UIApplication . shared. connectedScenes. first as? UIWindowScene
189+ }
146190}
147191
148192// Custom window that only intercepts touches on interactive elements
0 commit comments