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