From 6b1ad170caeac1c8dd46b1d078ce4f98bd306167 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Tue, 2 Feb 2021 08:16:45 +0800 Subject: [PATCH 1/4] Adds sidebar toggles for notifications/reader --- ...idebarViewController+ContextualMenus.swift | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift index 61661bb55..8dd53b15a 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift @@ -98,6 +98,23 @@ extension SidebarViewController { } window.beginSheet(renameSheet) } + + @objc func toggleNotificationsFromContextMenu(_ sender: Any?) { + guard let item = sender as? NSMenuItem, + let feed = item.representedObject as? WebFeed else { + return + } + feed.isNotifyAboutNewArticles?.toggle() + } + + @objc func toggleArticleExtractorFromContextMenu(_ sender: Any?) { + guard let item = sender as? NSMenuItem, + let feed = item.representedObject as? WebFeed else { + return + } + feed.isArticleExtractorAlwaysOn?.toggle() + } + } extension SidebarViewController: RenameWindowControllerDelegate { @@ -163,7 +180,24 @@ private extension SidebarViewController { menu.addItem(item) } menu.addItem(NSMenuItem.separator()) - + + var notificationText: String! + if webFeed.isNotifyAboutNewArticles != nil && webFeed.isNotifyAboutNewArticles! { + notificationText = NSLocalizedString("Disable New Article Notifications", comment: "Disable Notifications") + } else { + notificationText = NSLocalizedString("Enable New Article Notifications", comment: "Enable Notifications") + } + menu.addItem(menuItem(notificationText, #selector(toggleNotificationsFromContextMenu(_:)), webFeed)) + + var articleExtractorText: String! + if webFeed.isArticleExtractorAlwaysOn != nil && webFeed.isArticleExtractorAlwaysOn! { + articleExtractorText = NSLocalizedString("Disable Reader View", comment: "Disable Reader View") + } else { + articleExtractorText = NSLocalizedString("Enable Reader View", comment: "Enable Reader View") + } + menu.addItem(menuItem(articleExtractorText, #selector(toggleArticleExtractorFromContextMenu(_:)), webFeed)) + menu.addItem(NSMenuItem.separator()) + menu.addItem(renameMenuItem(webFeed)) menu.addItem(deleteMenuItem([webFeed])) From 62ed7492eb094de094c8f55f209b4ec2b606b6a9 Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Tue, 2 Feb 2021 10:26:34 +0800 Subject: [PATCH 2/4] Adds checkmarks Also adds notification to keep Inspector in sync. --- .../WebFeedInspectorViewController.swift | 4 ++- ...idebarViewController+ContextualMenus.swift | 34 ++++++++++++------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/Mac/Inspector/WebFeedInspectorViewController.swift b/Mac/Inspector/WebFeedInspectorViewController.swift index b71341a57..d03fd135f 100644 --- a/Mac/Inspector/WebFeedInspectorViewController.swift +++ b/Mac/Inspector/WebFeedInspectorViewController.swift @@ -50,6 +50,7 @@ final class WebFeedInspectorViewController: NSViewController, Inspector { override func viewDidLoad() { updateUI() NotificationCenter.default.addObserver(self, selector: #selector(imageDidBecomeAvailable(_:)), name: .ImageDidBecomeAvailable, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: .DidUpdateFeedPreferencesFromContextMenu, object: nil) } override func viewDidAppear() { @@ -129,7 +130,8 @@ private extension WebFeedInspectorViewController { feed = singleFeed } - func updateUI() { + + @objc func updateUI() { updateImage() updateName() updateHomePageURL() diff --git a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift index 8dd53b15a..c51698b8c 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift @@ -11,6 +11,10 @@ import Articles import Account import RSCore +extension Notification.Name { + public static let DidUpdateFeedPreferencesFromContextMenu = Notification.Name(rawValue: "DidUpdateFeedPreferencesFromContextMenu") +} + extension SidebarViewController { func menu(for objects: [Any]?) -> NSMenu? { @@ -105,6 +109,7 @@ extension SidebarViewController { return } feed.isNotifyAboutNewArticles?.toggle() + NotificationCenter.default.post(Notification(name: .DidUpdateFeedPreferencesFromContextMenu)) } @objc func toggleArticleExtractorFromContextMenu(_ sender: Any?) { @@ -113,6 +118,7 @@ extension SidebarViewController { return } feed.isArticleExtractorAlwaysOn?.toggle() + NotificationCenter.default.post(Notification(name: .DidUpdateFeedPreferencesFromContextMenu)) } } @@ -181,21 +187,25 @@ private extension SidebarViewController { } menu.addItem(NSMenuItem.separator()) - var notificationText: String! - if webFeed.isNotifyAboutNewArticles != nil && webFeed.isNotifyAboutNewArticles! { - notificationText = NSLocalizedString("Disable New Article Notifications", comment: "Disable Notifications") - } else { - notificationText = NSLocalizedString("Enable New Article Notifications", comment: "Enable Notifications") - } - menu.addItem(menuItem(notificationText, #selector(toggleNotificationsFromContextMenu(_:)), webFeed)) + let notificationText = NSLocalizedString("Show Notifications for New Articles", comment: "Show Notifications for New Articles") - var articleExtractorText: String! - if webFeed.isArticleExtractorAlwaysOn != nil && webFeed.isArticleExtractorAlwaysOn! { - articleExtractorText = NSLocalizedString("Disable Reader View", comment: "Disable Reader View") + let notificationMenuItem = menuItem(notificationText, #selector(toggleNotificationsFromContextMenu(_:)), webFeed) + if webFeed.isNotifyAboutNewArticles == nil || webFeed.isNotifyAboutNewArticles! == false { + notificationMenuItem.state = .off } else { - articleExtractorText = NSLocalizedString("Enable Reader View", comment: "Enable Reader View") + notificationMenuItem.state = .on } - menu.addItem(menuItem(articleExtractorText, #selector(toggleArticleExtractorFromContextMenu(_:)), webFeed)) + menu.addItem(notificationMenuItem) + + let articleExtractorText = NSLocalizedString("Always Use Reader View", comment: "Always Use Reader View") + let articleExtractorMenuItem = menuItem(articleExtractorText, #selector(toggleArticleExtractorFromContextMenu(_:)), webFeed) + + if webFeed.isArticleExtractorAlwaysOn == nil || webFeed.isArticleExtractorAlwaysOn! == false { + articleExtractorMenuItem.state = .off + } else { + articleExtractorMenuItem.state = .on + } + menu.addItem(articleExtractorMenuItem) menu.addItem(NSMenuItem.separator()) menu.addItem(renameMenuItem(webFeed)) From aa0a5d2269441577dd4ce485134b2d47fdeb029a Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Tue, 2 Feb 2021 11:54:47 +0800 Subject: [PATCH 3/4] Checks for notification permissions If notifications are authorised, the toggle will work. Otherwise, an alert is shown giving the user required information to enable notifications. --- ...idebarViewController+ContextualMenus.swift | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift index c51698b8c..d28fb85c1 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift @@ -10,6 +10,7 @@ import AppKit import Articles import Account import RSCore +import UserNotifications extension Notification.Name { public static let DidUpdateFeedPreferencesFromContextMenu = Notification.Name(rawValue: "DidUpdateFeedPreferencesFromContextMenu") @@ -108,8 +109,28 @@ extension SidebarViewController { let feed = item.representedObject as? WebFeed else { return } - feed.isNotifyAboutNewArticles?.toggle() - NotificationCenter.default.post(Notification(name: .DidUpdateFeedPreferencesFromContextMenu)) + UNUserNotificationCenter.current().getNotificationSettings { (settings) in + if settings.authorizationStatus == .denied { + self.showNotificationsNotEnabledAlert() + } else if settings.authorizationStatus == .authorized { + DispatchQueue.main.async { + feed.isNotifyAboutNewArticles?.toggle() + NotificationCenter.default.post(Notification(name: .DidUpdateFeedPreferencesFromContextMenu)) + } + } else { + UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert]) { (granted, error) in + if granted { + DispatchQueue.main.async { + feed.isNotifyAboutNewArticles?.toggle() + NotificationCenter.default.post(Notification(name: .DidUpdateFeedPreferencesFromContextMenu)) + NSApplication.shared.registerForRemoteNotifications() + } + } else { + self.showNotificationsNotEnabledAlert() + } + } + } + } } @objc func toggleArticleExtractorFromContextMenu(_ sender: Any?) { @@ -121,6 +142,25 @@ extension SidebarViewController { NotificationCenter.default.post(Notification(name: .DidUpdateFeedPreferencesFromContextMenu)) } + func showNotificationsNotEnabledAlert() { + DispatchQueue.main.async { + let alert = NSAlert() + alert.messageText = NSLocalizedString("Notifications are not enabled", comment: "Notifications are not enabled.") + alert.informativeText = NSLocalizedString("You can enable NetNewsWire notifications in System Preferences.", comment: "Notifications are not enabled.") + alert.addButton(withTitle: NSLocalizedString("Open System Preferences", comment: "Open System Preferences")) + alert.addButton(withTitle: NSLocalizedString("Dismiss", comment: "Dismiss")) + let userChoice = alert.runModal() + if userChoice == .alertFirstButtonReturn { + let config = NSWorkspace.OpenConfiguration() + config.activates = true + // If System Preferences is already open, and no delay is provided here, then it appears in the foreground and immediately disappears. + DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.2, execute: { + NSWorkspace.shared.open(URL(string: "x-apple.systempreferences:com.apple.preference.notifications")!, configuration: config) + }) + } + } + } + } extension SidebarViewController: RenameWindowControllerDelegate { From e88327be787863da221990df0f30fcc66db4e1ca Mon Sep 17 00:00:00 2001 From: Stuart Breckenridge Date: Tue, 2 Feb 2021 13:25:06 +0800 Subject: [PATCH 4/4] =?UTF-8?q?You=20can=E2=80=99t=20toggle=20an=20optiona?= =?UTF-8?q?l=20Bool?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sidebar/SidebarViewController+ContextualMenus.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift index d28fb85c1..e6861aa9c 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift @@ -114,6 +114,7 @@ extension SidebarViewController { self.showNotificationsNotEnabledAlert() } else if settings.authorizationStatus == .authorized { DispatchQueue.main.async { + if feed.isNotifyAboutNewArticles == nil { feed.isNotifyAboutNewArticles = false } feed.isNotifyAboutNewArticles?.toggle() NotificationCenter.default.post(Notification(name: .DidUpdateFeedPreferencesFromContextMenu)) } @@ -121,6 +122,7 @@ extension SidebarViewController { UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert]) { (granted, error) in if granted { DispatchQueue.main.async { + if feed.isNotifyAboutNewArticles == nil { feed.isNotifyAboutNewArticles = false } feed.isNotifyAboutNewArticles?.toggle() NotificationCenter.default.post(Notification(name: .DidUpdateFeedPreferencesFromContextMenu)) NSApplication.shared.registerForRemoteNotifications() @@ -138,6 +140,7 @@ extension SidebarViewController { let feed = item.representedObject as? WebFeed else { return } + if feed.isArticleExtractorAlwaysOn == nil { feed.isArticleExtractorAlwaysOn = false } feed.isArticleExtractorAlwaysOn?.toggle() NotificationCenter.default.post(Notification(name: .DidUpdateFeedPreferencesFromContextMenu)) }