mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Notification Manager changes
- Only appears in Settings when notifications are authorised. - Both Settings/NotificationsViewController monitor for return to foreground and update based on notification settings
This commit is contained in:
@@ -18,12 +18,14 @@ class NotificationsViewController: UIViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
self.title = NSLocalizedString("Notifications", comment: "Notifications")
|
||||
self.title = NSLocalizedString("New Article Notifications", comment: "Notifications")
|
||||
notificationsTableView.sectionHeaderTopPadding = 25
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reloadNotificationTableView(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reloadNotificationTableView(_:)), name: .WebFeedIconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reloadNotificationTableView(_:)), name: .NotificationPreferencesDidUpdate, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(reloadNotificationTableView(_:)), name: UIScene.willEnterForegroundNotification, object: nil)
|
||||
|
||||
reloadNotificationTableView()
|
||||
}
|
||||
|
||||
@@ -37,8 +39,6 @@ class NotificationsViewController: UIViewController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private func sortedWebFeedsForAccount(_ account: Account) -> [WebFeed] {
|
||||
return Array(account.flattenedWebFeeds()).sorted(by: { $0.nameForDisplay.caseInsensitiveCompare($1.nameForDisplay) == .orderedAscending })
|
||||
}
|
||||
@@ -49,33 +49,36 @@ class NotificationsViewController: UIViewController {
|
||||
extension NotificationsViewController: UITableViewDataSource {
|
||||
|
||||
func numberOfSections(in tableView: UITableView) -> Int {
|
||||
/// 1 section for enabling notifications
|
||||
/// + number of active accounts
|
||||
if status == .denied { return 1 }
|
||||
return 1 + AccountManager.shared.activeAccounts.count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if section == 0 { return 1 }
|
||||
if section == 0 {
|
||||
if status == .denied { return 1 }
|
||||
return 0
|
||||
}
|
||||
return AccountManager.shared.sortedActiveAccounts[section - 1].flattenedWebFeeds().count
|
||||
}
|
||||
|
||||
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "NotificationsCell") as! NotificationsTableViewCell
|
||||
|
||||
|
||||
if indexPath.section == 0 {
|
||||
cell.configure(status)
|
||||
let openSettingsCell = tableView.dequeueReusableCell(withIdentifier: "OpenSettingsCell") as! VibrantBasicTableViewCell
|
||||
return openSettingsCell
|
||||
} else {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "NotificationsCell") as! NotificationsTableViewCell
|
||||
let account = AccountManager.shared.sortedActiveAccounts[indexPath.section - 1]
|
||||
let feed = sortedWebFeedsForAccount(account)[indexPath.row]
|
||||
cell.configure(feed, status)
|
||||
return cell
|
||||
}
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
|
||||
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
if section == 0 { return " " }
|
||||
if section == 0 { return nil }
|
||||
return AccountManager.shared.sortedActiveAccounts[section - 1].nameForDisplay
|
||||
}
|
||||
|
||||
@@ -84,9 +87,6 @@ extension NotificationsViewController: UITableViewDataSource {
|
||||
if status == .denied {
|
||||
return NSLocalizedString("Notification permissions are currently denied. Enable notifications in the Settings app.", comment: "Notifications denied.")
|
||||
}
|
||||
if status == .notDetermined {
|
||||
return NSLocalizedString("Turn on notifications to configure new article notifications.", comment: "Notifications not determined.")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -94,7 +94,10 @@ extension NotificationsViewController: UITableViewDataSource {
|
||||
|
||||
extension NotificationsViewController: UITableViewDelegate {
|
||||
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.deselectRow(at: indexPath, animated: true)
|
||||
UIApplication.shared.open(URL(string: "\(UIApplication.openSettingsURLString)")!)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1115,32 +1115,32 @@
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="insetGrouped" separatorStyle="default" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="dsQ-vy-iVG">
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="-1" estimatedSectionHeaderHeight="-1" sectionFooterHeight="-1" estimatedSectionFooterHeight="-1" translatesAutoresizingMaskIntoConstraints="NO" id="dsQ-vy-iVG">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<color key="backgroundColor" systemColor="systemGroupedBackgroundColor"/>
|
||||
<prototypes>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="NotificationsCell" id="guK-h7-1U7" customClass="NotificationsTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="49.5" width="374" height="43.5"/>
|
||||
<rect key="frame" x="20" y="49.5" width="374" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="guK-h7-1U7" id="7Rd-Ur-EwD">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="40"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<switch opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" on="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ggq-dZ-hv7">
|
||||
<rect key="frame" x="307" y="6.5" width="51" height="31"/>
|
||||
<rect key="frame" x="307" y="4.5" width="51" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="49" id="O0E-7e-Q9P"/>
|
||||
</constraints>
|
||||
<color key="onTintColor" name="AccentColor"/>
|
||||
</switch>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="78k-PU-gKA">
|
||||
<rect key="frame" x="58" y="11" width="241" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<rect key="frame" x="58" y="11" width="241" height="17.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="bell.fill" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="Vha-ij-dDN">
|
||||
<rect key="frame" x="20" y="10" width="25" height="24.5"/>
|
||||
<rect key="frame" x="20" y="8" width="25" height="24.5"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="25" id="cpy-hb-TiY"/>
|
||||
<constraint firstAttribute="width" constant="25" id="xvC-Ma-Mfj"/>
|
||||
@@ -1164,6 +1164,23 @@
|
||||
<outlet property="notificationsSwitch" destination="ggq-dZ-hv7" id="Zta-QP-hSe"/>
|
||||
</connections>
|
||||
</tableViewCell>
|
||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="OpenSettingsCell" textLabel="5OE-bg-gWy" style="IBUITableViewCellStyleDefault" id="LXf-Fb-We7" customClass="VibrantBasicTableViewCell" customModule="NetNewsWire" customModuleProvider="target">
|
||||
<rect key="frame" x="20" y="89.5" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="LXf-Fb-We7" id="k2T-id-bci">
|
||||
<rect key="frame" x="0.0" y="0.0" width="374" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Open System Settings" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="5OE-bg-gWy">
|
||||
<rect key="frame" x="20" y="0.0" width="334" height="43.5"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</tableViewCellContentView>
|
||||
</tableViewCell>
|
||||
</prototypes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="vak-Sx-5aB" id="Qh1-Px-8LM"/>
|
||||
|
||||
@@ -12,6 +12,7 @@ import CoreServices
|
||||
import SafariServices
|
||||
import SwiftUI
|
||||
import UniformTypeIdentifiers
|
||||
import UserNotifications
|
||||
|
||||
class SettingsViewController: UITableViewController {
|
||||
|
||||
@@ -29,6 +30,8 @@ class SettingsViewController: UITableViewController {
|
||||
var scrollToArticlesSection = false
|
||||
weak var presentingParentController: UIViewController?
|
||||
|
||||
var notificationStatus: UNAuthorizationStatus = .notDetermined
|
||||
|
||||
override func viewDidLoad() {
|
||||
// This hack mostly works around a bug in static tables with dynamic type. See: https://spin.atomicobject.com/2018/10/15/dynamic-type-static-uitableview/
|
||||
NotificationCenter.default.removeObserver(tableView!, name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||
@@ -38,6 +41,7 @@ class SettingsViewController: UITableViewController {
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(accountsDidChange), name: .UserDidDeleteAccount, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(displayNameDidChange), name: .DisplayNameDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(activeExtensionPointsDidChange), name: .ActiveExtensionPointsDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(refreshNotificationStatus(_:)), name: UIScene.willEnterForegroundNotification, object: nil)
|
||||
|
||||
|
||||
tableView.register(UINib(nibName: "SettingsComboTableViewCell", bundle: nil), forCellReuseIdentifier: "SettingsComboTableViewCell")
|
||||
@@ -84,9 +88,7 @@ class SettingsViewController: UITableViewController {
|
||||
}
|
||||
|
||||
colorPaletteDetailLabel.text = String(describing: AppDefaults.userInterfaceColorPalette)
|
||||
|
||||
openLinksInNetNewsWire.isOn = !AppDefaults.shared.useSystemBrowser
|
||||
|
||||
|
||||
let buildLabel = NonIntrinsicLabel(frame: CGRect(x: 32.0, y: 0.0, width: 0.0, height: 0.0))
|
||||
buildLabel.font = UIFont.systemFont(ofSize: 11.0)
|
||||
@@ -110,7 +112,17 @@ class SettingsViewController: UITableViewController {
|
||||
tableView.scrollToRow(at: IndexPath(row: 0, section: 4), at: .top, animated: true)
|
||||
scrollToArticlesSection = false
|
||||
}
|
||||
|
||||
refreshNotificationStatus()
|
||||
}
|
||||
|
||||
@objc
|
||||
func refreshNotificationStatus(_ sender: Any? = nil) {
|
||||
UNUserNotificationCenter.current().getNotificationSettings { settings in
|
||||
DispatchQueue.main.async {
|
||||
self.notificationStatus = settings.authorizationStatus
|
||||
self.tableView.reloadData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: UITableView
|
||||
@@ -118,6 +130,9 @@ class SettingsViewController: UITableViewController {
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
|
||||
switch section {
|
||||
case 0:
|
||||
if notificationStatus == .authorized { return 2 }
|
||||
return 1
|
||||
case 1:
|
||||
return AccountManager.shared.accounts.count + 1
|
||||
case 2:
|
||||
|
||||
Reference in New Issue
Block a user