Merge pull request #2397 from AngeloStavrow/2390-check-notifications-permissions-for-unread-count

2390 check notifications permissions for unread count
This commit is contained in:
Brent Simmons 2020-09-06 22:15:06 -07:00 committed by GitHub
commit 78556238c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 33 deletions

View File

@ -194,7 +194,12 @@ final class AppDefaults {
} }
var hideDockUnreadCount: Bool { var hideDockUnreadCount: Bool {
return AppDefaults.bool(for: Key.hideDockUnreadCount) get {
return AppDefaults.bool(for: Key.hideDockUnreadCount)
}
set {
AppDefaults.setBool(for: Key.hideDockUnreadCount, newValue)
}
} }
#if !MAC_APP_STORE #if !MAC_APP_STORE

View File

@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="mPU-HG-I4u"> <document type="com.apple.InterfaceBuilder3.Cocoa.Storyboard.XIB" version="3.0" toolsVersion="17154" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" initialViewController="mPU-HG-I4u">
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="16097.2"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="17154"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<scenes> <scenes>
@ -138,18 +139,7 @@
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
</buttonCell> </buttonCell>
<connections> <connections>
<binding destination="mAF-gO-1PI" name="value" keyPath="values.JustinMillerHideDockUnreadCount" id="J0i-eh-Rqq"> <action selector="toggleShowingUnreadCount:" target="iuH-lz-18x" id="CfQ-Pv-9d2"/>
<dictionary key="options">
<bool key="NSAllowsEditingMultipleValuesSelection" value="NO"/>
<bool key="NSConditionallySetsEnabled" value="NO"/>
<integer key="NSMultipleValuesPlaceholder" value="1"/>
<integer key="NSNoSelectionPlaceholder" value="1"/>
<integer key="NSNotApplicablePlaceholder" value="1"/>
<integer key="NSNullPlaceholder" value="1"/>
<bool key="NSRaisesForNotApplicableKeys" value="NO"/>
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections> </connections>
</button> </button>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="j0t-Wa-UTL"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" translatesAutoresizingMaskIntoConstraints="NO" id="j0t-Wa-UTL">
@ -198,6 +188,7 @@
</view> </view>
<connections> <connections>
<outlet property="defaultBrowserPopup" destination="Ci4-fW-KjU" id="7Nh-nU-Sbc"/> <outlet property="defaultBrowserPopup" destination="Ci4-fW-KjU" id="7Nh-nU-Sbc"/>
<outlet property="showUnreadCountCheckbox" destination="mwT-nY-TrX" id="ZH9-P5-JkT"/>
</connections> </connections>
</viewController> </viewController>
<customObject id="bSQ-tq-wd3" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/> <customObject id="bSQ-tq-wd3" userLabel="First Responder" customClass="NSResponder" sceneMemberID="firstResponder"/>
@ -383,16 +374,16 @@
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="7UM-iq-OLB" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target"> <customView translatesAutoresizingMaskIntoConstraints="NO" id="7UM-iq-OLB" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="44" width="160" height="219"/> <rect key="frame" x="20" y="44" width="160" height="234"/>
<subviews> <subviews>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="PaF-du-r3c"> <scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="PaF-du-r3c">
<rect key="frame" x="1" y="0.0" width="158" height="218"/> <rect key="frame" x="1" y="0.0" width="158" height="233"/>
<clipView key="contentView" id="cil-Gq-akO"> <clipView key="contentView" id="cil-Gq-akO">
<rect key="frame" x="0.0" y="0.0" width="158" height="218"/> <rect key="frame" x="0.0" y="0.0" width="158" height="233"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="aTp-KR-y6b"> <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="aTp-KR-y6b">
<rect key="frame" x="0.0" y="0.0" width="159" height="218"/> <rect key="frame" x="0.0" y="0.0" width="188" height="233"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/> <size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -411,7 +402,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews> <prototypeCellViews>
<tableCellView identifier="Cell" id="h2e-5a-qNO"> <tableCellView identifier="Cell" id="h2e-5a-qNO">
<rect key="frame" x="1" y="1" width="156" height="17"/> <rect key="frame" x="11" y="1" width="165" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="27f-p8-Wnt"> <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="27f-p8-Wnt">
@ -423,7 +414,7 @@
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSActionTemplate" id="lKA-xK-bHU"/> <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSActionTemplate" id="lKA-xK-bHU"/>
</imageView> </imageView>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hR2-bm-0wE"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO" id="hR2-bm-0wE">
<rect key="frame" x="26" y="1" width="126" height="16"/> <rect key="frame" x="26" y="1" width="135" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="CcS-BO-sdv"> <textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="CcS-BO-sdv">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -499,7 +490,7 @@
<rect key="frame" x="83" y="20" width="97" height="24"/> <rect key="frame" x="83" y="20" width="97" height="24"/>
</customView> </customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="Y7D-xQ-wep"> <customView translatesAutoresizingMaskIntoConstraints="NO" id="Y7D-xQ-wep">
<rect key="frame" x="188" y="20" width="242" height="243"/> <rect key="frame" x="188" y="20" width="242" height="258"/>
</customView> </customView>
</subviews> </subviews>
<constraints> <constraints>
@ -554,16 +545,16 @@
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="pjs-G4-byk" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target"> <customView translatesAutoresizingMaskIntoConstraints="NO" id="pjs-G4-byk" customClass="PreferencesTableViewBackgroundView" customModule="NetNewsWire" customModuleProvider="target">
<rect key="frame" x="20" y="44" width="160" height="212"/> <rect key="frame" x="20" y="44" width="160" height="227"/>
<subviews> <subviews>
<scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="29T-r2-ckC"> <scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="26" horizontalPageScroll="10" verticalLineScroll="26" verticalPageScroll="10" hasHorizontalScroller="NO" horizontalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="29T-r2-ckC">
<rect key="frame" x="1" y="0.0" width="158" height="211"/> <rect key="frame" x="1" y="0.0" width="158" height="226"/>
<clipView key="contentView" id="dXw-GY-TP8"> <clipView key="contentView" id="dXw-GY-TP8">
<rect key="frame" x="0.0" y="0.0" width="158" height="211"/> <rect key="frame" x="0.0" y="0.0" width="158" height="226"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="dfn-Vn-oDp"> <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnSelection="YES" columnResizing="NO" multipleSelection="NO" autosaveColumns="NO" rowHeight="24" viewBased="YES" id="dfn-Vn-oDp">
<rect key="frame" x="0.0" y="0.0" width="159" height="211"/> <rect key="frame" x="0.0" y="0.0" width="188" height="226"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/> <size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@ -582,7 +573,7 @@
<tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/> <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
<prototypeCellViews> <prototypeCellViews>
<tableCellView identifier="Cell" id="xQs-6E-Kpy"> <tableCellView identifier="Cell" id="xQs-6E-Kpy">
<rect key="frame" x="1" y="1" width="156" height="17"/> <rect key="frame" x="11" y="1" width="165" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kmG-vw-CbN"> <imageView horizontalHuggingPriority="251" verticalHuggingPriority="251" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="kmG-vw-CbN">
@ -594,7 +585,7 @@
<imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSActionTemplate" id="OVD-Jo-TXU"/> <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="NSActionTemplate" id="OVD-Jo-TXU"/>
</imageView> </imageView>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6cr-cB-qAN"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsExpansionToolTips="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6cr-cB-qAN">
<rect key="frame" x="26" y="1" width="126" height="16"/> <rect key="frame" x="26" y="1" width="135" height="16"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="goO-QG-kk7"> <textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="Table View Cell" id="goO-QG-kk7">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/> <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
@ -666,7 +657,7 @@
<rect key="frame" x="83" y="20" width="97" height="24"/> <rect key="frame" x="83" y="20" width="97" height="24"/>
</customView> </customView>
<customView translatesAutoresizingMaskIntoConstraints="NO" id="N1N-pE-gBL"> <customView translatesAutoresizingMaskIntoConstraints="NO" id="N1N-pE-gBL">
<rect key="frame" x="188" y="20" width="242" height="236"/> <rect key="frame" x="188" y="20" width="242" height="251"/>
</customView> </customView>
</subviews> </subviews>
<constraints> <constraints>
@ -701,8 +692,8 @@
</scene> </scene>
</scenes> </scenes>
<resources> <resources>
<image name="NSActionTemplate" width="14" height="14"/> <image name="NSActionTemplate" width="15" height="15"/>
<image name="NSAddTemplate" width="11" height="11"/> <image name="NSAddTemplate" width="14" height="13"/>
<image name="NSRemoveTemplate" width="11" height="11"/> <image name="NSRemoveTemplate" width="14" height="4"/>
</resources> </resources>
</document> </document>

