From edfb564bab8bed586a5e2cdf0b3af8029afb26c3 Mon Sep 17 00:00:00 2001 From: Serhiy Mytrovtsiy Date: Sun, 23 Jan 2022 00:06:49 +0100 Subject: [PATCH] feat: moved from NSUserNotification to the User Notification --- Kit/helpers.swift | 36 +++++++++++++++++------ Modules/Battery/main.swift | 58 +++++++++++++++++++++++--------------- Stats/AppDelegate.swift | 22 +++++++++++---- Stats/helpers.swift | 51 +++++++++++++++++++++------------ 4 files changed, 114 insertions(+), 53 deletions(-) diff --git a/Kit/helpers.swift b/Kit/helpers.swift index 38f6201b..bf17819e 100644 --- a/Kit/helpers.swift +++ b/Kit/helpers.swift @@ -12,6 +12,7 @@ import Cocoa import ServiceManagement +import UserNotifications public struct LaunchAtLogin { private static let id = "\(Bundle.main.bundleIdentifier!).LaunchAtLogin" @@ -477,23 +478,42 @@ public func isNewestVersion(currentVersion: String, latestVersion: String) -> Bo return false } -public func showNotification(title: String, subtitle: String? = nil, text: String? = nil, id: String = UUID().uuidString, icon: NSImage? = nil) -> NSUserNotification { +@available(macOS 10.14, *) +public func showNotification(title: String, subtitle: String? = nil, userInfo: [AnyHashable: Any] = [:], delegate: UNUserNotificationCenterDelegate? = nil) { + let id = UUID().uuidString + + let content = UNMutableNotificationContent() + content.title = title + if let value = subtitle { + content.subtitle = value + } + content.userInfo = userInfo + content.sound = UNNotificationSound.default + + let request = UNNotificationRequest(identifier: id, content: content, trigger: nil) + let center = UNUserNotificationCenter.current() + center.delegate = delegate + + center.requestAuthorization(options: [.alert, .sound]) { _, _ in } + center.add(request) { (error: Error?) in + if let err = error { + print(err) + } + } +} + +public func showNSNotification(title: String, subtitle: String? = nil, body: String? = nil, userInfo: [AnyHashable: Any] = [:]) { let notification = NSUserNotification() + let id = UUID().uuidString notification.identifier = id notification.title = title notification.subtitle = subtitle - notification.informativeText = text + notification.informativeText = body notification.soundName = NSUserNotificationDefaultSoundName notification.hasActionButton = false - if icon != nil { - notification.setValue(icon, forKey: "_identityImage") - } - NSUserNotificationCenter.default.deliver(notification) - - return notification } public struct TopProcess { diff --git a/Modules/Battery/main.swift b/Modules/Battery/main.swift index 4b84d027..088f6599 100644 --- a/Modules/Battery/main.swift +++ b/Modules/Battery/main.swift @@ -48,8 +48,8 @@ public class Battery: Module { private let popupView: Popup private var settingsView: Settings - private var lowNotification: NSUserNotification? = nil - private var highNotification: NSUserNotification? = nil + private var lowLevelNotificationState: Bool = false + private var highLevelNotificationState: Bool = false public init() { self.settingsView = Settings("Battery") @@ -138,10 +138,9 @@ public class Battery: Module { return } - if (value.level > notificationLevel || value.powerSource != "Battery Power") && self.lowNotification != nil { - NSUserNotificationCenter.default.removeDeliveredNotification(self.lowNotification!) + if (value.level > notificationLevel || value.powerSource != "Battery Power") && self.lowLevelNotificationState { if value.level > notificationLevel { - self.lowNotification = nil + self.lowLevelNotificationState = false } return } @@ -150,18 +149,26 @@ public class Battery: Module { return } - if value.level <= notificationLevel && self.lowNotification == nil { + if value.level <= notificationLevel && !self.lowLevelNotificationState { + let title = localizedString("Low battery") var subtitle = localizedString("Battery remaining", "\(Int(value.level*100))") if value.timeToEmpty > 0 { subtitle += " (\(Double(value.timeToEmpty*60).printSecondsToHoursMinutesSeconds()))" } - self.lowNotification = showNotification( - title: localizedString("Low battery"), - subtitle: subtitle, - id: "battery-level", - icon: NSImage(named: NSImage.Name("low-battery"))! - ) + if #available(macOS 10.14, *) { + showNotification( + title: title, + subtitle: subtitle + ) + } else { + showNSNotification( + title: title, + subtitle: subtitle + ) + } + + self.lowLevelNotificationState = true } } @@ -175,10 +182,9 @@ public class Battery: Module { return } - if (value.level < notificationLevel || value.powerSource == "Battery Power") && self.highNotification != nil { - NSUserNotificationCenter.default.removeDeliveredNotification(self.highNotification!) + if (value.level < notificationLevel || value.powerSource == "Battery Power") && self.highLevelNotificationState { if value.level < notificationLevel { - self.highNotification = nil + self.highLevelNotificationState = false } return } @@ -187,18 +193,26 @@ public class Battery: Module { return } - if value.level >= notificationLevel && self.highNotification == nil { + if value.level >= notificationLevel && !self.highLevelNotificationState { + let title = localizedString("High battery") var subtitle = localizedString("Battery remaining to full charge", "\(Int((1-value.level)*100))") if value.timeToCharge > 0 { subtitle += " (\(Double(value.timeToCharge*60).printSecondsToHoursMinutesSeconds()))" } - self.highNotification = showNotification( - title: localizedString("High battery"), - subtitle: subtitle, - id: "battery-level2", - icon: NSImage(named: NSImage.Name("high-battery"))! - ) + if #available(macOS 10.14, *) { + showNotification( + title: title, + subtitle: subtitle + ) + } else { + showNSNotification( + title: title, + subtitle: subtitle + ) + } + + self.highLevelNotificationState = true } } } diff --git a/Stats/AppDelegate.swift b/Stats/AppDelegate.swift index b969518a..468b217c 100755 --- a/Stats/AppDelegate.swift +++ b/Stats/AppDelegate.swift @@ -9,6 +9,7 @@ import Cocoa import Kit +import UserNotifications import CPU import RAM @@ -34,11 +35,11 @@ var modules: [Module] = [ ] @main -class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDelegate { +class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate { internal let settingsWindow: SettingsWindow = SettingsWindow() internal let updateWindow: UpdateWindow = UpdateWindow() - internal let updateNotification = NSUserNotification() internal let updateActivity = NSBackgroundActivityScheduler(identifier: "eu.exelban.Stats.updateCheck") + internal var clickInNotification: Bool = false static func main() { let app = NSApplication.shared @@ -75,16 +76,27 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele } func applicationShouldHandleReopen(_ sender: NSApplication, hasVisibleWindows flag: Bool) -> Bool { + if self.clickInNotification { + self.clickInNotification = false + return true + } + if flag { self.settingsWindow.makeKeyAndOrderFront(self) } else { self.settingsWindow.setIsVisible(true) } + return true } - func userNotificationCenter(_ center: NSUserNotificationCenter, didActivate notification: NSUserNotification) { - if let uri = notification.userInfo?["url"] as? String { + @available(macOS 10.14, *) + func userNotificationCenter(_ center: UNUserNotificationCenter, + didReceive response: UNNotificationResponse, + withCompletionHandler completionHandler: @escaping () -> Void) { + self.clickInNotification = true + + if let uri = response.notification.request.content.userInfo["url"] as? String { debug("Downloading new version of app...") if let url = URL(string: uri) { updater.download(url, doneHandler: { path in @@ -93,6 +105,6 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserNotificationCenterDele } } - NSUserNotificationCenter.default.removeDeliveredNotification(self.updateNotification) + completionHandler() } } diff --git a/Stats/helpers.swift b/Stats/helpers.swift index e005cce2..49b3c936 100644 --- a/Stats/helpers.swift +++ b/Stats/helpers.swift @@ -67,11 +67,21 @@ extension AppDelegate { } if isNewestVersion(currentVersion: prevVersion, latestVersion: currentVersion) { - _ = showNotification( - title: localizedString("Successfully updated"), - subtitle: localizedString("Stats was updated to v", currentVersion), - id: "updated-from-\(prevVersion)-to-\(currentVersion)" - ) + let title: String = localizedString("Successfully updated") + let subtitle: String = localizedString("Stats was updated to v", currentVersion) + + if #available(macOS 10.14, *) { + showNotification( + title: title, + subtitle: subtitle, + delegate: self + ) + } else { + showNSNotification( + title: title, + subtitle: subtitle + ) + } } debug("Detected previous version \(prevVersion). Current version (\(currentVersion) set") @@ -163,19 +173,24 @@ extension AppDelegate { private func showUpdateNotification(version: version_s) { debug("show update notification") - DispatchQueue.main.async(execute: { - self.updateNotification.identifier = "new-version-\(version.latest)" - self.updateNotification.title = localizedString("New version available") - self.updateNotification.subtitle = localizedString("Click to install the new version of Stats") - self.updateNotification.soundName = NSUserNotificationDefaultSoundName - - self.updateNotification.hasActionButton = true - self.updateNotification.actionButtonTitle = localizedString("Install") - self.updateNotification.userInfo = ["url": version.url] - - NSUserNotificationCenter.default.delegate = self - NSUserNotificationCenter.default.deliver(self.updateNotification) - }) + let title = localizedString("New version available") + let subtitle = localizedString("Click to install the new version of Stats") + let userInfo = ["url": version.url] + + if #available(macOS 10.14, *) { + showNotification( + title: title, + subtitle: subtitle, + userInfo: userInfo, + delegate: self + ) + } else { + showNSNotification( + title: title, + subtitle: subtitle, + userInfo: userInfo + ) + } } private func showUpdateWindow(version: version_s) {