fix: explain notification permission state instead of failing silently
requestAuthorization only shows the system prompt once ever; when permission is already denied it silently returns false and the checkbox just snapped off with no explanation. toggleNotify now checks the authorization status first: already-authorized enables directly, not-determined triggers the system prompt (errors surfaced in an alert), and denied shows an alert with an Open System Settings button pointing at the Notifications pane. Also adds a UNUserNotificationCenterDelegate so banners are shown even while BrewBar is the active app — otherwise macOS suppresses them, which reads as "notifications don't work" right after enabling. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
25e4476317
commit
fe469d9157
|
|
@ -47,6 +47,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
|
||||
func applicationDidFinishLaunching(_: Notification) {
|
||||
Settings.registerDefaults()
|
||||
UNUserNotificationCenter.current().delegate = self
|
||||
|
||||
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
|
||||
statusItem.button?.imagePosition = .imageLeft // icon stays visible next to the count
|
||||
|
|
@ -437,3 +438,14 @@ class AppDelegate: NSObject, NSApplicationDelegate {
|
|||
logWindow?.update(text: logBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
extension AppDelegate: UNUserNotificationCenterDelegate {
|
||||
/// Without this, macOS suppresses banners while BrewBar is the active
|
||||
/// app (e.g. right after toggling the setting with the window open).
|
||||
func userNotificationCenter(_: UNUserNotificationCenter,
|
||||
willPresent _: UNNotification,
|
||||
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
|
||||
{
|
||||
completionHandler([.banner])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -246,15 +246,62 @@ class SettingsWindowController: NSWindowController {
|
|||
return
|
||||
}
|
||||
|
||||
UNUserNotificationCenter.current().requestAuthorization(options: [.alert]) { granted, _ in
|
||||
// requestAuthorization only shows the system prompt the first time
|
||||
// ever; if permission was denied before, it silently returns false.
|
||||
// Check the status first so the user learns what actually happened.
|
||||
let center = UNUserNotificationCenter.current()
|
||||
center.getNotificationSettings { notificationSettings in
|
||||
// callback arrives on a background queue; UI needs main
|
||||
DispatchQueue.main.async {
|
||||
Settings.notifyOnNewUpdates = granted
|
||||
sender.state = granted ? .on : .off
|
||||
switch notificationSettings.authorizationStatus {
|
||||
case .authorized, .provisional:
|
||||
Settings.notifyOnNewUpdates = true
|
||||
|
||||
case .notDetermined:
|
||||
center.requestAuthorization(options: [.alert, .sound]) { granted, error in
|
||||
DispatchQueue.main.async {
|
||||
Settings.notifyOnNewUpdates = granted
|
||||
sender.state = granted ? .on : .off
|
||||
if let error {
|
||||
self.showNotificationProblem(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case .denied:
|
||||
sender.state = .off
|
||||
self.showNotificationsDenied()
|
||||
|
||||
@unknown default:
|
||||
sender.state = .off
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func showNotificationsDenied() {
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .warning
|
||||
alert.messageText = "Notifications are disabled for BrewBar"
|
||||
alert.informativeText = "macOS has notifications turned off for BrewBar. Enable them in System Settings > Notifications > BrewBar, then flip this switch again."
|
||||
alert.addButton(withTitle: "Open System Settings")
|
||||
alert.addButton(withTitle: "Cancel")
|
||||
|
||||
if alert.runModal() == .alertFirstButtonReturn,
|
||||
let url = URL(string: "x-apple.systempreferences:com.apple.Notifications-Settings.extension")
|
||||
{
|
||||
NSWorkspace.shared.open(url)
|
||||
}
|
||||
}
|
||||
|
||||
func showNotificationProblem(_ message: String) {
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .warning
|
||||
alert.messageText = "Could not enable notifications"
|
||||
alert.informativeText = message
|
||||
alert.runModal()
|
||||
}
|
||||
|
||||
@objc func toggleShowCount(_ sender: NSButton) {
|
||||
Settings.showCountInMenuBar = sender.state == .on
|
||||
appDelegate?.updateMenuBarCount() // reflect immediately, no refetch needed
|
||||
|
|
|
|||
Loading…
Reference in a new issue