macos: fix dock icon badge permission (#12133)

The previous version requested general notification permissions but
omitted the `.badge` option. Because the initial request was granted,
`settings.authorizationStatus` returns `.authorized`, leading the app to
believe it has full notification privileges when it actually lacks the
authority to update the dock icon badge.

Debug hint:
You can reset the notification settings by right-clicking on the app
name.
<img width="307" height="85" alt=""
src="https://github.com/user-attachments/assets/660cd332-eda6-45d6-8bfd-a6f9e28e21e8"
/>
This commit is contained in:
Mitchell Hashimoto
2026-04-06 07:31:36 -07:00
committed by GitHub

View File

@@ -673,6 +673,22 @@ class AppDelegate: NSObject,
syncDockBadge()
}
private func requestBadgeAuthorizationAndSet(_ center: UNUserNotificationCenter) {
center.requestAuthorization(options: [.badge]) { granted, error in
if let error = error {
Self.logger.warning("Error requesting badge authorization: \(error)")
return
}
// Permission granted, set the badge
if granted {
DispatchQueue.main.async {
self.setDockBadge()
}
}
}
}
private func syncDockBadge() {
let center = UNUserNotificationCenter.current()
center.getNotificationSettings { settings in
@@ -683,23 +699,16 @@ class AppDelegate: NSObject,
DispatchQueue.main.async {
self.setDockBadge()
}
} else if settings.badgeSetting == .notSupported {
// If badge setting is not supported, we may be in a sandbox that doesn't allow it.
// We can still attempt to set the badge and hope for the best, but we should also
// request authorization just in case it is a permissions issue.
self.requestBadgeAuthorizationAndSet(center)
}
case .notDetermined:
// Not determined yet, request authorization for badge
center.requestAuthorization(options: [.badge]) { granted, error in
if let error = error {
Self.logger.warning("Error requesting badge authorization: \(error)")
return
}
if granted {
// Permission granted, set the badge
DispatchQueue.main.async {
self.setDockBadge()
}
}
}
self.requestBadgeAuthorizationAndSet(center)
case .denied, .provisional, .ephemeral:
// In these known non-authorized states, do not attempt to set the badge.