2019-11-07 13:40:10 +01:00
//
2024-02-26 08:12:21 +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
2019-11-07 13:40:10 +01:00
// N e t N e w s W i r e - i O S
//
// C r e a t e d b y M a u r i c e P a r k e r o n 1 1 / 6 / 1 9 .
// C o p y r i g h t © 2 0 1 9 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 UIKit
import Account
2020-01-11 22:31:47 +01:00
import SafariServices
2020-05-18 02:39:22 +02:00
import UserNotifications
2024-04-16 07:21:17 +02:00
import Images
2019-11-07 13:40:10 +01:00
2024-02-26 08:12:21 +01:00
class FeedInspectorViewController : UITableViewController {
2019-11-07 13:40:10 +01:00
2019-11-14 00:02:14 +01:00
static let preferredContentSizeForFormSheetDisplay = CGSize ( width : 460.0 , height : 500.0 )
2019-11-07 13:40:10 +01:00
2024-02-26 08:12:21 +01:00
var feed : Feed !
2019-11-07 13:40:10 +01:00
@IBOutlet weak var nameTextField : UITextField !
@IBOutlet weak var notifyAboutNewArticlesSwitch : UISwitch !
@IBOutlet weak var alwaysShowReaderViewSwitch : UISwitch !
@IBOutlet weak var homePageLabel : InteractiveLabel !
@IBOutlet weak var feedURLLabel : InteractiveLabel !
private var headerView : InspectorIconHeaderView ?
2021-05-08 21:42:44 +02:00
private var iconImage : IconImage ? {
2024-02-26 08:12:21 +01:00
return IconImageCache . shared . imageForFeed ( feed )
2019-11-07 13:40:10 +01:00
}
2020-01-11 22:31:47 +01:00
private let homePageIndexPath = IndexPath ( row : 0 , section : 1 )
2020-02-06 14:27:49 +01:00
private var shouldHideHomePageSection : Bool {
2024-02-26 08:12:21 +01:00
return feed . homePageURL = = nil
2020-02-06 14:27:49 +01:00
}
2020-05-18 02:39:22 +02:00
private var userNotificationSettings : UNNotificationSettings ?
2019-11-07 13:40:10 +01:00
override func viewDidLoad ( ) {
tableView . register ( InspectorIconHeaderView . self , forHeaderFooterViewReuseIdentifier : " SectionHeader " )
2024-02-26 08:12:21 +01:00
navigationItem . title = feed . nameForDisplay
nameTextField . text = feed . nameForDisplay
2019-11-07 13:40:10 +01:00
2024-05-26 08:05:38 +02:00
notifyAboutNewArticlesSwitch . setOn ( feed . shouldSendUserNotificationForNewArticles ? ? false , animated : false )
2021-04-10 03:03:08 +02:00
2024-02-26 08:12:21 +01:00
alwaysShowReaderViewSwitch . setOn ( feed . isArticleExtractorAlwaysOn ? ? false , animated : false )
2019-11-07 13:40:10 +01:00
2024-06-09 19:58:07 +02:00
homePageLabel . text = feed . homePageURL
feedURLLabel . text = feed . url
2019-11-07 13:40:10 +01:00
2024-02-26 08:12:21 +01:00
NotificationCenter . default . addObserver ( self , selector : #selector ( feedIconDidBecomeAvailable ( _ : ) ) , name : . FeedIconDidBecomeAvailable , object : nil )
2020-05-18 02:39:22 +02:00
2020-05-18 03:23:42 +02:00
NotificationCenter . default . addObserver ( self , selector : #selector ( updateNotificationSettings ) , name : UIApplication . willEnterForegroundNotification , object : nil )
2020-05-18 02:39:22 +02:00
}
override func viewDidAppear ( _ animated : Bool ) {
updateNotificationSettings ( )
2019-11-07 13:40:10 +01:00
}
override func viewDidDisappear ( _ animated : Bool ) {
2024-02-26 08:12:21 +01:00
if nameTextField . text != feed . nameForDisplay {
2019-11-07 13:40:10 +01:00
let nameText = nameTextField . text ? ? " "
2024-02-26 08:12:21 +01:00
let newName = nameText . isEmpty ? ( feed . name ? ? NSLocalizedString ( " Untitled " , comment : " Feed name " ) ) : nameText
2024-03-28 01:49:09 +01:00
Task { @ MainActor in
try ? await feed . rename ( to : newName )
}
2019-11-07 13:40:10 +01:00
}
}
// MARK: N o t i f i c a t i o n s
2024-02-26 08:12:21 +01:00
@objc func feedIconDidBecomeAvailable ( _ notification : Notification ) {
2019-11-07 13:40:10 +01:00
headerView ? . iconView . iconImage = iconImage
}
@IBAction func notifyAboutNewArticlesChanged ( _ sender : Any ) {
2020-05-18 02:39:22 +02:00
guard let settings = userNotificationSettings else {
notifyAboutNewArticlesSwitch . isOn = ! notifyAboutNewArticlesSwitch . isOn
return
}
if settings . authorizationStatus = = . denied {
notifyAboutNewArticlesSwitch . isOn = ! notifyAboutNewArticlesSwitch . isOn
present ( notificationUpdateErrorAlert ( ) , animated : true , completion : nil )
} else if settings . authorizationStatus = = . authorized {
2024-05-26 08:05:38 +02:00
feed . shouldSendUserNotificationForNewArticles = notifyAboutNewArticlesSwitch . isOn
2020-05-18 02:39:22 +02:00
} else {
UNUserNotificationCenter . current ( ) . requestAuthorization ( options : [ . badge , . sound , . alert ] ) { ( granted , error ) in
self . updateNotificationSettings ( )
if granted {
DispatchQueue . main . async {
2024-05-26 08:05:38 +02:00
self . feed . shouldSendUserNotificationForNewArticles = self . notifyAboutNewArticlesSwitch . isOn
2020-05-18 02:39:22 +02:00
UIApplication . shared . registerForRemoteNotifications ( )
}
} else {
DispatchQueue . main . async {
self . notifyAboutNewArticlesSwitch . isOn = ! self . notifyAboutNewArticlesSwitch . isOn
}
}
}
}
2019-11-07 13:40:10 +01:00
}
@IBAction func alwaysShowReaderViewChanged ( _ sender : Any ) {
2024-02-26 08:12:21 +01:00
feed . isArticleExtractorAlwaysOn = alwaysShowReaderViewSwitch . isOn
2019-11-07 13:40:10 +01:00
}
@IBAction func done ( _ sender : Any ) {
dismiss ( animated : true )
}
2020-02-06 14:27:49 +01:00
// / R e t u r n s a n e w i n d e x P a t h , t a k i n g i n t o c o n s i d e r a t i o n a n y
// / c o n d i t i o n s t h a t m a y r e q u i r e t h e t a b l e V i e w t o b e
// / d i s p l a y e d d i f f e r e n t l y t h a n w h a t i s s e t u p i n t h e s t o r y b o a r d .
private func shift ( _ indexPath : IndexPath ) -> IndexPath {
return IndexPath ( row : indexPath . row , section : shift ( indexPath . section ) )
}
// / R e t u r n s a n e w s e c t i o n , t a k i n g i n t o c o n s i d e r a t i o n a n y
// / c o n d i t i o n s t h a t m a y r e q u i r e t h e t a b l e V i e w t o b e
// / d i s p l a y e d d i f f e r e n t l y t h a n w h a t i s s e t u p i n t h e s t o r y b o a r d .
private func shift ( _ section : Int ) -> Int {
if section >= homePageIndexPath . section && shouldHideHomePageSection {
return section + 1
}
return section
}
2019-11-07 13:40:10 +01:00
}
// MARK: T a b l e V i e w
2024-02-26 08:12:21 +01:00
extension FeedInspectorViewController {
2020-02-06 14:27:49 +01:00
override func numberOfSections ( in tableView : UITableView ) -> Int {
let numberOfSections = super . numberOfSections ( in : tableView )
return shouldHideHomePageSection ? numberOfSections - 1 : numberOfSections
}
override func tableView ( _ tableView : UITableView , numberOfRowsInSection section : Int ) -> Int {
return super . tableView ( tableView , numberOfRowsInSection : shift ( section ) )
}
2019-11-07 13:40:10 +01:00
override func tableView ( _ tableView : UITableView , heightForHeaderInSection section : Int ) -> CGFloat {
2020-02-06 14:27:49 +01:00
return section = = 0 ? ImageHeaderView . rowHeight : super . tableView ( tableView , heightForHeaderInSection : shift ( section ) )
}
override func tableView ( _ tableView : UITableView , cellForRowAt indexPath : IndexPath ) -> UITableViewCell {
2021-04-19 05:10:57 +02:00
let cell = super . tableView ( tableView , cellForRowAt : shift ( indexPath ) )
if indexPath . section = = 0 && indexPath . row = = 1 {
guard let label = cell . contentView . subviews . filter ( { $0 . isKind ( of : UILabel . self ) } ) [ 0 ] as ? UILabel else {
return cell
}
label . numberOfLines = 2
2024-02-26 08:12:21 +01:00
label . text = feed . notificationDisplayName . capitalized
2021-04-19 05:10:57 +02:00
}
return cell
2020-02-06 14:27:49 +01:00
}
override func tableView ( _ tableView : UITableView , titleForHeaderInSection section : Int ) -> String ? {
super . tableView ( tableView , titleForHeaderInSection : shift ( section ) )
2019-11-07 13:40:10 +01:00
}
override func tableView ( _ tableView : UITableView , viewForHeaderInSection section : Int ) -> UIView ? {
2020-02-06 14:27:49 +01:00
if shift ( section ) = = 0 {
2019-11-07 13:40:10 +01:00
headerView = tableView . dequeueReusableHeaderFooterView ( withIdentifier : " SectionHeader " ) as ? InspectorIconHeaderView
headerView ? . iconView . iconImage = iconImage
return headerView
} else {
2020-02-06 14:27:49 +01:00
return super . tableView ( tableView , viewForHeaderInSection : shift ( section ) )
2019-11-07 13:40:10 +01:00
}
}
2020-01-11 22:31:47 +01:00
override func tableView ( _ tableView : UITableView , didSelectRowAt indexPath : IndexPath ) {
2020-02-06 14:27:49 +01:00
if shift ( indexPath ) = = homePageIndexPath ,
2024-02-26 08:12:21 +01:00
let homePageUrlString = feed . homePageURL ,
2020-01-11 22:31:47 +01:00
let homePageUrl = URL ( string : homePageUrlString ) {
let safari = SFSafariViewController ( url : homePageUrl )
2020-01-12 22:29:32 +01:00
safari . modalPresentationStyle = . pageSheet
2020-01-12 22:53:08 +01:00
present ( safari , animated : true ) {
tableView . deselectRow ( at : indexPath , animated : true )
}
2020-01-11 22:31:47 +01:00
}
}
2019-11-07 13:40:10 +01:00
}
// MARK: U I T e x t F i e l d D e l e g a t e
2024-02-26 08:12:21 +01:00
extension FeedInspectorViewController : UITextFieldDelegate {
2019-11-07 13:40:10 +01:00
func textFieldShouldReturn ( _ textField : UITextField ) -> Bool {
textField . resignFirstResponder ( )
return true
}
}
2020-05-18 02:39:22 +02:00
// MARK: U N U s e r N o t i f i c a t i o n C e n t e r
2024-02-26 08:12:21 +01:00
extension FeedInspectorViewController {
2020-05-18 02:39:22 +02:00
2020-05-18 03:23:42 +02:00
@objc
2020-05-18 02:39:22 +02:00
func updateNotificationSettings ( ) {
UNUserNotificationCenter . current ( ) . getNotificationSettings { ( settings ) in
DispatchQueue . main . async {
self . userNotificationSettings = settings
if settings . authorizationStatus = = . authorized {
UIApplication . shared . registerForRemoteNotifications ( )
}
}
}
}
func notificationUpdateErrorAlert ( ) -> UIAlertController {
let alert = UIAlertController ( title : NSLocalizedString ( " Enable Notifications " , comment : " Notifications " ) ,
message : NSLocalizedString ( " Notifications need to be enabled in the Settings app. " , comment : " Notifications need to be enabled in the Settings app. " ) , preferredStyle : . alert )
let openSettings = UIAlertAction ( title : NSLocalizedString ( " Open Settings " , comment : " Open Settings " ) , style : . default ) { ( action ) in
UIApplication . shared . open ( URL ( string : UIApplication . openSettingsURLString ) ! , options : [ UIApplication . OpenExternalURLOptionsKey . universalLinksOnly : false ] , completionHandler : nil )
}
let dismiss = UIAlertAction ( title : NSLocalizedString ( " Dismiss " , comment : " Dismiss " ) , style : . cancel , handler : nil )
alert . addAction ( openSettings )
alert . addAction ( dismiss )
2021-01-12 02:57:14 +01:00
alert . preferredAction = openSettings
2020-05-18 02:39:22 +02:00
return alert
}
}