Skip to content

Commit 412f19e

Browse files
committed
fix(ui): toasts not showing after soft crash
1 parent 4a27a88 commit 412f19e

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

Bitkit/Managers/ToastWindowManager.swift

Lines changed: 49 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Bitkit/Views/Settings/DevSettingsView.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@ struct DevSettingsView: View {
102102
SettingsListLabel(title: "Test Push Notification", rightIcon: nil)
103103
}
104104

105+
Button {
106+
fatalError("Simulate Crash")
107+
} label: {
108+
SettingsListLabel(title: "Simulate Crash", rightIcon: nil)
109+
}
110+
105111
Button {
106112
Task {
107113
do {

0 commit comments

Comments
 (0)