2019-10-21 18:51:33 +02:00
//
// S e t t i n g s V i e w C o n t r o l l e r . s w i f t
// 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 4 / 2 4 / 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-21 20:58:05 +01:00
import CoreServices
2019-10-22 00:52:29 +02:00
import SafariServices
2019-10-21 18:51:33 +02:00
class SettingsViewController : UITableViewController {
2019-10-22 01:02:44 +02:00
private let appNewsURLString = " https://nnw.ranchero.com/feed.json "
2019-10-22 17:32:35 +02:00
private weak var opmlAccount : Account ?
2019-10-21 18:51:33 +02:00
@IBOutlet weak var timelineSortOrderSwitch : UISwitch !
2019-10-21 23:42:58 +02:00
@IBOutlet weak var groupByFeedSwitch : UISwitch !
2020-01-11 02:14:21 +01:00
@IBOutlet weak var refreshClearsReadArticlesSwitch : UISwitch !
2020-01-11 19:30:16 +01:00
@IBOutlet weak var confirmMarkAllAsReadSwitch : UISwitch !
2019-11-24 21:18:58 +01:00
@IBOutlet weak var showFullscreenArticlesSwitch : UISwitch !
2020-03-15 10:25:25 +01:00
@IBOutlet weak var colorPaletteDetailLabel : UILabel !
2019-10-21 18:51:33 +02:00
2020-01-11 19:30:16 +01:00
var scrollToArticlesSection = false
2019-10-21 18:51:33 +02:00
weak var presentingParentController : UIViewController ?
override func viewDidLoad ( ) {
// T h i s h a c k m o s t l y w o r k s a r o u n d a b u g i n s t a t i c t a b l e s w i t h d y n a m i c t y p e . S e e : h t t p s : / / s p i n . a t o m i c o b j e c t . c o m / 2 0 1 8 / 1 0 / 1 5 / d y n a m i c - t y p e - s t a t i c - u i t a b l e v i e w /
NotificationCenter . default . removeObserver ( tableView ! , name : UIContentSizeCategory . didChangeNotification , object : nil )
NotificationCenter . default . addObserver ( self , selector : #selector ( contentSizeCategoryDidChange ) , name : UIContentSizeCategory . didChangeNotification , object : nil )
2019-10-23 02:20:35 +02:00
NotificationCenter . default . addObserver ( self , selector : #selector ( accountsDidChange ) , name : . UserDidAddAccount , object : nil )
NotificationCenter . default . addObserver ( self , selector : #selector ( accountsDidChange ) , name : . UserDidDeleteAccount , object : nil )
2019-10-24 02:58:18 +02:00
NotificationCenter . default . addObserver ( self , selector : #selector ( displayNameDidChange ) , name : . DisplayNameDidChange , object : nil )
2020-04-16 15:25:40 +02:00
NotificationCenter . default . addObserver ( self , selector : #selector ( activeExtensionPointsDidChange ) , name : . ActiveExtensionPointsDidChange , object : nil )
2019-10-23 02:20:35 +02:00
2020-04-16 15:25:40 +02:00
tableView . register ( UINib ( nibName : " SettingsComboTableViewCell " , bundle : nil ) , forCellReuseIdentifier : " SettingsComboTableViewCell " )
2019-10-21 18:51:33 +02:00
tableView . register ( UINib ( nibName : " SettingsTableViewCell " , bundle : nil ) , forCellReuseIdentifier : " SettingsTableViewCell " )
2020-01-11 19:30:16 +01:00
2020-03-12 17:56:43 +01:00
tableView . rowHeight = UITableView . automaticDimension
tableView . estimatedRowHeight = 44
2019-10-21 18:51:33 +02:00
}
override func viewWillAppear ( _ animated : Bool ) {
super . viewWillAppear ( animated )
2020-07-02 04:47:45 +02:00
if AppDefaults . shared . timelineSortDirection = = . orderedAscending {
2019-10-21 18:51:33 +02:00
timelineSortOrderSwitch . isOn = true
} else {
timelineSortOrderSwitch . isOn = false
}
2020-07-02 04:47:45 +02:00
if AppDefaults . shared . timelineGroupByFeed {
2019-10-21 23:42:58 +02:00
groupByFeedSwitch . isOn = true
} else {
groupByFeedSwitch . isOn = false
}
2020-07-02 04:47:45 +02:00
if AppDefaults . shared . refreshClearsReadArticles {
2020-01-11 02:14:21 +01:00
refreshClearsReadArticlesSwitch . isOn = true
} else {
refreshClearsReadArticlesSwitch . isOn = false
}
2020-07-02 04:47:45 +02:00
if AppDefaults . shared . confirmMarkAllAsRead {
2020-01-11 19:30:16 +01:00
confirmMarkAllAsReadSwitch . isOn = true
} else {
confirmMarkAllAsReadSwitch . isOn = false
}
2020-07-02 04:47:45 +02:00
if AppDefaults . shared . articleFullscreenAvailable {
2019-11-24 21:18:58 +01:00
showFullscreenArticlesSwitch . isOn = true
} else {
showFullscreenArticlesSwitch . isOn = false
}
2020-03-15 10:25:25 +01:00
colorPaletteDetailLabel . text = String ( describing : AppDefaults . userInterfaceColorPalette )
2019-11-24 21:18:58 +01:00
2019-11-26 17:16:58 +01:00
let buildLabel = NonIntrinsicLabel ( frame : CGRect ( x : 32.0 , y : 0.0 , width : 0.0 , height : 0.0 ) )
2019-10-21 18:51:33 +02:00
buildLabel . font = UIFont . systemFont ( ofSize : 11.0 )
buildLabel . textColor = UIColor . gray
2019-11-24 18:25:42 +01:00
buildLabel . text = " \( Bundle . main . appName ) \( Bundle . main . versionNumber ) (Build \( Bundle . main . buildNumber ) ) "
2019-10-21 18:51:33 +02:00
buildLabel . sizeToFit ( )
buildLabel . translatesAutoresizingMaskIntoConstraints = false
2019-10-31 01:47:28 +01:00
let wrapperView = UIView ( frame : CGRect ( x : 0 , y : 0 , width : buildLabel . frame . width , height : buildLabel . frame . height + 10.0 ) )
wrapperView . translatesAutoresizingMaskIntoConstraints = false
wrapperView . addSubview ( buildLabel )
tableView . tableFooterView = wrapperView
2019-10-21 18:51:33 +02:00
2019-10-23 02:20:35 +02:00
}
override func viewDidAppear ( _ animated : Bool ) {
super . viewDidAppear ( animated )
self . tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2020-01-11 19:30:16 +01:00
if scrollToArticlesSection {
tableView . scrollToRow ( at : IndexPath ( row : 0 , section : 4 ) , at : . top , animated : true )
scrollToArticlesSection = false
}
2019-10-21 18:51:33 +02:00
}
// MARK: U I T a b l e V i e w
override func tableView ( _ tableView : UITableView , numberOfRowsInSection section : Int ) -> Int {
2019-11-24 21:18:58 +01:00
2020-01-20 07:12:02 +01:00
switch section {
2019-10-21 18:51:33 +02:00
case 1 :
2019-10-22 15:43:39 +02:00
return AccountManager . shared . accounts . count + 1
2019-10-30 17:51:01 +01:00
case 2 :
2020-04-16 15:25:40 +02:00
return ExtensionPointManager . shared . activeExtensionPoints . count + 1
case 3 :
2020-01-20 07:12:02 +01:00
let defaultNumberOfRows = super . tableView ( tableView , numberOfRowsInSection : section )
2019-10-22 15:43:39 +02:00
if AccountManager . shared . activeAccounts . isEmpty || AccountManager . shared . anyAccountHasFeedWithURL ( appNewsURLString ) {
2019-10-22 01:02:44 +02:00
return defaultNumberOfRows - 1
}
return defaultNumberOfRows
2020-04-16 15:25:40 +02:00
case 5 :
2020-01-20 07:12:02 +01:00
return traitCollection . userInterfaceIdiom = = . phone ? 2 : 1
2019-10-21 18:51:33 +02:00
default :
2020-01-20 07:12:02 +01:00
return super . tableView ( tableView , numberOfRowsInSection : section )
2019-10-21 18:51:33 +02:00
}
}
override func tableView ( _ tableView : UITableView , cellForRowAt indexPath : IndexPath ) -> UITableViewCell {
2019-11-24 21:18:58 +01:00
2019-10-21 18:51:33 +02:00
let cell : UITableViewCell
2020-01-20 07:12:02 +01:00
switch indexPath . section {
2019-10-22 15:43:39 +02:00
case 1 :
2019-10-23 17:35:53 +02:00
2019-10-21 18:51:33 +02:00
let sortedAccounts = AccountManager . shared . sortedAccounts
if indexPath . row = = sortedAccounts . count {
2019-10-23 17:35:53 +02:00
cell = tableView . dequeueReusableCell ( withIdentifier : " SettingsTableViewCell " , for : indexPath )
2019-10-21 18:51:33 +02:00
cell . textLabel ? . text = NSLocalizedString ( " Add Account " , comment : " Accounts " )
} else {
2020-04-16 15:25:40 +02:00
let acctCell = tableView . dequeueReusableCell ( withIdentifier : " SettingsComboTableViewCell " , for : indexPath ) as ! SettingsComboTableViewCell
2019-10-23 18:47:21 +02:00
acctCell . applyThemeProperties ( )
2019-10-23 17:35:53 +02:00
let account = sortedAccounts [ indexPath . row ]
2020-04-16 15:25:40 +02:00
acctCell . comboImage ? . image = AppAssets . image ( for : account . type )
acctCell . comboNameLabel ? . text = account . nameForDisplay
cell = acctCell
}
case 2 :
let extensionPoints = Array ( ExtensionPointManager . shared . activeExtensionPoints . values )
if indexPath . row = = extensionPoints . count {
cell = tableView . dequeueReusableCell ( withIdentifier : " SettingsTableViewCell " , for : indexPath )
cell . textLabel ? . text = NSLocalizedString ( " Add Extension " , comment : " Extensions " )
} else {
let acctCell = tableView . dequeueReusableCell ( withIdentifier : " SettingsComboTableViewCell " , for : indexPath ) as ! SettingsComboTableViewCell
acctCell . applyThemeProperties ( )
let extensionPoint = extensionPoints [ indexPath . row ]
acctCell . comboImage ? . image = extensionPoint . templateImage
acctCell . comboNameLabel ? . text = extensionPoint . title
2019-10-23 17:35:53 +02:00
cell = acctCell
2019-10-21 18:51:33 +02:00
}
2019-11-03 01:57:01 +01:00
2019-10-21 18:51:33 +02:00
default :
2020-01-20 07:12:02 +01:00
cell = super . tableView ( tableView , cellForRowAt : indexPath )
2019-10-21 18:51:33 +02:00
}
return cell
}
override func tableView ( _ tableView : UITableView , didSelectRowAt indexPath : IndexPath ) {
2019-11-24 21:18:58 +01:00
2020-01-20 07:12:02 +01:00
switch indexPath . section {
2019-10-21 18:51:33 +02:00
case 0 :
2019-10-22 15:43:39 +02:00
UIApplication . shared . open ( URL ( string : " \( UIApplication . openSettingsURLString ) " ) ! )
2019-10-23 02:20:35 +02:00
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-22 15:43:39 +02:00
case 1 :
2019-10-21 18:51:33 +02:00
let sortedAccounts = AccountManager . shared . sortedAccounts
if indexPath . row = = sortedAccounts . count {
let controller = UIStoryboard . settings . instantiateController ( ofType : AddAccountViewController . self )
self . navigationController ? . pushViewController ( controller , animated : true )
} else {
2019-10-24 02:58:18 +02:00
let controller = UIStoryboard . inspector . instantiateController ( ofType : AccountInspectorViewController . self )
2019-10-21 18:51:33 +02:00
controller . account = sortedAccounts [ indexPath . row ]
self . navigationController ? . pushViewController ( controller , animated : true )
}
2019-10-30 17:51:01 +01:00
case 2 :
2020-04-16 15:25:40 +02:00
let extensionPoints = Array ( ExtensionPointManager . shared . activeExtensionPoints . values )
if indexPath . row = = extensionPoints . count {
let controller = UIStoryboard . settings . instantiateController ( ofType : AddExtensionPointViewController . self )
self . navigationController ? . pushViewController ( controller , animated : true )
} else {
let controller = UIStoryboard . inspector . instantiateController ( ofType : ExtensionPointInspectorViewController . self )
controller . extensionPoint = extensionPoints [ indexPath . row ]
self . navigationController ? . pushViewController ( controller , animated : true )
}
case 3 :
2019-10-21 23:27:54 +02:00
switch indexPath . row {
case 0 :
2019-10-23 02:20:35 +02:00
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-22 17:32:35 +02:00
if let sourceView = tableView . cellForRow ( at : indexPath ) {
let sourceRect = tableView . rectForRow ( at : indexPath )
importOPML ( sourceView : sourceView , sourceRect : sourceRect )
}
2019-11-14 00:13:06 +01:00
case 1 :
2019-10-23 02:20:35 +02:00
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-22 17:32:35 +02:00
if let sourceView = tableView . cellForRow ( at : indexPath ) {
let sourceRect = tableView . rectForRow ( at : indexPath )
exportOPML ( sourceView : sourceView , sourceRect : sourceRect )
}
2019-11-14 00:13:06 +01:00
case 2 :
2019-10-30 17:51:01 +01:00
addFeed ( )
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-21 23:27:54 +02:00
default :
2019-10-21 23:42:58 +02:00
break
2019-10-21 23:27:54 +02:00
}
2020-04-16 15:25:40 +02:00
case 4 :
2019-11-09 00:16:09 +01:00
switch indexPath . row {
2020-01-16 22:44:30 +01:00
case 3 :
2019-11-09 00:16:09 +01:00
let timeline = UIStoryboard . settings . instantiateController ( ofType : TimelineCustomizerViewController . self )
self . navigationController ? . pushViewController ( timeline , animated : true )
default :
break
}
2020-04-16 15:25:40 +02:00
case 6 :
2020-03-15 10:25:25 +01:00
let colorPalette = UIStoryboard . settings . instantiateController ( ofType : ColorPaletteTableViewController . self )
self . navigationController ? . pushViewController ( colorPalette , animated : true )
2020-04-16 15:25:40 +02:00
case 7 :
2019-10-21 18:51:33 +02:00
switch indexPath . row {
case 0 :
2019-11-24 18:33:01 +01:00
openURL ( " https://ranchero.com/netnewswire/help/ios/5.0/en/ " )
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-21 18:51:33 +02:00
case 1 :
2019-10-22 00:52:29 +02:00
openURL ( " https://ranchero.com/netnewswire/ " )
2019-10-23 02:20:35 +02:00
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-21 18:51:33 +02:00
case 2 :
2020-07-26 11:46:27 +02:00
openURL ( " https://github.com/brentsimmons/NetNewsWire/blob/main/Technotes/HowToSupportNetNewsWire.markdown " )
2019-10-23 02:20:35 +02:00
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-21 18:51:33 +02:00
case 3 :
2019-10-22 00:52:29 +02:00
openURL ( " https://github.com/brentsimmons/NetNewsWire " )
2019-10-23 02:20:35 +02:00
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-21 18:51:33 +02:00
case 4 :
2019-10-22 00:52:29 +02:00
openURL ( " https://github.com/brentsimmons/NetNewsWire/issues " )
2019-10-23 02:20:35 +02:00
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-21 18:51:33 +02:00
case 5 :
2020-07-26 11:46:27 +02:00
openURL ( " https://github.com/brentsimmons/NetNewsWire/tree/main/Technotes " )
2019-10-23 02:20:35 +02:00
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-11-24 18:33:01 +01:00
case 6 :
2019-11-27 21:17:57 +01:00
openURL ( " https://ranchero.com/netnewswire/slack " )
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
case 7 :
2019-11-24 18:33:01 +01:00
let timeline = UIStoryboard . settings . instantiateController ( ofType : AboutViewController . self )
self . navigationController ? . pushViewController ( timeline , animated : true )
2019-10-21 18:51:33 +02:00
default :
2019-10-22 00:52:29 +02:00
break
2019-10-21 18:51:33 +02:00
}
default :
2019-10-23 02:20:35 +02:00
tableView . selectRow ( at : nil , animated : true , scrollPosition : . none )
2019-10-21 18:51:33 +02:00
}
}
override func tableView ( _ tableView : UITableView , canEditRowAt indexPath : IndexPath ) -> Bool {
return false
}
override func tableView ( _ tableView : UITableView , canMoveRowAt indexPath : IndexPath ) -> Bool {
return false
}
override func tableView ( _ tableView : UITableView , editingStyleForRowAt indexPath : IndexPath ) -> UITableViewCell . EditingStyle {
return . none
}
override func tableView ( _ tableView : UITableView , heightForRowAt indexPath : IndexPath ) -> CGFloat {
2020-03-12 17:56:43 +01:00
return UITableView . automaticDimension
2019-10-21 18:51:33 +02:00
}
override func tableView ( _ tableView : UITableView , indentationLevelForRowAt indexPath : IndexPath ) -> Int {
2019-11-24 21:18:58 +01:00
return super . tableView ( tableView , indentationLevelForRowAt : IndexPath ( row : 0 , section : 1 ) )
2019-10-21 18:51:33 +02:00
}
// MARK: A c t i o n s
@IBAction func done ( _ sender : Any ) {
dismiss ( animated : true )
}
@IBAction func switchTimelineOrder ( _ sender : Any ) {
if timelineSortOrderSwitch . isOn {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . timelineSortDirection = . orderedAscending
2019-10-21 18:51:33 +02:00
} else {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . timelineSortDirection = . orderedDescending
2019-10-21 18:51:33 +02:00
}
}
2019-10-21 23:42:58 +02:00
@IBAction func switchGroupByFeed ( _ sender : Any ) {
if groupByFeedSwitch . isOn {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . timelineGroupByFeed = true
2019-10-21 23:42:58 +02:00
} else {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . timelineGroupByFeed = false
2019-10-21 23:42:58 +02:00
}
}
2020-01-11 02:14:21 +01:00
@IBAction func switchClearsReadArticles ( _ sender : Any ) {
if refreshClearsReadArticlesSwitch . isOn {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . refreshClearsReadArticles = true
2020-01-11 02:14:21 +01:00
} else {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . refreshClearsReadArticles = false
2020-01-11 02:14:21 +01:00
}
}
2020-01-11 19:30:16 +01:00
@IBAction func switchConfirmMarkAllAsRead ( _ sender : Any ) {
if confirmMarkAllAsReadSwitch . isOn {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . confirmMarkAllAsRead = true
2020-01-11 19:30:16 +01:00
} else {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . confirmMarkAllAsRead = false
2020-01-11 19:30:16 +01:00
}
}
2019-11-24 21:18:58 +01:00
@IBAction func switchFullscreenArticles ( _ sender : Any ) {
if showFullscreenArticlesSwitch . isOn {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . articleFullscreenAvailable = true
2019-11-24 21:18:58 +01:00
} else {
2020-07-02 04:47:45 +02:00
AppDefaults . shared . articleFullscreenAvailable = false
2019-11-24 21:18:58 +01:00
}
}
2019-10-23 02:20:35 +02:00
// MARK: N o t i f i c a t i o n s
2019-10-21 18:51:33 +02:00
@objc func contentSizeCategoryDidChange ( ) {
tableView . reloadData ( )
}
2019-10-23 02:20:35 +02:00
@objc func accountsDidChange ( ) {
tableView . reloadData ( )
}
2019-10-24 02:58:18 +02:00
@objc func displayNameDidChange ( ) {
tableView . reloadData ( )
}
2019-11-03 01:57:01 +01:00
2020-04-16 15:25:40 +02:00
@objc func activeExtensionPointsDidChange ( ) {
tableView . reloadData ( )
}
2019-10-21 18:51:33 +02:00
}
// MARK: O P M L D o c u m e n t P i c k e r
extension SettingsViewController : UIDocumentPickerDelegate {
func documentPicker ( _ controller : UIDocumentPickerViewController , didPickDocumentsAt urls : [ URL ] ) {
for url in urls {
2019-10-30 18:04:39 +01:00
opmlAccount ? . importOPML ( url ) { result in
switch result {
case . success :
break
2020-01-20 22:57:07 +01:00
case . failure :
2019-10-30 18:04:39 +01:00
let title = NSLocalizedString ( " Import Failed " , comment : " Import Failed " )
2020-01-20 22:57:07 +01:00
let message = NSLocalizedString ( " We were unable to process the selected file. Please ensure that it is a properly formatted OPML file. " , comment : " Import Failed Message " )
self . presentError ( title : title , message : message )
2019-10-30 18:04:39 +01:00
}
}
2019-10-21 18:51:33 +02:00
}
}
}
// MARK: P r i v a t e
private extension SettingsViewController {
func addFeed ( ) {
self . dismiss ( animated : true )
let addNavViewController = UIStoryboard . add . instantiateInitialViewController ( ) as ! UINavigationController
let addViewController = addNavViewController . topViewController as ! AddContainerViewController
addNavViewController . modalPresentationStyle = . formSheet
addNavViewController . preferredContentSize = AddContainerViewController . preferredContentSizeForFormSheetDisplay
2019-10-22 01:02:44 +02:00
addViewController . initialControllerType = . feed
2019-10-21 18:51:33 +02:00
addViewController . initialFeed = appNewsURLString
addViewController . initialFeedName = " NetNewsWire News "
presentingParentController ? . present ( addNavViewController , animated : true )
}
2019-10-22 17:32:35 +02:00
func importOPML ( sourceView : UIView , sourceRect : CGRect ) {
switch AccountManager . shared . activeAccounts . count {
case 0 :
presentError ( title : " Error " , message : NSLocalizedString ( " You must have at least one active account. " , comment : " Missing active account " ) )
case 1 :
opmlAccount = AccountManager . shared . activeAccounts . first
importOPMLDocumentPicker ( )
default :
importOPMLAccountPicker ( sourceView : sourceView , sourceRect : sourceRect )
}
}
func importOPMLAccountPicker ( sourceView : UIView , sourceRect : CGRect ) {
2019-11-26 17:23:33 +01:00
let title = NSLocalizedString ( " Choose an account to receive the imported feeds and folders " , comment : " Import Account " )
2019-10-22 17:32:35 +02:00
let alert = UIAlertController ( title : title , message : nil , preferredStyle : . actionSheet )
2019-10-21 18:51:33 +02:00
2019-10-22 17:32:35 +02:00
if let popoverController = alert . popoverPresentationController {
popoverController . sourceView = view
popoverController . sourceRect = sourceRect
}
2019-10-23 00:18:37 +02:00
for account in AccountManager . shared . sortedActiveAccounts {
2019-10-22 17:32:35 +02:00
let action = UIAlertAction ( title : account . nameForDisplay , style : . default ) { [ weak self ] action in
self ? . opmlAccount = account
self ? . importOPMLDocumentPicker ( )
}
alert . addAction ( action )
}
let cancelTitle = NSLocalizedString ( " Cancel " , comment : " Cancel " )
alert . addAction ( UIAlertAction ( title : cancelTitle , style : . cancel ) )
self . present ( alert , animated : true )
}
func importOPMLDocumentPicker ( ) {
2020-01-21 20:58:05 +01:00
let utiArray = UTTypeCreateAllIdentifiersForTag ( kUTTagClassFilenameExtension , " opml " as NSString , nil ) ? . takeRetainedValue ( ) as ? [ String ] ? ? [ String ] ( )
var opmlUTIs = utiArray
. compactMap ( { UTTypeCopyDeclaration ( $0 as NSString ) ? . takeUnretainedValue ( ) as ? [ String : Any ] } )
. reduce ( [ String ] ( ) ) { ( result , dict ) in
return result + dict . values . compactMap ( { $0 as ? String } )
}
opmlUTIs . append ( " public.xml " )
let docPicker = UIDocumentPickerViewController ( documentTypes : opmlUTIs , in : . import )
2019-10-21 18:51:33 +02:00
docPicker . delegate = self
docPicker . modalPresentationStyle = . formSheet
self . present ( docPicker , animated : true )
2019-10-22 17:32:35 +02:00
}
func exportOPML ( sourceView : UIView , sourceRect : CGRect ) {
if AccountManager . shared . accounts . count = = 1 {
2019-12-26 20:35:39 +01:00
opmlAccount = AccountManager . shared . accounts . first !
2019-10-22 17:32:35 +02:00
exportOPMLDocumentPicker ( )
} else {
exportOPMLAccountPicker ( sourceView : sourceView , sourceRect : sourceRect )
}
}
func exportOPMLAccountPicker ( sourceView : UIView , sourceRect : CGRect ) {
2019-11-26 17:21:18 +01:00
let title = NSLocalizedString ( " Choose an account with the subscriptions to export " , comment : " Export Account " )
2019-10-22 17:32:35 +02:00
let alert = UIAlertController ( title : title , message : nil , preferredStyle : . actionSheet )
2019-10-21 18:51:33 +02:00
2019-10-22 17:32:35 +02:00
if let popoverController = alert . popoverPresentationController {
popoverController . sourceView = view
popoverController . sourceRect = sourceRect
}
2019-10-23 00:18:37 +02:00
for account in AccountManager . shared . sortedAccounts {
2019-10-22 17:32:35 +02:00
let action = UIAlertAction ( title : account . nameForDisplay , style : . default ) { [ weak self ] action in
self ? . opmlAccount = account
self ? . exportOPMLDocumentPicker ( )
}
alert . addAction ( action )
}
let cancelTitle = NSLocalizedString ( " Cancel " , comment : " Cancel " )
alert . addAction ( UIAlertAction ( title : cancelTitle , style : . cancel ) )
self . present ( alert , animated : true )
2019-10-21 18:51:33 +02:00
}
2019-10-22 17:32:35 +02:00
func exportOPMLDocumentPicker ( ) {
guard let account = opmlAccount else { return }
2019-10-21 18:51:33 +02:00
2019-10-22 17:32:35 +02:00
let accountName = account . nameForDisplay . replacingOccurrences ( of : " " , with : " " ) . trimmingCharacters ( in : . whitespaces )
let filename = " Subscriptions- \( accountName ) .opml "
2019-10-21 18:51:33 +02:00
let tempFile = FileManager . default . temporaryDirectory . appendingPathComponent ( filename )
2019-10-22 17:32:35 +02:00
let opmlString = OPMLExporter . OPMLString ( with : account , title : filename )
2019-10-21 18:51:33 +02:00
do {
try opmlString . write ( to : tempFile , atomically : true , encoding : String . Encoding . utf8 )
} catch {
self . presentError ( title : " OPML Export Error " , message : error . localizedDescription )
}
let docPicker = UIDocumentPickerViewController ( url : tempFile , in : . exportToService )
docPicker . modalPresentationStyle = . formSheet
self . present ( docPicker , animated : true )
}
2019-10-22 00:52:29 +02:00
func openURL ( _ urlString : String ) {
let vc = SFSafariViewController ( url : URL ( string : urlString ) ! )
vc . modalPresentationStyle = . pageSheet
present ( vc , animated : true )
}
2019-10-21 18:51:33 +02:00
}