2018-01-21 04:06:07 +01:00
//
// F e e d I n s p e c t o r V i e w C o n t r o l l e r . s w i f t
2018-08-29 07:18:24 +02:00
// N e t N e w s W i r e
2018-01-21 04:06:07 +01:00
//
// C r e a t e d b y B r e n t S i m m o n s o n 1 / 2 0 / 1 8 .
// C o p y r i g h t © 2 0 1 8 R a n c h e r o S o f t w a r e . A l l r i g h t s r e s e r v e d .
//
import AppKit
2018-07-24 03:29:08 +02:00
import Articles
2018-07-28 21:16:14 +02:00
import Account
2020-08-01 17:50:57 +02:00
import UserNotifications
2018-01-21 04:06:07 +01:00
2019-11-15 03:11:41 +01:00
final class WebFeedInspectorViewController : NSViewController , Inspector {
2018-01-21 04:06:07 +01:00
2019-11-12 22:52:07 +01:00
@IBOutlet weak var iconView : IconView !
2019-10-03 02:42:16 +02:00
@IBOutlet weak var nameTextField : NSTextField ?
@IBOutlet weak var homePageURLTextField : NSTextField ?
@IBOutlet weak var urlTextField : NSTextField ?
@IBOutlet weak var isNotifyAboutNewArticlesCheckBox : NSButton !
2019-09-20 02:49:11 +02:00
@IBOutlet weak var isReaderViewAlwaysOnCheckBox : NSButton ?
2019-11-15 03:11:41 +01:00
private var feed : WebFeed ? {
2018-01-22 06:01:18 +01:00
didSet {
2018-01-22 06:24:25 +01:00
if feed != oldValue {
updateUI ( )
}
2018-01-22 06:01:18 +01:00
}
}
2020-08-01 17:50:57 +02:00
private var userNotificationSettings : UNNotificationSettings ?
2018-01-22 06:01:18 +01:00
// MARK: I n s p e c t o r
2018-01-22 05:35:44 +01:00
2018-01-21 07:36:17 +01:00
let isFallbackInspector = false
2018-01-22 05:35:44 +01:00
var objects : [ Any ] ? {
didSet {
2020-12-10 00:09:28 +01:00
renameWebFeedIfNecessary ( )
2018-01-22 06:01:18 +01:00
updateFeed ( )
2018-01-22 05:35:44 +01:00
}
}
2020-09-07 19:34:37 +02:00
var windowTitle : String = NSLocalizedString ( " Feed Inspector " , comment : " Feed Inspector window title " )
2018-01-21 07:36:17 +01:00
func canInspect ( _ objects : [ Any ] ) -> Bool {
2019-11-15 03:11:41 +01:00
return objects . count = = 1 && objects . first is WebFeed
2018-01-21 07:36:17 +01:00
}
2018-01-22 06:01:18 +01:00
// MARK: N S V i e w C o n t r o l l e r
override func viewDidLoad ( ) {
updateUI ( )
NotificationCenter . default . addObserver ( self , selector : #selector ( imageDidBecomeAvailable ( _ : ) ) , name : . ImageDidBecomeAvailable , object : nil )
2021-02-02 03:26:34 +01:00
NotificationCenter . default . addObserver ( self , selector : #selector ( updateUI ) , name : . DidUpdateFeedPreferencesFromContextMenu , object : nil )
2018-01-22 06:01:18 +01:00
}
2020-08-01 17:52:33 +02:00
override func viewDidAppear ( ) {
updateNotificationSettings ( )
}
2020-12-10 00:09:28 +01:00
override func viewDidDisappear ( ) {
renameWebFeedIfNecessary ( )
}
2019-09-20 02:49:11 +02:00
// MARK: A c t i o n s
2019-10-03 02:42:16 +02:00
@IBAction func isNotifyAboutNewArticlesChanged ( _ sender : Any ) {
2020-08-02 14:49:37 +02:00
guard userNotificationSettings != nil else {
DispatchQueue . main . async {
self . isNotifyAboutNewArticlesCheckBox . setNextState ( )
}
2020-08-01 17:53:26 +02:00
return
}
2020-08-02 14:47:14 +02:00
UNUserNotificationCenter . current ( ) . getNotificationSettings { ( settings ) in
self . updateNotificationSettings ( )
if settings . authorizationStatus = = . denied {
DispatchQueue . main . async {
self . isNotifyAboutNewArticlesCheckBox . setNextState ( )
self . showNotificationsDeniedError ( )
}
} else if settings . authorizationStatus = = . authorized {
DispatchQueue . main . async {
self . feed ? . isNotifyAboutNewArticles = ( self . isNotifyAboutNewArticlesCheckBox ? . state ? ? . off ) = = . on ? true : false
}
} else {
UNUserNotificationCenter . current ( ) . requestAuthorization ( options : [ . badge , . sound , . alert ] ) { ( granted , error ) in
self . updateNotificationSettings ( )
if granted {
DispatchQueue . main . async {
self . feed ? . isNotifyAboutNewArticles = ( self . isNotifyAboutNewArticlesCheckBox ? . state ? ? . off ) = = . on ? true : false
NSApplication . shared . registerForRemoteNotifications ( )
}
} else {
DispatchQueue . main . async {
self . isNotifyAboutNewArticlesCheckBox . setNextState ( )
}
2020-08-01 19:09:33 +02:00
}
2020-08-01 17:53:26 +02:00
}
}
}
2019-10-03 02:42:16 +02:00
}
2019-09-20 02:49:11 +02:00
@IBAction func isReaderViewAlwaysOnChanged ( _ sender : Any ) {
feed ? . isArticleExtractorAlwaysOn = ( isReaderViewAlwaysOnCheckBox ? . state ? ? . off ) = = . on ? true : false
}
2018-01-22 06:01:18 +01:00
// MARK: N o t i f i c a t i o n s
@objc func imageDidBecomeAvailable ( _ note : Notification ) {
updateImage ( )
2018-01-22 05:35:44 +01:00
}
2019-09-20 02:49:11 +02:00
2018-01-22 05:35:44 +01:00
}
2019-11-15 03:11:41 +01:00
extension WebFeedInspectorViewController : NSTextFieldDelegate {
2018-01-22 06:31:26 +01:00
2020-12-10 00:09:28 +01:00
func controlTextDidEndEditing ( _ note : Notification ) {
renameWebFeedIfNecessary ( )
2018-01-24 06:49:33 +01:00
}
2019-09-20 02:49:11 +02:00
2018-01-22 06:31:26 +01:00
}
2019-11-15 03:11:41 +01:00
private extension WebFeedInspectorViewController {
2018-01-22 05:35:44 +01:00
2018-01-22 06:01:18 +01:00
func updateFeed ( ) {
2019-11-15 03:11:41 +01:00
guard let objects = objects , objects . count = = 1 , let singleFeed = objects . first as ? WebFeed else {
2018-01-22 06:01:18 +01:00
feed = nil
return
2018-01-22 05:35:44 +01:00
}
2018-01-22 06:01:18 +01:00
feed = singleFeed
2018-01-22 05:35:44 +01:00
}
2021-02-02 03:26:34 +01:00
@objc func updateUI ( ) {
2018-01-22 06:01:18 +01:00
updateImage ( )
updateName ( )
updateHomePageURL ( )
updateFeedURL ( )
2019-10-03 02:42:16 +02:00
updateNotifyAboutNewArticles ( )
2019-09-20 02:49:11 +02:00
updateIsReaderViewAlwaysOn ( )
2020-09-07 19:59:14 +02:00
windowTitle = feed ? . nameForDisplay ? ? NSLocalizedString ( " Feed Inspector " , comment : " Feed Inspector window title " )
2018-01-22 06:01:18 +01:00
view . needsLayout = true
2018-01-22 05:35:44 +01:00
}
2018-01-22 06:01:18 +01:00
func updateImage ( ) {
2019-11-12 22:52:07 +01:00
guard let feed = feed , let iconView = iconView else {
2018-01-22 06:01:18 +01:00
return
2018-01-22 05:35:44 +01:00
}
2019-11-15 03:11:41 +01:00
if let feedIcon = appDelegate . webFeedIconDownloader . icon ( for : feed ) {
2019-11-12 22:52:07 +01:00
iconView . iconImage = feedIcon
2018-01-22 06:04:52 +01:00
return
}
2018-01-22 06:24:25 +01:00
2019-11-12 22:52:07 +01:00
if let favicon = appDelegate . faviconDownloader . favicon ( for : feed ) {
iconView . iconImage = favicon
2018-01-22 06:04:52 +01:00
return
}
2018-01-22 05:35:44 +01:00
2019-11-12 22:52:07 +01:00
iconView . iconImage = feed . smallIcon
2018-01-22 05:35:44 +01:00
}
2018-01-22 06:01:18 +01:00
func updateName ( ) {
2018-01-23 07:01:25 +01:00
guard let nameTextField = nameTextField else {
return
}
let name = feed ? . editedName ? ? feed ? . name ? ? " "
if nameTextField . stringValue != name {
nameTextField . stringValue = name
}
2018-01-22 05:35:44 +01:00
}
2018-01-22 06:01:18 +01:00
func updateHomePageURL ( ) {
2020-07-06 17:06:12 +02:00
homePageURLTextField ? . stringValue = feed ? . homePageURL ? . decodedURLString ? ? " "
2018-01-22 05:35:44 +01:00
}
2018-01-22 06:01:18 +01:00
func updateFeedURL ( ) {
2020-07-06 17:06:12 +02:00
urlTextField ? . stringValue = feed ? . url . decodedURLString ? ? " "
2018-01-21 07:36:17 +01:00
}
2020-08-01 17:52:33 +02:00
2020-08-02 14:43:24 +02:00
func updateNotifyAboutNewArticles ( ) {
isNotifyAboutNewArticlesCheckBox ? . state = ( feed ? . isNotifyAboutNewArticles ? ? false ) ? . on : . off
}
func updateIsReaderViewAlwaysOn ( ) {
isReaderViewAlwaysOnCheckBox ? . state = ( feed ? . isArticleExtractorAlwaysOn ? ? false ) ? . on : . off
}
2020-08-01 17:52:33 +02:00
func updateNotificationSettings ( ) {
UNUserNotificationCenter . current ( ) . getNotificationSettings { ( settings ) in
2020-08-02 14:45:36 +02:00
self . userNotificationSettings = settings
if settings . authorizationStatus = = . authorized {
DispatchQueue . main . async {
2020-08-01 17:52:33 +02:00
NSApplication . shared . registerForRemoteNotifications ( )
}
}
}
}
2020-08-01 19:02:24 +02:00
func showNotificationsDeniedError ( ) {
let updateAlert = NSAlert ( )
updateAlert . alertStyle = . informational
updateAlert . messageText = NSLocalizedString ( " Enable Notifications " , comment : " Notifications " )
2020-08-02 14:41:48 +02:00
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. " )
2020-08-01 19:02:24 +02:00
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 {
2020-09-22 13:10:13 +02:00
NSWorkspace . shared . open ( URL ( string : " x-apple.systempreferences:com.apple.preference.notifications " ) ! )
2020-08-01 19:02:24 +02:00
}
}
2019-10-03 02:42:16 +02:00
2020-12-10 00:09:28 +01:00
func renameWebFeedIfNecessary ( ) {
guard let feed = feed ,
let account = feed . account ,
let nameTextField = nameTextField ,
feed . nameForDisplay != nameTextField . stringValue else {
return
}
account . renameWebFeed ( feed , to : nameTextField . stringValue ) { [ weak self ] result in
if case . failure ( let error ) = result {
self ? . presentError ( error )
2020-12-10 00:12:58 +01:00
} else {
self ? . windowTitle = feed . nameForDisplay
2020-12-10 00:09:28 +01:00
}
}
}
2018-01-21 06:35:59 +01:00
}