import SwiftUI
#if canImport(UIKit)
import UIKit
#endif
extension View {
/// Mounts the single app-wide error alert, driven by the shared presenter.
func errorAlert(_ presenter: ErrorPresenter) -> some View {
modifier(ErrorAlertModifier(presenter: presenter))
}
}
private struct ErrorAlertModifier: ViewModifier {
@Bindable var presenter: ErrorPresenter
func body(content: Content) -> some View {
content.alert(
presenter.current?.title ?? "",
isPresented: Binding(
get: { presenter.current != nil },
set: { if !$0 { presenter.dismiss() } }
),
presenting: presenter.current
) { err in
if err.recovery == .openSettings, let url = Self.settingsURL {
Button("Open Settings") { Self.open(url) }
Button("OK", role: .cancel) { presenter.dismiss() }
} else {
Button("OK", role: .cancel) { presenter.dismiss() }
}
} message: { err in
Text(err.message)
}
}
private static var settingsURL: URL? {
#if os(iOS)
return URL(string: UIApplication.openSettingsURLString)
#elseif os(macOS)
return URL(string: "x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone")
#else
return nil
#endif
}
private static func open(_ url: URL) {
#if os(iOS)
UIApplication.shared.open(url)
#elseif os(macOS)
NSWorkspace.shared.open(url)
#endif
}
}