mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Fix lint issues.
This commit is contained in:
@@ -15,11 +15,11 @@ class AboutViewController: UITableViewController {
|
||||
@IBOutlet weak var acknowledgmentsTextView: UITextView!
|
||||
@IBOutlet weak var thanksTextView: UITextView!
|
||||
@IBOutlet weak var dedicationTextView: UITextView!
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
|
||||
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
configureCell(file: "About", textView: aboutTextView)
|
||||
configureCell(file: "Credits", textView: creditsTextView)
|
||||
configureCell(file: "Thanks", textView: thanksTextView)
|
||||
@@ -32,7 +32,7 @@ class AboutViewController: UITableViewController {
|
||||
buildLabel.numberOfLines = 0
|
||||
buildLabel.sizeToFit()
|
||||
buildLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
|
||||
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)
|
||||
@@ -42,11 +42,11 @@ class AboutViewController: UITableViewController {
|
||||
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
return UITableView.automaticDimension
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private extension AboutViewController {
|
||||
|
||||
|
||||
func configureCell(file: String, textView: UITextView) {
|
||||
let url = Bundle.main.url(forResource: file, withExtension: "rtf")!
|
||||
let string = try! NSAttributedString(url: url, options: [NSAttributedString.DocumentReadingOptionKey.documentType: NSAttributedString.DocumentType.rtf], documentAttributes: nil)
|
||||
@@ -55,5 +55,5 @@ private extension AboutViewController {
|
||||
textView.adjustsFontForContentSizeCategory = true
|
||||
textView.font = .preferredFont(forTextStyle: .body)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ class AddAccountViewController: UITableViewController, AddAccountDismissDelegate
|
||||
case icloud
|
||||
case web
|
||||
case selfhosted
|
||||
|
||||
|
||||
var sectionHeader: String {
|
||||
switch self {
|
||||
case .local:
|
||||
@@ -34,7 +34,7 @@ class AddAccountViewController: UITableViewController, AddAccountDismissDelegate
|
||||
return NSLocalizedString("Self-hosted", comment: "Self hosted Account")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var sectionFooter: String {
|
||||
switch self {
|
||||
case .local:
|
||||
@@ -47,7 +47,7 @@ class AddAccountViewController: UITableViewController, AddAccountDismissDelegate
|
||||
return NSLocalizedString("Self-hosted accounts sync your feeds across all your devices", comment: "Self hosted Account")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var sectionContent: [AccountType] {
|
||||
switch self {
|
||||
case .local:
|
||||
@@ -65,35 +65,31 @@ class AddAccountViewController: UITableViewController, AddAccountDismissDelegate
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
}
|
||||
|
||||
override func numberOfSections(in tableView: UITableView) -> Int {
|
||||
return AddAccountSections.allCases.count
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
if section == AddAccountSections.local.rawValue {
|
||||
return AddAccountSections.local.sectionContent.count
|
||||
}
|
||||
|
||||
|
||||
if section == AddAccountSections.icloud.rawValue {
|
||||
return AddAccountSections.icloud.sectionContent.count
|
||||
}
|
||||
|
||||
|
||||
if section == AddAccountSections.web.rawValue {
|
||||
return AddAccountSections.web.sectionContent.count
|
||||
}
|
||||
|
||||
|
||||
if section == AddAccountSections.selfhosted.rawValue {
|
||||
return AddAccountSections.selfhosted.sectionContent.count
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
|
||||
switch section {
|
||||
case AddAccountSections.local.rawValue:
|
||||
@@ -108,7 +104,7 @@ class AddAccountViewController: UITableViewController, AddAccountDismissDelegate
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
|
||||
switch section {
|
||||
case AddAccountSections.local.rawValue:
|
||||
@@ -123,10 +119,10 @@ class AddAccountViewController: UITableViewController, AddAccountDismissDelegate
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "SettingsAccountTableViewCell", for: indexPath) as! SettingsComboTableViewCell
|
||||
|
||||
|
||||
switch indexPath.section {
|
||||
case AddAccountSections.local.rawValue:
|
||||
cell.comboNameLabel?.text = AddAccountSections.local.sectionContent[indexPath.row].localizedAccountName()
|
||||
@@ -149,15 +145,15 @@ class AddAccountViewController: UITableViewController, AddAccountDismissDelegate
|
||||
case AddAccountSections.selfhosted.rawValue:
|
||||
cell.comboNameLabel?.text = AddAccountSections.selfhosted.sectionContent[indexPath.row].localizedAccountName()
|
||||
cell.comboImage?.image = AppAssets.image(for: AddAccountSections.selfhosted.sectionContent[indexPath.row])
|
||||
|
||||
|
||||
default:
|
||||
return cell
|
||||
}
|
||||
return cell
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
|
||||
|
||||
switch indexPath.section {
|
||||
case AddAccountSections.local.rawValue:
|
||||
let type = AddAccountSections.local.sectionContent[indexPath.row]
|
||||
@@ -175,7 +171,7 @@ class AddAccountViewController: UITableViewController, AddAccountDismissDelegate
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func presentController(for accountType: AccountType) {
|
||||
switch accountType {
|
||||
case .onMyMac:
|
||||
@@ -216,18 +212,18 @@ class AddAccountViewController: UITableViewController, AddAccountDismissDelegate
|
||||
present(navController, animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func dismiss() {
|
||||
navigationController?.popViewController(animated: false)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension AddAccountViewController: OAuthAccountAuthorizationOperationDelegate {
|
||||
|
||||
|
||||
func oauthAccountAuthorizationOperation(_ operation: OAuthAccountAuthorizationOperation, didCreate account: Account) {
|
||||
let rootViewController = view.window?.rootViewController
|
||||
|
||||
|
||||
account.refreshAll { result in
|
||||
switch result {
|
||||
case .success:
|
||||
@@ -239,10 +235,10 @@ extension AddAccountViewController: OAuthAccountAuthorizationOperationDelegate {
|
||||
viewController.presentError(error)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dismiss()
|
||||
}
|
||||
|
||||
|
||||
func oauthAccountAuthorizationOperation(_ operation: OAuthAccountAuthorizationOperation, didFailWith error: Error) {
|
||||
presentError(error)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
import UIKit
|
||||
|
||||
struct ArticleThemeImporter {
|
||||
|
||||
|
||||
static func importTheme(controller: UIViewController, url: URL) throws {
|
||||
let theme = try ArticleTheme(url: url, isAppTheme: false)
|
||||
|
||||
@@ -20,13 +20,13 @@ struct ArticleThemeImporter {
|
||||
let message = NSString.localizedStringWithFormat(localizedMessageText as NSString, theme.creatorHomePage) as String
|
||||
|
||||
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
|
||||
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel")
|
||||
alertController.addAction(UIAlertAction(title: cancelTitle, style: .cancel))
|
||||
|
||||
|
||||
if let websiteURL = URL(string: theme.creatorHomePage) {
|
||||
let visitSiteTitle = NSLocalizedString("Show Website", comment: "Show Website")
|
||||
let visitSiteAction = UIAlertAction(title: visitSiteTitle, style: .default) { action in
|
||||
let visitSiteAction = UIAlertAction(title: visitSiteTitle, style: .default) { _ in
|
||||
UIApplication.shared.open(websiteURL)
|
||||
try? Self.importTheme(controller: controller, url: url)
|
||||
}
|
||||
@@ -49,7 +49,7 @@ struct ArticleThemeImporter {
|
||||
}
|
||||
|
||||
let installThemeTitle = NSLocalizedString("Install Theme", comment: "Install Theme")
|
||||
let installThemeAction = UIAlertAction(title: installThemeTitle, style: .default) { action in
|
||||
let installThemeAction = UIAlertAction(title: installThemeTitle, style: .default) { _ in
|
||||
|
||||
if ArticleThemesManager.shared.themeExists(filename: url.path) {
|
||||
let title = NSLocalizedString("Duplicate Theme", comment: "Duplicate Theme")
|
||||
@@ -61,7 +61,7 @@ struct ArticleThemeImporter {
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel")
|
||||
alertController.addAction(UIAlertAction(title: cancelTitle, style: .cancel))
|
||||
|
||||
let overwriteAction = UIAlertAction(title: NSLocalizedString("Overwrite", comment: "Overwrite"), style: .default) { action in
|
||||
let overwriteAction = UIAlertAction(title: NSLocalizedString("Overwrite", comment: "Overwrite"), style: .default) { _ in
|
||||
importTheme()
|
||||
}
|
||||
alertController.addAction(overwriteAction)
|
||||
@@ -71,32 +71,32 @@ struct ArticleThemeImporter {
|
||||
} else {
|
||||
importTheme()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
alertController.addAction(installThemeAction)
|
||||
alertController.preferredAction = installThemeAction
|
||||
|
||||
controller.present(alertController, animated: true)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private extension ArticleThemeImporter {
|
||||
|
||||
|
||||
static func confirmImportSuccess(controller: UIViewController, themeName: String) {
|
||||
let title = NSLocalizedString("Theme installed", comment: "Theme installed")
|
||||
|
||||
|
||||
let localizedMessageText = NSLocalizedString("The theme “%@” has been installed.", comment: "Theme installed")
|
||||
let message = NSString.localizedStringWithFormat(localizedMessageText as NSString, themeName) as String
|
||||
|
||||
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
|
||||
|
||||
let doneTitle = NSLocalizedString("Done", comment: "Done")
|
||||
alertController.addAction(UIAlertAction(title: doneTitle, style: .default))
|
||||
|
||||
|
||||
controller.present(alertController, animated: true)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,15 +17,15 @@ extension UTType {
|
||||
class ArticleThemesTableViewController: UITableViewController {
|
||||
|
||||
override func viewDidLoad() {
|
||||
let importBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(importTheme(_:)));
|
||||
importBarButtonItem.title = NSLocalizedString("Import Theme", comment: "Import Theme");
|
||||
let importBarButtonItem = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(importTheme(_:)))
|
||||
importBarButtonItem.title = NSLocalizedString("Import Theme", comment: "Import Theme")
|
||||
navigationItem.rightBarButtonItem = importBarButtonItem
|
||||
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(articleThemeNamesDidChangeNotification(_:)), name: .ArticleThemeNamesDidChangeNotification, object: nil)
|
||||
}
|
||||
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
|
||||
@objc func articleThemeNamesDidChangeNotification(_ note: Notification) {
|
||||
tableView.reloadData()
|
||||
}
|
||||
@@ -49,21 +49,21 @@ class ArticleThemesTableViewController: UITableViewController {
|
||||
|
||||
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
|
||||
|
||||
|
||||
let themeName: String
|
||||
if indexPath.row == 0 {
|
||||
themeName = ArticleTheme.defaultTheme.name
|
||||
} else {
|
||||
themeName = ArticleThemesManager.shared.themeNames[indexPath.row - 1]
|
||||
}
|
||||
|
||||
|
||||
cell.textLabel?.text = themeName
|
||||
if themeName == ArticleThemesManager.shared.currentTheme.name {
|
||||
cell.accessoryType = .checkmark
|
||||
} else {
|
||||
cell.accessoryType = .none
|
||||
}
|
||||
|
||||
|
||||
return cell
|
||||
}
|
||||
|
||||
@@ -80,33 +80,33 @@ class ArticleThemesTableViewController: UITableViewController {
|
||||
!theme.isAppTheme else { return nil }
|
||||
|
||||
let deleteTitle = NSLocalizedString("Delete", comment: "Delete")
|
||||
let deleteAction = UIContextualAction(style: .normal, title: deleteTitle) { [weak self] (action, view, completion) in
|
||||
let deleteAction = UIContextualAction(style: .normal, title: deleteTitle) { [weak self] (_, _, completion) in
|
||||
let title = NSLocalizedString("Delete Theme?", comment: "Delete Theme")
|
||||
|
||||
|
||||
let localizedMessageText = NSLocalizedString("Are you sure you want to delete the theme “%@”?.", comment: "Delete Theme Message")
|
||||
let message = NSString.localizedStringWithFormat(localizedMessageText as NSString, themeName) as String
|
||||
|
||||
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
|
||||
|
||||
let cancelTitle = NSLocalizedString("Cancel", comment: "Cancel")
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel) { action in
|
||||
let cancelAction = UIAlertAction(title: cancelTitle, style: .cancel) { _ in
|
||||
completion(true)
|
||||
}
|
||||
alertController.addAction(cancelAction)
|
||||
|
||||
let deleteTitle = NSLocalizedString("Delete", comment: "Delete")
|
||||
let deleteAction = UIAlertAction(title: deleteTitle, style: .destructive) { action in
|
||||
let deleteAction = UIAlertAction(title: deleteTitle, style: .destructive) { _ in
|
||||
ArticleThemesManager.shared.deleteTheme(themeName: themeName)
|
||||
completion(true)
|
||||
}
|
||||
alertController.addAction(deleteAction)
|
||||
|
||||
|
||||
self?.present(alertController, animated: true)
|
||||
}
|
||||
|
||||
|
||||
deleteAction.image = AppAssets.trashImage
|
||||
deleteAction.backgroundColor = UIColor.systemRed
|
||||
|
||||
|
||||
return UISwipeActionsConfiguration(actions: [deleteAction])
|
||||
}
|
||||
}
|
||||
@@ -114,12 +114,12 @@ class ArticleThemesTableViewController: UITableViewController {
|
||||
// MARK: UIDocumentPickerDelegate
|
||||
|
||||
extension ArticleThemesTableViewController: UIDocumentPickerDelegate {
|
||||
|
||||
|
||||
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
|
||||
guard let url = urls.first else { return }
|
||||
|
||||
if url.startAccessingSecurityScopedResource() {
|
||||
|
||||
|
||||
defer {
|
||||
url.stopAccessingSecurityScopedResource()
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ class SettingsComboTableViewCell: VibrantTableViewCell {
|
||||
override func updateVibrancy(animated: Bool) {
|
||||
super.updateVibrancy(animated: animated)
|
||||
updateLabelVibrancy(comboNameLabel, color: labelColor, animated: animated)
|
||||
|
||||
|
||||
let tintColor = isHighlighted || isSelected ? AppAssets.vibrantTextColor : UIColor.label
|
||||
if animated {
|
||||
UIView.animate(withDuration: Self.duration) {
|
||||
@@ -26,5 +26,5 @@ class SettingsComboTableViewCell: VibrantTableViewCell {
|
||||
self.comboImage?.tintColor = tintColor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ import UniformTypeIdentifiers
|
||||
class SettingsViewController: UITableViewController {
|
||||
|
||||
private weak var opmlAccount: Account?
|
||||
|
||||
|
||||
@IBOutlet weak var timelineSortOrderSwitch: UISwitch!
|
||||
@IBOutlet weak var groupByFeedSwitch: UISwitch!
|
||||
@IBOutlet weak var refreshClearsReadArticlesSwitch: UISwitch!
|
||||
@@ -25,10 +25,10 @@ class SettingsViewController: UITableViewController {
|
||||
@IBOutlet weak var showFullscreenArticlesSwitch: UISwitch!
|
||||
@IBOutlet weak var colorPaletteDetailLabel: UILabel!
|
||||
@IBOutlet weak var openLinksInNetNewsWire: UISwitch!
|
||||
|
||||
|
||||
var scrollToArticlesSection = false
|
||||
weak var presentingParentController: UIViewController?
|
||||
|
||||
|
||||
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)
|
||||
@@ -40,14 +40,14 @@ class SettingsViewController: UITableViewController {
|
||||
|
||||
tableView.register(UINib(nibName: "SettingsComboTableViewCell", bundle: nil), forCellReuseIdentifier: "SettingsComboTableViewCell")
|
||||
tableView.register(UINib(nibName: "SettingsTableViewCell", bundle: nil), forCellReuseIdentifier: "SettingsTableViewCell")
|
||||
|
||||
|
||||
tableView.rowHeight = UITableView.automaticDimension
|
||||
tableView.estimatedRowHeight = 44
|
||||
}
|
||||
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
|
||||
|
||||
if AppDefaults.shared.timelineSortDirection == .orderedAscending {
|
||||
timelineSortOrderSwitch.isOn = true
|
||||
} else {
|
||||
@@ -66,7 +66,6 @@ class SettingsViewController: UITableViewController {
|
||||
refreshClearsReadArticlesSwitch.isOn = false
|
||||
}
|
||||
|
||||
|
||||
articleThemeDetailLabel.text = ArticleThemesManager.shared.currentTheme.name
|
||||
|
||||
if AppDefaults.shared.confirmMarkAllAsRead {
|
||||
@@ -80,11 +79,10 @@ class SettingsViewController: UITableViewController {
|
||||
} else {
|
||||
showFullscreenArticlesSwitch.isOn = false
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
@@ -92,27 +90,27 @@ class SettingsViewController: UITableViewController {
|
||||
buildLabel.text = "\(Bundle.main.appName) \(Bundle.main.versionNumber) (Build \(Bundle.main.buildNumber))"
|
||||
buildLabel.sizeToFit()
|
||||
buildLabel.translatesAutoresizingMaskIntoConstraints = false
|
||||
|
||||
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
self.tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
|
||||
|
||||
|
||||
if scrollToArticlesSection {
|
||||
tableView.scrollToRow(at: IndexPath(row: 0, section: 4), at: .top, animated: true)
|
||||
scrollToArticlesSection = false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// MARK: UITableView
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
|
||||
|
||||
switch section {
|
||||
@@ -237,7 +235,7 @@ class SettingsViewController: UITableViewController {
|
||||
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
|
||||
return false
|
||||
}
|
||||
@@ -245,21 +243,21 @@ class SettingsViewController: UITableViewController {
|
||||
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
|
||||
return .none
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||
return UITableView.automaticDimension
|
||||
}
|
||||
|
||||
|
||||
override func tableView(_ tableView: UITableView, indentationLevelForRowAt indexPath: IndexPath) -> Int {
|
||||
return super.tableView(tableView, indentationLevelForRowAt: IndexPath(row: 0, section: 1))
|
||||
}
|
||||
|
||||
|
||||
// MARK: Actions
|
||||
|
||||
|
||||
@IBAction func done(_ sender: Any) {
|
||||
dismiss(animated: true)
|
||||
}
|
||||
|
||||
|
||||
@IBAction func switchTimelineOrder(_ sender: Any) {
|
||||
if timelineSortOrderSwitch.isOn {
|
||||
AppDefaults.shared.timelineSortDirection = .orderedAscending
|
||||
@@ -267,7 +265,7 @@ class SettingsViewController: UITableViewController {
|
||||
AppDefaults.shared.timelineSortDirection = .orderedDescending
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBAction func switchGroupByFeed(_ sender: Any) {
|
||||
if groupByFeedSwitch.isOn {
|
||||
AppDefaults.shared.timelineGroupByFeed = true
|
||||
@@ -275,7 +273,7 @@ class SettingsViewController: UITableViewController {
|
||||
AppDefaults.shared.timelineGroupByFeed = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBAction func switchClearsReadArticles(_ sender: Any) {
|
||||
if refreshClearsReadArticlesSwitch.isOn {
|
||||
AppDefaults.shared.refreshClearsReadArticles = true
|
||||
@@ -283,7 +281,7 @@ class SettingsViewController: UITableViewController {
|
||||
AppDefaults.shared.refreshClearsReadArticles = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBAction func switchConfirmMarkAllAsRead(_ sender: Any) {
|
||||
if confirmMarkAllAsReadSwitch.isOn {
|
||||
AppDefaults.shared.confirmMarkAllAsRead = true
|
||||
@@ -291,7 +289,7 @@ class SettingsViewController: UITableViewController {
|
||||
AppDefaults.shared.confirmMarkAllAsRead = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBAction func switchFullscreenArticles(_ sender: Any) {
|
||||
if showFullscreenArticlesSwitch.isOn {
|
||||
AppDefaults.shared.articleFullscreenAvailable = true
|
||||
@@ -299,7 +297,7 @@ class SettingsViewController: UITableViewController {
|
||||
AppDefaults.shared.articleFullscreenAvailable = false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@IBAction func switchBrowserPreference(_ sender: Any) {
|
||||
if openLinksInNetNewsWire.isOn {
|
||||
AppDefaults.shared.useSystemBrowser = false
|
||||
@@ -307,14 +305,13 @@ class SettingsViewController: UITableViewController {
|
||||
AppDefaults.shared.useSystemBrowser = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// MARK: Notifications
|
||||
|
||||
|
||||
@objc func contentSizeCategoryDidChange() {
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
|
||||
@objc func accountsDidChange() {
|
||||
tableView.reloadData()
|
||||
}
|
||||
@@ -322,17 +319,17 @@ class SettingsViewController: UITableViewController {
|
||||
@objc func displayNameDidChange() {
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
|
||||
@objc func browserPreferenceDidChange() {
|
||||
tableView.reloadData()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// MARK: OPML Document Picker
|
||||
|
||||
extension SettingsViewController: UIDocumentPickerDelegate {
|
||||
|
||||
|
||||
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
|
||||
for url in urls {
|
||||
opmlAccount?.importOPML(url) { result in
|
||||
@@ -347,13 +344,13 @@ extension SettingsViewController: UIDocumentPickerDelegate {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private extension SettingsViewController {
|
||||
|
||||
|
||||
func addFeed() {
|
||||
self.dismiss(animated: true)
|
||||
|
||||
@@ -363,10 +360,10 @@ private extension SettingsViewController {
|
||||
addViewController.initialFeedName = NSLocalizedString("NetNewsWire News", comment: "NetNewsWire News")
|
||||
addNavViewController.modalPresentationStyle = .formSheet
|
||||
addNavViewController.preferredContentSize = AddFeedViewController.preferredContentSizeForFormSheetDisplay
|
||||
|
||||
|
||||
presentingParentController?.present(addNavViewController, animated: true)
|
||||
}
|
||||
|
||||
|
||||
func importOPML(sourceView: UIView, sourceRect: CGRect) {
|
||||
switch AccountManager.shared.activeAccounts.count {
|
||||
case 0:
|
||||
@@ -378,18 +375,18 @@ private extension SettingsViewController {
|
||||
importOPMLAccountPicker(sourceView: sourceView, sourceRect: sourceRect)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func importOPMLAccountPicker(sourceView: UIView, sourceRect: CGRect) {
|
||||
let title = NSLocalizedString("Choose an account to receive the imported feeds and folders", comment: "Import Account")
|
||||
let alert = UIAlertController(title: title, message: nil, preferredStyle: .actionSheet)
|
||||
|
||||
|
||||
if let popoverController = alert.popoverPresentationController {
|
||||
popoverController.sourceView = view
|
||||
popoverController.sourceRect = sourceRect
|
||||
}
|
||||
|
||||
for account in AccountManager.shared.sortedActiveAccounts {
|
||||
let action = UIAlertAction(title: account.nameForDisplay, style: .default) { [weak self] action in
|
||||
let action = UIAlertAction(title: account.nameForDisplay, style: .default) { [weak self] _ in
|
||||
self?.opmlAccount = account
|
||||
self?.importOPMLDocumentPicker()
|
||||
}
|
||||
@@ -401,15 +398,15 @@ private extension SettingsViewController {
|
||||
|
||||
self.present(alert, animated: true)
|
||||
}
|
||||
|
||||
|
||||
func importOPMLDocumentPicker() {
|
||||
|
||||
|
||||
let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.opml, UTType.xml], asCopy: true)
|
||||
documentPicker.delegate = self
|
||||
documentPicker.modalPresentationStyle = .formSheet
|
||||
self.present(documentPicker, animated: true)
|
||||
}
|
||||
|
||||
|
||||
func exportOPML(sourceView: UIView, sourceRect: CGRect) {
|
||||
if AccountManager.shared.accounts.count == 1 {
|
||||
opmlAccount = AccountManager.shared.accounts.first!
|
||||
@@ -418,18 +415,18 @@ private extension SettingsViewController {
|
||||
exportOPMLAccountPicker(sourceView: sourceView, sourceRect: sourceRect)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func exportOPMLAccountPicker(sourceView: UIView, sourceRect: CGRect) {
|
||||
let title = NSLocalizedString("Choose an account with the subscriptions to export", comment: "Export Account")
|
||||
let alert = UIAlertController(title: title, message: nil, preferredStyle: .actionSheet)
|
||||
|
||||
|
||||
if let popoverController = alert.popoverPresentationController {
|
||||
popoverController.sourceView = view
|
||||
popoverController.sourceRect = sourceRect
|
||||
}
|
||||
|
||||
for account in AccountManager.shared.sortedAccounts {
|
||||
let action = UIAlertAction(title: account.nameForDisplay, style: .default) { [weak self] action in
|
||||
let action = UIAlertAction(title: account.nameForDisplay, style: .default) { [weak self] _ in
|
||||
self?.opmlAccount = account
|
||||
self?.exportOPMLDocumentPicker()
|
||||
}
|
||||
@@ -441,10 +438,10 @@ private extension SettingsViewController {
|
||||
|
||||
self.present(alert, animated: true)
|
||||
}
|
||||
|
||||
|
||||
func exportOPMLDocumentPicker() {
|
||||
guard let account = opmlAccount else { return }
|
||||
|
||||
|
||||
let accountName = account.nameForDisplay.replacingOccurrences(of: " ", with: "").trimmingCharacters(in: .whitespaces)
|
||||
let filename = "Subscriptions-\(accountName).opml"
|
||||
let tempFile = FileManager.default.temporaryDirectory.appendingPathComponent(filename)
|
||||
@@ -454,16 +451,16 @@ private extension SettingsViewController {
|
||||
} catch {
|
||||
self.presentError(title: "OPML Export Error", message: error.localizedDescription)
|
||||
}
|
||||
|
||||
|
||||
let documentPicker = UIDocumentPickerViewController(forExporting: [tempFile])
|
||||
documentPicker.modalPresentationStyle = .formSheet
|
||||
self.present(documentPicker, animated: true)
|
||||
}
|
||||
|
||||
|
||||
func openURL(_ urlString: String) {
|
||||
let vc = SFSafariViewController(url: URL(string: urlString)!)
|
||||
vc.modalPresentationStyle = .pageSheet
|
||||
present(vc, animated: true)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -14,15 +14,15 @@ class TimelineCustomizerViewController: UIViewController {
|
||||
@IBOutlet weak var iconSizeSlider: TickMarkSlider!
|
||||
@IBOutlet weak var numberOfLinesSliderContainerView: UIView!
|
||||
@IBOutlet weak var numberOfLinesSlider: TickMarkSlider!
|
||||
|
||||
|
||||
@IBOutlet weak var previewWidthConstraint: NSLayoutConstraint!
|
||||
@IBOutlet weak var previewHeightConstraint: NSLayoutConstraint!
|
||||
|
||||
|
||||
@IBOutlet weak var previewContainerView: UIView!
|
||||
var previewController: TimelinePreviewTableViewController {
|
||||
return children.first as! TimelinePreviewTableViewController
|
||||
}
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
@@ -34,13 +34,13 @@ class TimelineCustomizerViewController: UIViewController {
|
||||
numberOfLinesSlider.value = Float(AppDefaults.shared.timelineNumberOfLines)
|
||||
numberOfLinesSlider.addTickMarks()
|
||||
}
|
||||
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
updatePreviewBorder()
|
||||
updatePreview()
|
||||
}
|
||||
|
||||
|
||||
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||
updatePreviewBorder()
|
||||
updatePreview()
|
||||
@@ -51,18 +51,18 @@ class TimelineCustomizerViewController: UIViewController {
|
||||
AppDefaults.shared.timelineIconSize = iconSize
|
||||
updatePreview()
|
||||
}
|
||||
|
||||
|
||||
@IBAction func numberOfLinesChanged(_ sender: Any) {
|
||||
AppDefaults.shared.timelineNumberOfLines = Int(numberOfLinesSlider.value.rounded())
|
||||
updatePreview()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private extension TimelineCustomizerViewController {
|
||||
|
||||
|
||||
func updatePreview() {
|
||||
let previewWidth: CGFloat = {
|
||||
if traitCollection.userInterfaceIdiom == .phone {
|
||||
@@ -71,13 +71,13 @@ private extension TimelineCustomizerViewController {
|
||||
return view.bounds.width / 1.5
|
||||
}
|
||||
}()
|
||||
|
||||
|
||||
previewWidthConstraint.constant = previewWidth
|
||||
previewHeightConstraint.constant = previewController.heightFor(width: previewWidth)
|
||||
|
||||
|
||||
previewController.reload()
|
||||
}
|
||||
|
||||
|
||||
func updatePreviewBorder() {
|
||||
if traitCollection.userInterfaceStyle == .dark {
|
||||
previewContainerView.layer.borderColor = UIColor.black.cgColor
|
||||
@@ -86,5 +86,5 @@ private extension TimelineCustomizerViewController {
|
||||
previewContainerView.layer.borderWidth = 0
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -12,13 +12,13 @@ import Articles
|
||||
class TimelinePreviewTableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
|
||||
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
|
||||
|
||||
tableView.delegate = self
|
||||
tableView.dataSource = self
|
||||
|
||||
|
||||
}
|
||||
|
||||
func heightFor(width: CGFloat) -> CGFloat {
|
||||
@@ -46,7 +46,7 @@ class TimelinePreviewTableViewController: UIViewController, UITableViewDelegate,
|
||||
cell.cellData = prototypeCellData
|
||||
return cell
|
||||
}
|
||||
|
||||
|
||||
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
|
||||
tableView.selectRow(at: nil, animated: true, scrollPosition: .none)
|
||||
}
|
||||
@@ -64,14 +64,14 @@ private extension TimelinePreviewTableViewController {
|
||||
|
||||
var prototypeCellData: MainTimelineCellData {
|
||||
let longTitle = "Enim ut tellus elementum sagittis vitae et. Nibh praesent tristique magna sit amet purus gravida quis blandit. Neque volutpat ac tincidunt vitae semper quis lectus nulla. Massa id neque aliquam vestibulum morbi blandit. Ultrices vitae auctor eu augue. Enim eu turpis egestas pretium aenean pharetra magna. Eget gravida cum sociis natoque. Sit amet consectetur adipiscing elit. Auctor eu augue ut lectus arcu bibendum. Maecenas volutpat blandit aliquam etiam erat velit. Ut pharetra sit amet aliquam id diam maecenas ultricies. In hac habitasse platea dictumst quisque sagittis purus sit amet."
|
||||
|
||||
|
||||
let prototypeID = "prototype"
|
||||
let status = ArticleStatus(articleID: prototypeID, read: false, starred: false, dateArrived: Date())
|
||||
let prototypeArticle = Article(accountID: prototypeID, articleID: prototypeID, feedID: prototypeID, uniqueID: prototypeID, title: longTitle, contentHTML: nil, contentText: nil, url: nil, externalURL: nil, summary: nil, imageURL: nil, datePublished: nil, dateModified: nil, authors: nil, status: status)
|
||||
|
||||
|
||||
let iconImage = IconImage(AppAssets.faviconTemplateImage.withTintColor(AppAssets.secondaryAccentColor))
|
||||
|
||||
|
||||
return MainTimelineCellData(article: prototypeArticle, showFeedName: .feed, feedName: "Feed Name", byline: nil, iconImage: iconImage, showIcon: true, numberOfLines: AppDefaults.shared.timelineNumberOfLines, iconSize: AppDefaults.shared.timelineIconSize)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user