View File

@ -9,11 +9,15 @@
import AppKit import AppKit
import RSCore import RSCore
import RSWeb import RSWeb
import UserNotifications
final class GeneralPreferencesViewController: NSViewController { final class GeneralPreferencesViewController: NSViewController {
@IBOutlet var defaultBrowserPopup: NSPopUpButton! private var userNotificationSettings: UNNotificationSettings?
@IBOutlet var defaultBrowserPopup: NSPopUpButton!
@IBOutlet weak var showUnreadCountCheckbox: NSButton!
public override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) { public override init(nibName nibNameOrNil: NSNib.Name?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
commonInit() commonInit()
@ -27,6 +31,7 @@ final class GeneralPreferencesViewController: NSViewController {
override func viewWillAppear() { override func viewWillAppear() {
super.viewWillAppear() super.viewWillAppear()
updateUI() updateUI()
updateNotificationSettings()
} }
// MARK: - Notifications // MARK: - Notifications
@ -45,6 +50,47 @@ final class GeneralPreferencesViewController: NSViewController {
AppDefaults.shared.defaultBrowserID = bundleID AppDefaults.shared.defaultBrowserID = bundleID
updateUI() updateUI()
} }
@IBAction func toggleShowingUnreadCount(_ sender: Any) {
guard let checkbox = sender as? NSButton else { return }
guard userNotificationSettings != nil else {
DispatchQueue.main.async {
self.showUnreadCountCheckbox.setNextState()
}
return
}
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
self.updateNotificationSettings()
if settings.authorizationStatus == .denied {
DispatchQueue.main.async {
self.showUnreadCountCheckbox.setNextState()
self.showNotificationsDeniedError()
}
} else if settings.authorizationStatus == .authorized {
DispatchQueue.main.async {
AppDefaults.shared.hideDockUnreadCount = (checkbox.state.rawValue == 0)
}
} else {
UNUserNotificationCenter.current().requestAuthorization(options: [.badge]) { (granted, error) in
self.updateNotificationSettings()
if granted {
DispatchQueue.main.async {
AppDefaults.shared.hideDockUnreadCount = checkbox.state.rawValue == 0
NSApplication.shared.registerForRemoteNotifications()
}
} else {
DispatchQueue.main.async {
self.showUnreadCountCheckbox.setNextState()
}
}
}
}
}
}
} }
// MARK: - Private // MARK: - Private
@ -57,6 +103,7 @@ private extension GeneralPreferencesViewController {
func updateUI() { func updateUI() {
updateBrowserPopup() updateBrowserPopup()
updateHideUnreadCountCheckbox()
} }
func updateBrowserPopup() { func updateBrowserPopup() {
@ -89,4 +136,33 @@ private extension GeneralPreferencesViewController {
defaultBrowserPopup.selectItem(at: defaultBrowserPopup.indexOfItem(withRepresentedObject: AppDefaults.shared.defaultBrowserID)) defaultBrowserPopup.selectItem(at: defaultBrowserPopup.indexOfItem(withRepresentedObject: AppDefaults.shared.defaultBrowserID))
} }
func updateHideUnreadCountCheckbox() {
showUnreadCountCheckbox.state = AppDefaults.shared.hideDockUnreadCount ? .off : .on
}
func updateNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { (settings) in
self.userNotificationSettings = settings
if settings.authorizationStatus == .authorized {
DispatchQueue.main.async {
NSApplication.shared.registerForRemoteNotifications()
}
}
}
}
func showNotificationsDeniedError() {
let updateAlert = NSAlert()
updateAlert.alertStyle = .informational
updateAlert.messageText = NSLocalizedString("Enable Notifications", comment: "Notifications")
updateAlert.informativeText = NSLocalizedString("To enable notifications, open Notifications in System Preferences, then find NetNewsWire in the list.", comment: "To enable notifications, open Notifications in System Preferences, then find NetNewsWire in the list.")
updateAlert.addButton(withTitle: NSLocalizedString("Open System Preferences", comment: "Open System Preferences"))
updateAlert.addButton(withTitle: NSLocalizedString("Close", comment: "Close"))
let modalResponse = updateAlert.runModal()
if modalResponse == .alertFirstButtonReturn {
NSWorkspace.shared.open(URL(fileURLWithPath: "x-apple.systempreferences:com.apple.preference.notifications"))
}
}
} }