mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Renamed Feed and related classes/instances to WebFeed
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
<!--Add Feed-->
|
||||
<scene sceneID="2Tc-JN-edX">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="AddFeedViewController" id="7aE-6a-iP7" customClass="AddFeedViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableViewController storyboardIdentifier="AddWebFeedViewController" id="7aE-6a-iP7" customClass="AddWebFeedViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" scrollEnabled="NO" dataMode="static" style="grouped" separatorStyle="default" allowsSelection="NO" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="1" sectionFooterHeight="5" id="D0S-TM-mtm">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="812"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
@@ -78,7 +78,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vaV-kY-CaE">
|
||||
<rect key="frame" x="313" y="11.999999999999998" width="42" height="20.333333333333329"/>
|
||||
<rect key="frame" x="313" y="12" width="42" height="20"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@@ -166,12 +166,12 @@
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="1Ce-E7-rG2">
|
||||
<rect key="frame" x="112.66666666666669" y="108" width="150" height="32"/>
|
||||
<rect key="frame" x="97.666666666666686" y="108" width="180" height="32"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="150" id="IEO-pf-4PB"/>
|
||||
<constraint firstAttribute="width" constant="180" id="IEO-pf-4PB"/>
|
||||
</constraints>
|
||||
<segments>
|
||||
<segment title="Feed"/>
|
||||
<segment title="Web Feed"/>
|
||||
<segment title="Folder"/>
|
||||
</segments>
|
||||
<connections>
|
||||
@@ -282,7 +282,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mxj-Bw-Jfx">
|
||||
<rect key="frame" x="313" y="11.999999999999998" width="42" height="20.333333333333329"/>
|
||||
<rect key="frame" x="313" y="12" width="42" height="20"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
|
||||
@@ -105,15 +105,15 @@ private extension AddContainerViewController {
|
||||
|
||||
func switchToFeed() {
|
||||
|
||||
guard !(currentViewController is AddFeedViewController) else {
|
||||
guard !(currentViewController is AddWebFeedViewController) else {
|
||||
return
|
||||
}
|
||||
|
||||
navigationItem.title = NSLocalizedString("Add Feed", comment: "Add Feed")
|
||||
navigationItem.title = NSLocalizedString("Add Web Feed", comment: "Add Web Feed")
|
||||
resetUI()
|
||||
hideCurrentController()
|
||||
|
||||
let addFeedController = UIStoryboard.add.instantiateController(ofType: AddFeedViewController.self)
|
||||
let addFeedController = UIStoryboard.add.instantiateController(ofType: AddWebFeedViewController.self)
|
||||
addFeedController.initialFeed = initialFeed
|
||||
addFeedController.initialFeedName = initialFeedName
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import RSCore
|
||||
import RSTree
|
||||
import RSParser
|
||||
|
||||
class AddFeedViewController: UITableViewController, AddContainerViewControllerChild {
|
||||
class AddWebFeedViewController: UITableViewController, AddContainerViewControllerChild {
|
||||
|
||||
@IBOutlet private weak var urlTextField: UITextField!
|
||||
@IBOutlet private weak var nameTextField: UITextField!
|
||||
@@ -91,7 +91,7 @@ class AddFeedViewController: UITableViewController, AddContainerViewControllerCh
|
||||
account = containerAccount
|
||||
}
|
||||
|
||||
if account!.hasFeed(withURL: url.absoluteString) {
|
||||
if account!.hasWebFeed(withURL: url.absoluteString) {
|
||||
presentError(AccountError.createErrorAlreadySubscribed)
|
||||
return
|
||||
}
|
||||
@@ -102,14 +102,14 @@ class AddFeedViewController: UITableViewController, AddContainerViewControllerCh
|
||||
|
||||
BatchUpdate.shared.start()
|
||||
|
||||
account!.createFeed(url: url.absoluteString, name: feedName, container: container) { result in
|
||||
account!.createWebFeed(url: url.absoluteString, name: feedName, container: container) { result in
|
||||
|
||||
BatchUpdate.shared.end()
|
||||
|
||||
switch result {
|
||||
case .success(let feed):
|
||||
self.delegate?.processingDidEnd()
|
||||
NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: [UserInfoKey.feed: feed])
|
||||
NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: [UserInfoKey.webFeed: feed])
|
||||
case .failure(let error):
|
||||
self.presentError(error)
|
||||
self.delegate?.processingDidCancel()
|
||||
@@ -135,7 +135,7 @@ class AddFeedViewController: UITableViewController, AddContainerViewControllerCh
|
||||
|
||||
}
|
||||
|
||||
extension AddFeedViewController: UIPickerViewDataSource, UIPickerViewDelegate {
|
||||
extension AddWebFeedViewController: UIPickerViewDataSource, UIPickerViewDelegate {
|
||||
|
||||
func numberOfComponents(in pickerView: UIPickerView) ->Int {
|
||||
return 1
|
||||
@@ -155,7 +155,7 @@ extension AddFeedViewController: UIPickerViewDataSource, UIPickerViewDelegate {
|
||||
|
||||
}
|
||||
|
||||
extension AddFeedViewController: UITextFieldDelegate {
|
||||
extension AddWebFeedViewController: UITextFieldDelegate {
|
||||
|
||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
textField.resignFirstResponder()
|
||||
@@ -40,7 +40,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||
var faviconDownloader: FaviconDownloader!
|
||||
var imageDownloader: ImageDownloader!
|
||||
var authorAvatarDownloader: AuthorAvatarDownloader!
|
||||
var feedIconDownloader: FeedIconDownloader!
|
||||
var webFeedIconDownloader: WebFeedIconDownloader!
|
||||
|
||||
var unreadCount = 0 {
|
||||
didSet {
|
||||
@@ -192,7 +192,7 @@ private extension AppDelegate {
|
||||
|
||||
let tempFolder = tempDir.absoluteString
|
||||
let tempFolderPath = tempFolder.suffix(from: tempFolder.index(tempFolder.startIndex, offsetBy: 7))
|
||||
feedIconDownloader = FeedIconDownloader(imageDownloader: imageDownloader, folder: String(tempFolderPath))
|
||||
webFeedIconDownloader = WebFeedIconDownloader(imageDownloader: imageDownloader, folder: String(tempFolderPath))
|
||||
}
|
||||
|
||||
private func initializeHomeScreenQuickActions() {
|
||||
|
||||
@@ -160,10 +160,10 @@
|
||||
</objects>
|
||||
<point key="canvasLocation" x="863.768115942029" y="-591.29464285714278"/>
|
||||
</scene>
|
||||
<!--Feed Inspector View Controller-->
|
||||
<!--Web Feed Inspector View Controller-->
|
||||
<scene sceneID="jnI-2I-AcU">
|
||||
<objects>
|
||||
<tableViewController storyboardIdentifier="FeedInspectorViewControllelr" id="lEH-bG-pQW" customClass="FeedInspectorViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableViewController storyboardIdentifier="FeedInspectorViewControllelr" id="lEH-bG-pQW" customClass="WebFeedInspectorViewController" customModule="NetNewsWire" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="insetGrouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="26V-ZC-Q2R">
|
||||
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// FeedInspectorViewController.swift
|
||||
// WebFeedInspectorViewController.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Maurice Parker on 11/6/19.
|
||||
@@ -9,11 +9,11 @@
|
||||
import UIKit
|
||||
import Account
|
||||
|
||||
class FeedInspectorViewController: UITableViewController {
|
||||
class WebFeedInspectorViewController: UITableViewController {
|
||||
|
||||
static let preferredContentSizeForFormSheetDisplay = CGSize(width: 460.0, height: 500.0)
|
||||
|
||||
var feed: Feed!
|
||||
var webFeed: WebFeed!
|
||||
@IBOutlet weak var nameTextField: UITextField!
|
||||
@IBOutlet weak var notifyAboutNewArticlesSwitch: UISwitch!
|
||||
@IBOutlet weak var alwaysShowReaderViewSwitch: UISwitch!
|
||||
@@ -22,49 +22,49 @@ class FeedInspectorViewController: UITableViewController {
|
||||
|
||||
private var headerView: InspectorIconHeaderView?
|
||||
private var iconImage: IconImage {
|
||||
if let feedIcon = appDelegate.feedIconDownloader.icon(for: feed) {
|
||||
if let feedIcon = appDelegate.webFeedIconDownloader.icon(for: webFeed) {
|
||||
return feedIcon
|
||||
}
|
||||
if let favicon = appDelegate.faviconDownloader.favicon(for: feed) {
|
||||
if let favicon = appDelegate.faviconDownloader.favicon(for: webFeed) {
|
||||
return favicon
|
||||
}
|
||||
return FaviconGenerator.favicon(feed)
|
||||
return FaviconGenerator.favicon(webFeed)
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
tableView.register(InspectorIconHeaderView.self, forHeaderFooterViewReuseIdentifier: "SectionHeader")
|
||||
|
||||
navigationItem.title = feed.nameForDisplay
|
||||
nameTextField.text = feed.nameForDisplay
|
||||
navigationItem.title = webFeed.nameForDisplay
|
||||
nameTextField.text = webFeed.nameForDisplay
|
||||
|
||||
notifyAboutNewArticlesSwitch.setOn(feed.isNotifyAboutNewArticles ?? false, animated: false)
|
||||
alwaysShowReaderViewSwitch.setOn(feed.isArticleExtractorAlwaysOn ?? false, animated: false)
|
||||
notifyAboutNewArticlesSwitch.setOn(webFeed.isNotifyAboutNewArticles ?? false, animated: false)
|
||||
alwaysShowReaderViewSwitch.setOn(webFeed.isArticleExtractorAlwaysOn ?? false, animated: false)
|
||||
|
||||
homePageLabel.text = feed.homePageURL
|
||||
feedURLLabel.text = feed.url
|
||||
homePageLabel.text = webFeed.homePageURL
|
||||
feedURLLabel.text = webFeed.url
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(feedIconDidBecomeAvailable(_:)), name: .FeedIconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(webFeedIconDidBecomeAvailable(_:)), name: .WebFeedIconDidBecomeAvailable, object: nil)
|
||||
}
|
||||
|
||||
override func viewDidDisappear(_ animated: Bool) {
|
||||
if nameTextField.text != feed.nameForDisplay {
|
||||
if nameTextField.text != webFeed.nameForDisplay {
|
||||
let nameText = nameTextField.text ?? ""
|
||||
let newName = nameText.isEmpty ? (feed.name ?? NSLocalizedString("Untitled", comment: "Feed name")) : nameText
|
||||
feed.rename(to: newName) { _ in }
|
||||
let newName = nameText.isEmpty ? (webFeed.name ?? NSLocalizedString("Untitled", comment: "Feed name")) : nameText
|
||||
webFeed.rename(to: newName) { _ in }
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: Notifications
|
||||
@objc func feedIconDidBecomeAvailable(_ notification: Notification) {
|
||||
@objc func webFeedIconDidBecomeAvailable(_ notification: Notification) {
|
||||
headerView?.iconView.iconImage = iconImage
|
||||
}
|
||||
|
||||
@IBAction func notifyAboutNewArticlesChanged(_ sender: Any) {
|
||||
feed.isNotifyAboutNewArticles = notifyAboutNewArticlesSwitch.isOn
|
||||
webFeed.isNotifyAboutNewArticles = notifyAboutNewArticlesSwitch.isOn
|
||||
}
|
||||
|
||||
@IBAction func alwaysShowReaderViewChanged(_ sender: Any) {
|
||||
feed.isArticleExtractorAlwaysOn = alwaysShowReaderViewSwitch.isOn
|
||||
webFeed.isArticleExtractorAlwaysOn = alwaysShowReaderViewSwitch.isOn
|
||||
}
|
||||
|
||||
@IBAction func done(_ sender: Any) {
|
||||
@@ -75,7 +75,7 @@ class FeedInspectorViewController: UITableViewController {
|
||||
|
||||
// MARK: Table View
|
||||
|
||||
extension FeedInspectorViewController {
|
||||
extension WebFeedInspectorViewController {
|
||||
|
||||
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
|
||||
return section == 0 ? 64.0 : super.tableView(tableView, heightForHeaderInSection: section)
|
||||
@@ -95,7 +95,7 @@ extension FeedInspectorViewController {
|
||||
|
||||
// MARK: UITextFieldDelegate
|
||||
|
||||
extension FeedInspectorViewController: UITextFieldDelegate {
|
||||
extension WebFeedInspectorViewController: UITextFieldDelegate {
|
||||
|
||||
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
|
||||
textField.resignFirstResponder()
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// AddFeedIntentHandler.swift
|
||||
// AddWebFeedIntentHandler.swift
|
||||
// NetNewsWire
|
||||
//
|
||||
// Created by Maurice Parker on 10/18/19.
|
||||
@@ -9,7 +9,7 @@
|
||||
import Intents
|
||||
import Account
|
||||
|
||||
public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
|
||||
public class AddWebFeedIntentHandler: NSObject, AddWebFeedIntentHandling {
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
@@ -18,7 +18,7 @@ public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
|
||||
}
|
||||
}
|
||||
|
||||
public func resolveUrl(for intent: AddFeedIntent, with completion: @escaping (AddFeedUrlResolutionResult) -> Void) {
|
||||
public func resolveUrl(for intent: AddWebFeedIntent, with completion: @escaping (AddWebFeedUrlResolutionResult) -> Void) {
|
||||
guard let url = intent.url else {
|
||||
completion(.unsupported(forReason: .required))
|
||||
return
|
||||
@@ -26,16 +26,16 @@ public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
|
||||
completion(.success(with: url))
|
||||
}
|
||||
|
||||
public func provideAccountNameOptions(for intent: AddFeedIntent, with completion: @escaping ([String]?, Error?) -> Void) {
|
||||
public func provideAccountNameOptions(for intent: AddWebFeedIntent, with completion: @escaping ([String]?, Error?) -> Void) {
|
||||
DispatchQueue.main.async {
|
||||
let accountNames = AccountManager.shared.activeAccounts.compactMap { $0.nameForDisplay }
|
||||
completion(accountNames, nil)
|
||||
}
|
||||
}
|
||||
|
||||
public func resolveAccountName(for intent: AddFeedIntent, with completion: @escaping (AddFeedAccountNameResolutionResult) -> Void) {
|
||||
public func resolveAccountName(for intent: AddWebFeedIntent, with completion: @escaping (AddWebFeedAccountNameResolutionResult) -> Void) {
|
||||
guard let accountName = intent.accountName else {
|
||||
completion(AddFeedAccountNameResolutionResult.notRequired())
|
||||
completion(AddWebFeedAccountNameResolutionResult.notRequired())
|
||||
return
|
||||
}
|
||||
DispatchQueue.main.async {
|
||||
@@ -47,7 +47,7 @@ public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
|
||||
}
|
||||
}
|
||||
|
||||
public func provideFolderNameOptions(for intent: AddFeedIntent, with completion: @escaping ([String]?, Error?) -> Void) {
|
||||
public func provideFolderNameOptions(for intent: AddWebFeedIntent, with completion: @escaping ([String]?, Error?) -> Void) {
|
||||
DispatchQueue.main.async {
|
||||
guard let accountName = intent.accountName, let account = AccountManager.shared.findActiveAccount(forDisplayName: accountName) else {
|
||||
completion([String](), nil)
|
||||
@@ -59,9 +59,9 @@ public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
|
||||
}
|
||||
}
|
||||
|
||||
public func resolveFolderName(for intent: AddFeedIntent, with completion: @escaping (AddFeedFolderNameResolutionResult) -> Void) {
|
||||
public func resolveFolderName(for intent: AddWebFeedIntent, with completion: @escaping (AddWebFeedFolderNameResolutionResult) -> Void) {
|
||||
guard let accountName = intent.accountName, let folderName = intent.folderName else {
|
||||
completion(AddFeedFolderNameResolutionResult.notRequired())
|
||||
completion(AddWebFeedFolderNameResolutionResult.notRequired())
|
||||
return
|
||||
}
|
||||
|
||||
@@ -79,9 +79,9 @@ public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
|
||||
}
|
||||
}
|
||||
|
||||
public func handle(intent: AddFeedIntent, completion: @escaping (AddFeedIntentResponse) -> Void) {
|
||||
public func handle(intent: AddWebFeedIntent, completion: @escaping (AddWebFeedIntentResponse) -> Void) {
|
||||
guard let url = intent.url else {
|
||||
completion(AddFeedIntentResponse(code: .failure, userActivity: nil))
|
||||
completion(AddWebFeedIntentResponse(code: .failure, userActivity: nil))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
|
||||
}()
|
||||
|
||||
guard let validAccount = account else {
|
||||
completion(AddFeedIntentResponse(code: .failure, userActivity: nil))
|
||||
completion(AddWebFeedIntentResponse(code: .failure, userActivity: nil))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -109,22 +109,22 @@ public class AddFeedIntentHandler: NSObject, AddFeedIntentHandling {
|
||||
}()
|
||||
|
||||
guard let validContainer = container else {
|
||||
completion(AddFeedIntentResponse(code: .failure, userActivity: nil))
|
||||
completion(AddWebFeedIntentResponse(code: .failure, userActivity: nil))
|
||||
return
|
||||
}
|
||||
|
||||
validAccount.createFeed(url: url.absoluteString, name: nil, container: validContainer) { result in
|
||||
validAccount.createWebFeed(url: url.absoluteString, name: nil, container: validContainer) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
completion(AddFeedIntentResponse(code: .success, userActivity: nil))
|
||||
completion(AddWebFeedIntentResponse(code: .success, userActivity: nil))
|
||||
case .failure(let error):
|
||||
switch error {
|
||||
case AccountError.createErrorNotFound:
|
||||
completion(AddFeedIntentResponse(code: .feedNotFound, userActivity: nil))
|
||||
completion(AddWebFeedIntentResponse(code: .feedNotFound, userActivity: nil))
|
||||
case AccountError.createErrorAlreadySubscribed:
|
||||
completion(AddFeedIntentResponse(code: .alreadySubscribed, userActivity: nil))
|
||||
completion(AddWebFeedIntentResponse(code: .alreadySubscribed, userActivity: nil))
|
||||
default:
|
||||
completion(AddFeedIntentResponse(code: .failure, userActivity: nil))
|
||||
completion(AddWebFeedIntentResponse(code: .failure, userActivity: nil))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,11 +9,11 @@
|
||||
<key>INIntentDefinitionNamespace</key>
|
||||
<string>U6u7RF</string>
|
||||
<key>INIntentDefinitionSystemVersion</key>
|
||||
<string>19A602</string>
|
||||
<string>19B88</string>
|
||||
<key>INIntentDefinitionToolsBuildVersion</key>
|
||||
<string>11B41</string>
|
||||
<string>11B53</string>
|
||||
<key>INIntentDefinitionToolsVersion</key>
|
||||
<string>11.2</string>
|
||||
<string>11.2.1</string>
|
||||
<key>INIntents</key>
|
||||
<array>
|
||||
<dict>
|
||||
@@ -22,7 +22,7 @@
|
||||
<key>INIntentConfigurable</key>
|
||||
<true/>
|
||||
<key>INIntentDescription</key>
|
||||
<string>Add a feed</string>
|
||||
<string>Add a web feed</string>
|
||||
<key>INIntentDescriptionID</key>
|
||||
<string>IuAbef</string>
|
||||
<key>INIntentIneligibleForSuggestions</key>
|
||||
@@ -59,7 +59,7 @@
|
||||
</dict>
|
||||
</dict>
|
||||
<key>INIntentName</key>
|
||||
<string>AddFeed</string>
|
||||
<string>AddWebFeed</string>
|
||||
<key>INIntentParameters</key>
|
||||
<array>
|
||||
<dict>
|
||||
@@ -303,7 +303,7 @@
|
||||
</array>
|
||||
</dict>
|
||||
<key>INIntentTitle</key>
|
||||
<string>Add Feed</string>
|
||||
<string>Add Web Feed</string>
|
||||
<key>INIntentTitleID</key>
|
||||
<string>oV681v</string>
|
||||
<key>INIntentType</key>
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<array/>
|
||||
<key>IntentsSupported</key>
|
||||
<array>
|
||||
<string>AddFeedIntent</string>
|
||||
<string>AddWebFeedIntent</string>
|
||||
</array>
|
||||
</dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
|
||||
@@ -12,8 +12,8 @@ class IntentHandler: INExtension {
|
||||
|
||||
override func handler(for intent: INIntent) -> Any {
|
||||
switch intent {
|
||||
case is AddFeedIntent:
|
||||
return AddFeedIntentHandler()
|
||||
case is AddWebFeedIntent:
|
||||
return AddWebFeedIntentHandler()
|
||||
default:
|
||||
fatalError("Unhandled intent type: \(intent)")
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ private extension KeyboardManager {
|
||||
static func globalAuxilaryKeyCommands() -> [UIKeyCommand] {
|
||||
var keys = [UIKeyCommand]()
|
||||
|
||||
let addNewFeedTitle = NSLocalizedString("New Feed", comment: "New Feed")
|
||||
let addNewFeedTitle = NSLocalizedString("New Web Feed", comment: "New Web Feed")
|
||||
keys.append(KeyboardManager.createKeyCommand(title: addNewFeedTitle, action: "addNewFeed:", input: "n", modifiers: [.command]))
|
||||
|
||||
let addNewFolderTitle = NSLocalizedString("New Folder", comment: "New Folder")
|
||||
|
||||
@@ -34,12 +34,12 @@ class MasterFeedDataSource: UITableViewDiffableDataSource<Node, Node> {
|
||||
guard let node = itemIdentifier(for: indexPath) else {
|
||||
return false
|
||||
}
|
||||
return node.representedObject is Feed
|
||||
return node.representedObject is WebFeed
|
||||
}
|
||||
|
||||
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
|
||||
|
||||
guard let sourceNode = itemIdentifier(for: sourceIndexPath), let feed = sourceNode.representedObject as? Feed else {
|
||||
guard let sourceNode = itemIdentifier(for: sourceIndexPath), let webFeed = sourceNode.representedObject as? WebFeed else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -67,15 +67,15 @@ class MasterFeedDataSource: UITableViewDiffableDataSource<Node, Node> {
|
||||
}
|
||||
}()
|
||||
|
||||
// Move the Feed
|
||||
// Move the Web Feed
|
||||
guard let source = sourceNode.parent?.representedObject as? Container, let destination = destParentNode?.representedObject as? Container else {
|
||||
return
|
||||
}
|
||||
|
||||
if sameAccount(sourceNode, destParentNode!) {
|
||||
moveFeedInAccount(feed: feed, sourceContainer: source, destinationContainer: destination)
|
||||
moveWebFeedInAccount(feed: webFeed, sourceContainer: source, destinationContainer: destination)
|
||||
} else {
|
||||
moveFeedBetweenAccounts(feed: feed, sourceContainer: source, destinationContainer: destination)
|
||||
moveWebFeedBetweenAccounts(feed: webFeed, sourceContainer: source, destinationContainer: destination)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -94,8 +94,8 @@ class MasterFeedDataSource: UITableViewDiffableDataSource<Node, Node> {
|
||||
return account
|
||||
} else if let folder = node.representedObject as? Folder {
|
||||
return folder.account
|
||||
} else if let feed = node.representedObject as? Feed {
|
||||
return feed.account
|
||||
} else if let webFeed = node.representedObject as? WebFeed {
|
||||
return webFeed.account
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
@@ -106,9 +106,9 @@ class MasterFeedDataSource: UITableViewDiffableDataSource<Node, Node> {
|
||||
return nodeAccount(node)?.accountID
|
||||
}
|
||||
|
||||
func moveFeedInAccount(feed: Feed, sourceContainer: Container, destinationContainer: Container) {
|
||||
func moveWebFeedInAccount(feed: WebFeed, sourceContainer: Container, destinationContainer: Container) {
|
||||
BatchUpdate.shared.start()
|
||||
sourceContainer.account?.moveFeed(feed, from: sourceContainer, to: destinationContainer) { result in
|
||||
sourceContainer.account?.moveWebFeed(feed, from: sourceContainer, to: destinationContainer) { result in
|
||||
BatchUpdate.shared.end()
|
||||
switch result {
|
||||
case .success:
|
||||
@@ -119,15 +119,15 @@ class MasterFeedDataSource: UITableViewDiffableDataSource<Node, Node> {
|
||||
}
|
||||
}
|
||||
|
||||
func moveFeedBetweenAccounts(feed: Feed, sourceContainer: Container, destinationContainer: Container) {
|
||||
func moveWebFeedBetweenAccounts(feed: WebFeed, sourceContainer: Container, destinationContainer: Container) {
|
||||
|
||||
if let existingFeed = destinationContainer.account?.existingFeed(withURL: feed.url) {
|
||||
if let existingFeed = destinationContainer.account?.existingWebFeed(withURL: feed.url) {
|
||||
|
||||
BatchUpdate.shared.start()
|
||||
destinationContainer.account?.addFeed(existingFeed, to: destinationContainer) { result in
|
||||
destinationContainer.account?.addWebFeed(existingFeed, to: destinationContainer) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
sourceContainer.account?.removeFeed(feed, from: sourceContainer) { result in
|
||||
sourceContainer.account?.removeWebFeed(feed, from: sourceContainer) { result in
|
||||
BatchUpdate.shared.end()
|
||||
switch result {
|
||||
case .success:
|
||||
@@ -145,10 +145,10 @@ class MasterFeedDataSource: UITableViewDiffableDataSource<Node, Node> {
|
||||
} else {
|
||||
|
||||
BatchUpdate.shared.start()
|
||||
destinationContainer.account?.createFeed(url: feed.url, name: feed.editedName, container: destinationContainer) { result in
|
||||
destinationContainer.account?.createWebFeed(url: feed.url, name: feed.editedName, container: destinationContainer) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
sourceContainer.account?.removeFeed(feed, from: sourceContainer) { result in
|
||||
sourceContainer.account?.removeWebFeed(feed, from: sourceContainer) { result in
|
||||
BatchUpdate.shared.end()
|
||||
switch result {
|
||||
case .success:
|
||||
|
||||
@@ -53,9 +53,9 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(feedIconDidBecomeAvailable(_:)), name: .FeedIconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(feedSettingDidChange(_:)), name: .FeedSettingDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(feedMetadataDidChange(_:)), name: .FeedMetadataDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(webFeedIconDidBecomeAvailable(_:)), name: .WebFeedIconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(webFeedSettingDidChange(_:)), name: .WebFeedSettingDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(webFeedMetadataDidChange(_:)), name: .WebFeedMetadataDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userDidAddFeed(_:)), name: .UserDidAddFeed, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(contentSizeCategoryDidChange), name: UIContentSizeCategory.didChangeNotification, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(willEnterForeground(_:)), name: UIApplication.willEnterForegroundNotification, object: nil)
|
||||
@@ -117,31 +117,31 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||
applyToAvailableCells(configureIcon)
|
||||
}
|
||||
|
||||
@objc func feedIconDidBecomeAvailable(_ note: Notification) {
|
||||
guard let feed = note.userInfo?[UserInfoKey.feed] as? Feed else {
|
||||
@objc func webFeedIconDidBecomeAvailable(_ note: Notification) {
|
||||
guard let webFeed = note.userInfo?[UserInfoKey.webFeed] as? WebFeed else {
|
||||
return
|
||||
}
|
||||
applyToCellsForRepresentedObject(feed, configureIcon(_:_:))
|
||||
applyToCellsForRepresentedObject(webFeed, configureIcon(_:_:))
|
||||
}
|
||||
|
||||
@objc func feedSettingDidChange(_ note: Notification) {
|
||||
guard let feed = note.object as? Feed, let key = note.userInfo?[Feed.FeedSettingUserInfoKey] as? String else {
|
||||
@objc func webFeedSettingDidChange(_ note: Notification) {
|
||||
guard let webFeed = note.object as? WebFeed, let key = note.userInfo?[WebFeed.WebFeedSettingUserInfoKey] as? String else {
|
||||
return
|
||||
}
|
||||
if key == Feed.FeedSettingKey.homePageURL || key == Feed.FeedSettingKey.faviconURL {
|
||||
configureCellsForRepresentedObject(feed)
|
||||
if key == WebFeed.WebFeedSettingKey.homePageURL || key == WebFeed.WebFeedSettingKey.faviconURL {
|
||||
configureCellsForRepresentedObject(webFeed)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func feedMetadataDidChange(_ note: Notification) {
|
||||
@objc func webFeedMetadataDidChange(_ note: Notification) {
|
||||
reloadAllVisibleCells()
|
||||
}
|
||||
|
||||
@objc func userDidAddFeed(_ notification: Notification) {
|
||||
guard let feed = notification.userInfo?[UserInfoKey.feed] as? Feed else {
|
||||
guard let webFeed = notification.userInfo?[UserInfoKey.webFeed] as? WebFeed else {
|
||||
return
|
||||
}
|
||||
discloseFeed(feed, animated: true)
|
||||
discloseFeed(webFeed, animated: true)
|
||||
}
|
||||
|
||||
@objc func contentSizeCategoryDidChange(_ note: Notification) {
|
||||
@@ -237,13 +237,13 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||
renameAction.backgroundColor = UIColor.systemOrange
|
||||
actions.append(renameAction)
|
||||
|
||||
if let feed = dataSource.itemIdentifier(for: indexPath)?.representedObject as? Feed {
|
||||
if let webFeed = dataSource.itemIdentifier(for: indexPath)?.representedObject as? WebFeed {
|
||||
let moreTitle = NSLocalizedString("More", comment: "More")
|
||||
let moreAction = UIContextualAction(style: .normal, title: moreTitle) { [weak self] (action, view, completionHandler) in
|
||||
|
||||
if let self = self {
|
||||
|
||||
let alert = UIAlertController(title: feed.nameForDisplay, message: nil, preferredStyle: .actionSheet)
|
||||
let alert = UIAlertController(title: webFeed.nameForDisplay, message: nil, preferredStyle: .actionSheet)
|
||||
if let popoverController = alert.popoverPresentationController {
|
||||
popoverController.sourceView = view
|
||||
popoverController.sourceRect = CGRect(x: view.frame.size.width/2, y: view.frame.size.height/2, width: 1, height: 1)
|
||||
@@ -288,7 +288,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||
guard let node = dataSource.itemIdentifier(for: indexPath), !(node.representedObject is PseudoFeed) else {
|
||||
return nil
|
||||
}
|
||||
if node.representedObject is Feed {
|
||||
if node.representedObject is WebFeed {
|
||||
return makeFeedContextMenu(indexPath: indexPath, includeDeleteRename: true)
|
||||
} else {
|
||||
return makeFolderContextMenu(indexPath: indexPath)
|
||||
@@ -508,7 +508,7 @@ class MasterFeedViewController: UITableViewController, UndoableCommandRunner {
|
||||
}
|
||||
}
|
||||
|
||||
func discloseFeed(_ feed: Feed, animated: Bool, completion: (() -> Void)? = nil) {
|
||||
func discloseFeed(_ feed: WebFeed, animated: Bool, completion: (() -> Void)? = nil) {
|
||||
|
||||
guard let node = coordinator.rootNode.descendantNodeRepresentingObject(feed as AnyObject) else {
|
||||
completion?()
|
||||
@@ -674,14 +674,14 @@ private extension MasterFeedViewController {
|
||||
}
|
||||
|
||||
func imageFor(_ node: Node) -> IconImage? {
|
||||
if let feed = node.representedObject as? Feed {
|
||||
if let webFeed = node.representedObject as? WebFeed {
|
||||
|
||||
let feedIconImage = appDelegate.feedIconDownloader.icon(for: feed)
|
||||
let feedIconImage = appDelegate.webFeedIconDownloader.icon(for: webFeed)
|
||||
if feedIconImage != nil {
|
||||
return feedIconImage
|
||||
}
|
||||
|
||||
if let faviconImage = appDelegate.faviconDownloader.favicon(for: feed) {
|
||||
if let faviconImage = appDelegate.faviconDownloader.favicon(for: webFeed) {
|
||||
return faviconImage
|
||||
}
|
||||
|
||||
@@ -742,7 +742,7 @@ private extension MasterFeedViewController {
|
||||
if let folder = node.representedObject as? Folder {
|
||||
return folder.account
|
||||
}
|
||||
if let feed = node.representedObject as? Feed {
|
||||
if let feed = node.representedObject as? WebFeed {
|
||||
return feed.account
|
||||
}
|
||||
return nil
|
||||
@@ -843,7 +843,7 @@ private extension MasterFeedViewController {
|
||||
|
||||
func copyFeedPageAction(indexPath: IndexPath) -> UIAction? {
|
||||
guard let node = dataSource.itemIdentifier(for: indexPath),
|
||||
let feed = node.representedObject as? Feed,
|
||||
let feed = node.representedObject as? WebFeed,
|
||||
let url = URL(string: feed.url) else {
|
||||
return nil
|
||||
}
|
||||
@@ -857,7 +857,7 @@ private extension MasterFeedViewController {
|
||||
|
||||
func copyFeedPageAlertAction(indexPath: IndexPath, completionHandler: @escaping (Bool) -> Void) -> UIAlertAction? {
|
||||
guard let node = dataSource.itemIdentifier(for: indexPath),
|
||||
let feed = node.representedObject as? Feed,
|
||||
let feed = node.representedObject as? WebFeed,
|
||||
let url = URL(string: feed.url) else {
|
||||
return nil
|
||||
}
|
||||
@@ -872,7 +872,7 @@ private extension MasterFeedViewController {
|
||||
|
||||
func copyHomePageAction(indexPath: IndexPath) -> UIAction? {
|
||||
guard let node = dataSource.itemIdentifier(for: indexPath),
|
||||
let feed = node.representedObject as? Feed,
|
||||
let feed = node.representedObject as? WebFeed,
|
||||
let homePageURL = feed.homePageURL,
|
||||
let url = URL(string: homePageURL) else {
|
||||
return nil
|
||||
@@ -887,7 +887,7 @@ private extension MasterFeedViewController {
|
||||
|
||||
func copyHomePageAlertAction(indexPath: IndexPath, completionHandler: @escaping (Bool) -> Void) -> UIAlertAction? {
|
||||
guard let node = dataSource.itemIdentifier(for: indexPath),
|
||||
let feed = node.representedObject as? Feed,
|
||||
let feed = node.representedObject as? WebFeed,
|
||||
let homePageURL = feed.homePageURL,
|
||||
let url = URL(string: homePageURL) else {
|
||||
return nil
|
||||
@@ -919,7 +919,7 @@ private extension MasterFeedViewController {
|
||||
}
|
||||
|
||||
func getInfoAction(indexPath: IndexPath) -> UIAction? {
|
||||
guard let node = dataSource.itemIdentifier(for: indexPath), let feed = node.representedObject as? Feed else {
|
||||
guard let node = dataSource.itemIdentifier(for: indexPath), let feed = node.representedObject as? WebFeed else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -947,7 +947,7 @@ private extension MasterFeedViewController {
|
||||
}
|
||||
|
||||
func getInfoAlertAction(indexPath: IndexPath, completionHandler: @escaping (Bool) -> Void) -> UIAlertAction? {
|
||||
guard let node = dataSource.itemIdentifier(for: indexPath), let feed = node.representedObject as? Feed else {
|
||||
guard let node = dataSource.itemIdentifier(for: indexPath), let feed = node.representedObject as? WebFeed else {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -979,7 +979,7 @@ private extension MasterFeedViewController {
|
||||
return
|
||||
}
|
||||
|
||||
if let feed = node.representedObject as? Feed {
|
||||
if let feed = node.representedObject as? WebFeed {
|
||||
feed.rename(to: name) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
@@ -1023,7 +1023,7 @@ private extension MasterFeedViewController {
|
||||
|
||||
if let folder = deleteNode.representedObject as? Folder {
|
||||
ActivityManager.cleanUp(folder)
|
||||
} else if let feed = deleteNode.representedObject as? Feed {
|
||||
} else if let feed = deleteNode.representedObject as? WebFeed {
|
||||
ActivityManager.cleanUp(feed)
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(statusesDidChange(_:)), name: .StatusesDidChange, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(feedIconDidBecomeAvailable(_:)), name: .FeedIconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(webFeedIconDidBecomeAvailable(_:)), name: .WebFeedIconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(avatarDidBecomeAvailable(_:)), name: .AvatarDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil)
|
||||
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil)
|
||||
@@ -316,16 +316,16 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
}
|
||||
}
|
||||
|
||||
@objc func feedIconDidBecomeAvailable(_ note: Notification) {
|
||||
@objc func webFeedIconDidBecomeAvailable(_ note: Notification) {
|
||||
titleView?.iconView.iconImage = coordinator.timelineIconImage
|
||||
guard let feed = note.userInfo?[UserInfoKey.feed] as? Feed else {
|
||||
guard let feed = note.userInfo?[UserInfoKey.webFeed] as? WebFeed else {
|
||||
return
|
||||
}
|
||||
tableView.indexPathsForVisibleRows?.forEach { indexPath in
|
||||
guard let article = dataSource.itemIdentifier(for: indexPath) else {
|
||||
return
|
||||
}
|
||||
if article.feed == feed, let cell = tableView.cellForRow(at: indexPath) as? MasterTimelineTableViewCell, let image = iconImageFor(article) {
|
||||
if article.webFeed == feed, let cell = tableView.cellForRow(at: indexPath) as? MasterTimelineTableViewCell, let image = iconImageFor(article) {
|
||||
cell.setIconImage(image)
|
||||
}
|
||||
}
|
||||
@@ -402,7 +402,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
||||
|
||||
let prototypeID = "prototype"
|
||||
let status = ArticleStatus(articleID: prototypeID, read: false, starred: false, userDeleted: 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, bannerImageURL: nil, datePublished: nil, dateModified: nil, authors: nil, attachments: nil, status: status)
|
||||
let prototypeArticle = Article(accountID: prototypeID, articleID: prototypeID, webFeedID: prototypeID, uniqueID: prototypeID, title: longTitle, contentHTML: nil, contentText: nil, url: nil, externalURL: nil, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: nil, dateModified: nil, authors: nil, attachments: nil, status: status)
|
||||
|
||||
let prototypeCellData = MasterTimelineCellData(article: prototypeArticle, showFeedName: true, feedName: "Prototype Feed Name", iconImage: nil, showIcon: false, featuredImage: nil, numberOfLines: numberOfTextLines, iconSize: iconSize)
|
||||
|
||||
@@ -464,7 +464,7 @@ private extension MasterTimelineViewController {
|
||||
titleView.label.text = coordinator.timelineName
|
||||
updateTitleUnreadCount()
|
||||
|
||||
if coordinator.timelineFetcher is Feed {
|
||||
if coordinator.timelineFetcher is WebFeed {
|
||||
titleView.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
|
||||
let tap = UITapGestureRecognizer(target: self, action:#selector(showFeedInspector(_:)))
|
||||
titleView.addGestureRecognizer(tap)
|
||||
@@ -525,7 +525,7 @@ private extension MasterTimelineViewController {
|
||||
|
||||
let showFeedNames = coordinator.showFeedNames
|
||||
let showIcon = coordinator.showIcons && iconImage != nil
|
||||
cell.cellData = MasterTimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.feed?.nameForDisplay, iconImage: iconImage, showIcon: showIcon, featuredImage: featuredImage, numberOfLines: numberOfTextLines, iconSize: iconSize)
|
||||
cell.cellData = MasterTimelineCellData(article: article, showFeedName: showFeedNames, feedName: article.webFeed?.nameForDisplay, iconImage: iconImage, showIcon: showIcon, featuredImage: featuredImage, numberOfLines: numberOfTextLines, iconSize: iconSize)
|
||||
|
||||
}
|
||||
|
||||
@@ -590,36 +590,36 @@ private extension MasterTimelineViewController {
|
||||
}
|
||||
|
||||
func discloseFeedAction(_ article: Article) -> UIAction? {
|
||||
guard let feed = article.feed else { return nil }
|
||||
guard let webFeed = article.webFeed else { return nil }
|
||||
|
||||
let title = NSLocalizedString("Go to Feed", comment: "Go to Feed")
|
||||
let action = UIAction(title: title, image: AppAssets.openInSidebarImage) { [weak self] action in
|
||||
self?.coordinator.discloseFeed(feed, animated: true)
|
||||
self?.coordinator.discloseFeed(webFeed, animated: true)
|
||||
}
|
||||
return action
|
||||
}
|
||||
|
||||
func discloseFeedAlertAction(_ article: Article, completionHandler: @escaping (Bool) -> Void) -> UIAlertAction? {
|
||||
guard let feed = article.feed else { return nil }
|
||||
guard let webFeed = article.webFeed else { return nil }
|
||||
|
||||
let title = NSLocalizedString("Go to Feed", comment: "Go to Feed")
|
||||
let action = UIAlertAction(title: title, style: .default) { [weak self] action in
|
||||
self?.coordinator.discloseFeed(feed, animated: true)
|
||||
self?.coordinator.discloseFeed(webFeed, animated: true)
|
||||
completionHandler(true)
|
||||
}
|
||||
return action
|
||||
}
|
||||
|
||||
func markAllInFeedAsReadAction(_ article: Article) -> UIAction? {
|
||||
guard let feed = article.feed else { return nil }
|
||||
guard let webFeed = article.webFeed else { return nil }
|
||||
|
||||
let articles = Array(feed.fetchArticles())
|
||||
let articles = Array(webFeed.fetchArticles())
|
||||
guard articles.canMarkAllAsRead() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let localizedMenuText = NSLocalizedString("Mark All as Read in “%@”", comment: "Command")
|
||||
let title = NSString.localizedStringWithFormat(localizedMenuText as NSString, feed.nameForDisplay) as String
|
||||
let title = NSString.localizedStringWithFormat(localizedMenuText as NSString, webFeed.nameForDisplay) as String
|
||||
|
||||
let action = UIAction(title: title, image: AppAssets.markAllInFeedAsReadImage) { [weak self] action in
|
||||
self?.coordinator.markAllAsRead(articles)
|
||||
@@ -628,15 +628,15 @@ private extension MasterTimelineViewController {
|
||||
}
|
||||
|
||||
func markAllInFeedAsReadAlertAction(_ article: Article, completionHandler: @escaping (Bool) -> Void) -> UIAlertAction? {
|
||||
guard let feed = article.feed else { return nil }
|
||||
guard let webFeed = article.webFeed else { return nil }
|
||||
|
||||
let articles = Array(feed.fetchArticles())
|
||||
let articles = Array(webFeed.fetchArticles())
|
||||
guard articles.canMarkAllAsRead() else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let localizedMenuText = NSLocalizedString("Mark All as Read in “%@”", comment: "Mark All as Read in Feed")
|
||||
let title = NSString.localizedStringWithFormat(localizedMenuText as NSString, feed.nameForDisplay) as String
|
||||
let title = NSString.localizedStringWithFormat(localizedMenuText as NSString, webFeed.nameForDisplay) as String
|
||||
|
||||
let action = UIAlertAction(title: title, style: .default) { [weak self] action in
|
||||
self?.coordinator.markAllAsRead(articles)
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<string>Grant permission to save images from the article.</string>
|
||||
<key>NSUserActivityTypes</key>
|
||||
<array>
|
||||
<string>AddFeedIntent</string>
|
||||
<string>AddWebFeedIntent</string>
|
||||
<string>NextUnread</string>
|
||||
<string>ReadArticle</string>
|
||||
<string>SelectFeed</string>
|
||||
|
||||
@@ -88,7 +88,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
||||
set { AppDefaults.displayUndoAvailableTip = newValue }
|
||||
}
|
||||
|
||||
private let treeControllerDelegate = FeedTreeControllerDelegate()
|
||||
private let treeControllerDelegate = WebFeedTreeControllerDelegate()
|
||||
private let treeController: TreeController
|
||||
|
||||
var stateRestorationActivity: NSUserActivity? {
|
||||
@@ -110,9 +110,9 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
||||
private(set) var currentFeedIndexPath: IndexPath?
|
||||
|
||||
var timelineIconImage: IconImage? {
|
||||
if let feed = timelineFetcher as? Feed {
|
||||
if let feed = timelineFetcher as? WebFeed {
|
||||
|
||||
let feedIconImage = appDelegate.feedIconDownloader.icon(for: feed)
|
||||
let feedIconImage = appDelegate.webFeedIconDownloader.icon(for: feed)
|
||||
if feedIconImage != nil {
|
||||
return feedIconImage
|
||||
}
|
||||
@@ -135,7 +135,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
||||
|
||||
timelineMiddleIndexPath = nil
|
||||
|
||||
if timelineFetcher is Feed {
|
||||
if timelineFetcher is WebFeed {
|
||||
showFeedNames = false
|
||||
} else {
|
||||
showFeedNames = true
|
||||
@@ -442,7 +442,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
||||
}
|
||||
|
||||
@objc func accountDidDownloadArticles(_ note: Notification) {
|
||||
guard let feeds = note.userInfo?[Account.UserInfoKey.feeds] as? Set<Feed> else {
|
||||
guard let feeds = note.userInfo?[Account.UserInfoKey.webFeeds] as? Set<WebFeed> else {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -607,7 +607,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
||||
|
||||
masterTimelineViewController?.updateArticleSelection(animated: animated)
|
||||
|
||||
if article!.feed?.isArticleExtractorAlwaysOn ?? false {
|
||||
if article!.webFeed?.isArticleExtractorAlwaysOn ?? false {
|
||||
startArticleExtractorForCurrentLink()
|
||||
currentArticleViewController.state = .loading
|
||||
} else {
|
||||
@@ -780,7 +780,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
||||
markArticlesWithUndo([article], statusKey: .starred, flag: !article.status.starred)
|
||||
}
|
||||
|
||||
func discloseFeed(_ feed: Feed, animated: Bool, completion: (() -> Void)? = nil) {
|
||||
func discloseFeed(_ feed: WebFeed, animated: Bool, completion: (() -> Void)? = nil) {
|
||||
masterFeedViewController.discloseFeed(feed, animated: animated) {
|
||||
completion?()
|
||||
}
|
||||
@@ -806,19 +806,19 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
||||
}
|
||||
|
||||
func showFeedInspector() {
|
||||
guard let feed = timelineFetcher as? Feed else {
|
||||
guard let feed = timelineFetcher as? WebFeed else {
|
||||
return
|
||||
}
|
||||
showFeedInspector(for: feed)
|
||||
}
|
||||
|
||||
func showFeedInspector(for feed: Feed) {
|
||||
func showFeedInspector(for feed: WebFeed) {
|
||||
let feedInspectorNavController =
|
||||
UIStoryboard.inspector.instantiateViewController(identifier: "FeedInspectorNavigationViewController") as! UINavigationController
|
||||
let feedInspectorController = feedInspectorNavController.topViewController as! FeedInspectorViewController
|
||||
let feedInspectorController = feedInspectorNavController.topViewController as! WebFeedInspectorViewController
|
||||
feedInspectorNavController.modalPresentationStyle = .formSheet
|
||||
feedInspectorNavController.preferredContentSize = FeedInspectorViewController.preferredContentSizeForFormSheetDisplay
|
||||
feedInspectorController.feed = feed
|
||||
feedInspectorNavController.preferredContentSize = WebFeedInspectorViewController.preferredContentSizeForFormSheetDisplay
|
||||
feedInspectorController.webFeed = feed
|
||||
rootSplitViewController.present(feedInspectorNavController, animated: true)
|
||||
}
|
||||
|
||||
@@ -878,7 +878,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
||||
|
||||
func homePageURLForFeed(_ indexPath: IndexPath) -> URL? {
|
||||
guard let node = nodeFor(indexPath),
|
||||
let feed = node.representedObject as? Feed,
|
||||
let feed = node.representedObject as? WebFeed,
|
||||
let homePageURL = feed.homePageURL,
|
||||
let url = URL(string: homePageURL) else {
|
||||
return nil
|
||||
@@ -1460,19 +1460,19 @@ private extension SceneCoordinator {
|
||||
return false
|
||||
}
|
||||
|
||||
func timelineFetcherContainsAnyFeed(_ feeds: Set<Feed>) -> Bool {
|
||||
func timelineFetcherContainsAnyFeed(_ feeds: Set<WebFeed>) -> Bool {
|
||||
|
||||
// Return true if there’s a match or if a folder contains (recursively) one of feeds
|
||||
|
||||
if let feed = timelineFetcher as? Feed {
|
||||
if let feed = timelineFetcher as? WebFeed {
|
||||
for oneFeed in feeds {
|
||||
if feed.feedID == oneFeed.feedID || feed.url == oneFeed.url {
|
||||
if feed.webFeedID == oneFeed.webFeedID || feed.url == oneFeed.url {
|
||||
return true
|
||||
}
|
||||
}
|
||||
} else if let folder = timelineFetcher as? Folder {
|
||||
for oneFeed in feeds {
|
||||
if folder.hasFeed(with: oneFeed.feedID) || folder.hasFeed(withURL: oneFeed.url) {
|
||||
if folder.hasWebFeed(with: oneFeed.webFeedID) || folder.hasWebFeed(withURL: oneFeed.url) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1648,11 +1648,11 @@ private extension SceneCoordinator {
|
||||
selectFeed(indexPath, animated: false)
|
||||
}
|
||||
|
||||
case .feed(let accountID, let feedID):
|
||||
guard let accountNode = findAccountNode(accountID: accountID), let feedNode = findFeedNode(feedID: feedID, beginningAt: accountNode) else {
|
||||
case .webFeed(let accountID, let webFeedID):
|
||||
guard let accountNode = findAccountNode(accountID: accountID), let feedNode = findWebFeedNode(webFeedID: webFeedID, beginningAt: accountNode) else {
|
||||
return
|
||||
}
|
||||
if let feed = feedNode.representedObject as? Feed {
|
||||
if let feed = feedNode.representedObject as? WebFeed {
|
||||
discloseFeed(feed, animated: false)
|
||||
}
|
||||
|
||||
@@ -1664,16 +1664,16 @@ private extension SceneCoordinator {
|
||||
let articlePathUserInfo = userInfo[UserInfoKey.articlePath] as? [AnyHashable : Any],
|
||||
let accountID = articlePathUserInfo[ArticlePathKey.accountID] as? String,
|
||||
let accountName = articlePathUserInfo[ArticlePathKey.accountName] as? String,
|
||||
let feedID = articlePathUserInfo[ArticlePathKey.feedID] as? String,
|
||||
let webFeedID = articlePathUserInfo[ArticlePathKey.webFeedID] as? String,
|
||||
let articleID = articlePathUserInfo[ArticlePathKey.articleID] as? String else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let accountNode = findAccountNode(accountID: accountID, accountName: accountName), let feedNode = findFeedNode(feedID: feedID, beginningAt: accountNode) else {
|
||||
guard let accountNode = findAccountNode(accountID: accountID, accountName: accountName), let feedNode = findWebFeedNode(webFeedID: webFeedID, beginningAt: accountNode) else {
|
||||
return
|
||||
}
|
||||
|
||||
discloseFeed(feedNode.representedObject as! Feed, animated: false) {
|
||||
discloseFeed(feedNode.representedObject as! WebFeed, animated: false) {
|
||||
if let article = self.articles.first(where: { $0.articleID == articleID }) {
|
||||
self.selectArticle(article)
|
||||
}
|
||||
@@ -1699,8 +1699,8 @@ private extension SceneCoordinator {
|
||||
return nil
|
||||
}
|
||||
|
||||
func findFeedNode(feedID: String, beginningAt startingNode: Node) -> Node? {
|
||||
if let node = startingNode.descendantNode(where: { ($0.representedObject as? Feed)?.feedID == feedID }) {
|
||||
func findWebFeedNode(webFeedID: String, beginningAt startingNode: Node) -> Node? {
|
||||
if let node = startingNode.descendantNode(where: { ($0.representedObject as? WebFeed)?.webFeedID == webFeedID }) {
|
||||
return node
|
||||
}
|
||||
return nil
|
||||
|
||||
@@ -67,7 +67,7 @@ private extension TimelinePreviewTableViewController {
|
||||
|
||||
let prototypeID = "prototype"
|
||||
let status = ArticleStatus(articleID: prototypeID, read: false, starred: false, userDeleted: 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, bannerImageURL: nil, datePublished: nil, dateModified: nil, authors: nil, attachments: nil, status: status)
|
||||
let prototypeArticle = Article(accountID: prototypeID, articleID: prototypeID, webFeedID: prototypeID, uniqueID: prototypeID, title: longTitle, contentHTML: nil, contentText: nil, url: nil, externalURL: nil, summary: nil, imageURL: nil, bannerImageURL: nil, datePublished: nil, dateModified: nil, authors: nil, attachments: nil, status: status)
|
||||
|
||||
let iconImage = IconImage(AppAssets.faviconTemplateImage.withTintColor(AppAssets.secondaryAccentColor))
|
||||
|
||||
|
||||
@@ -108,14 +108,14 @@ class ShareViewController: SLComposeServiceViewController, ShareFolderPickerCont
|
||||
account = containerAccount
|
||||
}
|
||||
|
||||
if let urlString = url?.absoluteString, account!.hasFeed(withURL: urlString) {
|
||||
if let urlString = url?.absoluteString, account!.hasWebFeed(withURL: urlString) {
|
||||
presentError(AccountError.createErrorAlreadySubscribed)
|
||||
return
|
||||
}
|
||||
|
||||
let feedName = contentText.isEmpty ? nil : contentText
|
||||
|
||||
account!.createFeed(url: url!.absoluteString, name: feedName, container: container!) { result in
|
||||
account!.createWebFeed(url: url!.absoluteString, name: feedName, container: container!) { result in
|
||||
|
||||
switch result {
|
||||
case .success:
|
||||
|
||||
Reference in New Issue
Block a user