Continue removing feed provider and extension point references.

This commit is contained in:
Brent Simmons
2023-06-30 21:47:17 -07:00
parent 48ff7ec80d
commit d309c05cb0
17 changed files with 52 additions and 323 deletions

View File

@@ -181,12 +181,7 @@ final class CloudKitAccountDelegate: AccountDelegate, Logging {
let editedName = name == nil || name!.isEmpty ? nil : name
// Username should be part of the URL on new feed adds
if let feedProvider = FeedProviderManager.shared.best(for: urlComponents) {
createProviderWebFeed(for: account, urlComponents: urlComponents, editedName: editedName, container: container, feedProvider: feedProvider, completion: completion)
} else {
createRSSWebFeed(for: account, url: url, editedName: editedName, container: container, validateFeed: validateFeed, completion: completion)
}
createRSSWebFeed(for: account, url: url, editedName: editedName, container: container, validateFeed: validateFeed, completion: completion)
}
func renameWebFeed(for account: Account, with feed: WebFeed, to name: String, completion: @escaping (Result<Void, Error>) -> Void) {
@@ -570,123 +565,19 @@ private extension CloudKitAccountDelegate {
}
func combinedRefresh(_ account: Account, _ webFeeds: Set<WebFeed>, completion: @escaping (Result<Void, Error>) -> Void) {
var refresherWebFeeds = Set<WebFeed>()
let group = DispatchGroup()
var feedProviderError: Error? = nil
for webFeed in webFeeds {
if let components = URLComponents(string: webFeed.url), let feedProvider = FeedProviderManager.shared.best(for: components) {
group.enter()
feedProvider.refresh(webFeed) { result in
switch result {
case .success(let parsedItems):
account.update(webFeed.webFeedID, with: parsedItems) { result in
switch result {
case .success(let articleChanges):
self.storeArticleChanges(new: articleChanges.newArticles, updated: articleChanges.updatedArticles, deleted: articleChanges.deletedArticles) {
self.refreshProgress.completeTask()
group.leave()
}
case .failure(let error):
self.logger.error("CloudKit Feed refresh update error: \(error.localizedDescription, privacy: .public)")
self.refreshProgress.completeTask()
group.leave()
}
}
func combinedRefresh(_ account: Account, _ webFeeds: Set<WebFeed>, completion: @escaping (Result<Void, Error>) -> Void) {
case .failure(let error):
self.logger.error("CloudKit Feed refresh error: \(error.localizedDescription, privacy: .public)")
feedProviderError = error
self.refreshProgress.completeTask()
group.leave()
}
}
} else {
refresherWebFeeds.insert(webFeed)
}
}
group.enter()
refresher.refreshFeeds(refresherWebFeeds) {
group.leave()
}
group.notify(queue: DispatchQueue.main) {
if let error = feedProviderError {
completion(.failure(error))
} else {
completion(.success(()))
}
}
let group = DispatchGroup()
}
group.enter()
refresher.refreshFeeds(webFeeds) {
group.leave()
}
func createProviderWebFeed(for account: Account, urlComponents: URLComponents, editedName: String?, container: Container, feedProvider: FeedProvider, completion: @escaping (Result<WebFeed, Error>) -> Void) {
refreshProgress.addToNumberOfTasksAndRemaining(5)
feedProvider.metaData(urlComponents) { result in
self.refreshProgress.completeTask()
switch result {
case .success(let metaData):
guard let urlString = urlComponents.url?.absoluteString else {
self.refreshProgress.completeTasks(4)
completion(.failure(AccountError.createErrorNotFound))
return
}
self.accountZone.createWebFeed(url: urlString, name: metaData.name, editedName: editedName, homePageURL: metaData.homePageURL, container: container) { result in
self.refreshProgress.completeTask()
switch result {
case .success(let externalID):
let feed = account.createWebFeed(with: metaData.name, url: urlString, webFeedID: urlString, homePageURL: metaData.homePageURL)
feed.editedName = editedName
feed.externalID = externalID
container.addWebFeed(feed)
feedProvider.refresh(feed) { result in
self.refreshProgress.completeTask()
switch result {
case .success(let parsedItems):
account.update(urlString, with: parsedItems) { result in
switch result {
case .success:
self.sendNewArticlesToTheCloud(account, feed)
self.refreshProgress.clear()
completion(.success(feed))
case .failure(let error):
self.refreshProgress.completeTasks(2)
completion(.failure(error))
}
}
case .failure:
self.refreshProgress.completeTasks(3)
completion(.failure(AccountError.createErrorNotFound))
}
}
case .failure(let error):
self.refreshProgress.completeTasks(4)
completion(.failure(error))
}
}
case .failure:
self.refreshProgress.completeTasks(4)
completion(.failure(AccountError.createErrorNotFound))
}
}
}
group.notify(queue: DispatchQueue.main) {
completion(.success(()))
}
}
func createRSSWebFeed(for account: Account, url: URL, editedName: String?, container: Container, validateFeed: Bool, completion: @escaping (Result<WebFeed, Error>) -> Void) {

View File

@@ -41,57 +41,29 @@ final class LocalAccountDelegate: AccountDelegate, Logging {
completion()
}
func refreshAll(for account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
guard refreshProgress.isComplete else {
completion(.success(()))
return
}
func refreshAll(for account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
guard refreshProgress.isComplete else {
completion(.success(()))
return
}
var refresherWebFeeds = Set<WebFeed>()
let webFeeds = account.flattenedWebFeeds()
refreshProgress.addToNumberOfTasksAndRemaining(webFeeds.count)
let webFeeds = account.flattenedWebFeeds()
refreshProgress.addToNumberOfTasksAndRemaining(webFeeds.count)
let group = DispatchGroup()
group.enter()
refresher?.refreshFeeds(webFeeds) {
group.leave()
}
group.notify(queue: DispatchQueue.main) {
self.refreshProgress.clear()
account.metadata.lastArticleFetchEndTime = Date()
completion(.success(()))
}
}
let group = DispatchGroup()
var feedProviderError: Error? = nil
for webFeed in webFeeds {
if let components = URLComponents(string: webFeed.url), let feedProvider = FeedProviderManager.shared.best(for: components) {
group.enter()
feedProvider.refresh(webFeed) { result in
switch result {
case .success(let parsedItems):
account.update(webFeed.webFeedID, with: parsedItems) { _ in
self.refreshProgress.completeTask()
group.leave()
}
case .failure(let error):
self.logger.error("Feed Provided refresh error: \(error.localizedDescription, privacy: .public)")
feedProviderError = error
self.refreshProgress.completeTask()
group.leave()
}
}
} else {
refresherWebFeeds.insert(webFeed)
}
}
group.enter()
refresher?.refreshFeeds(refresherWebFeeds) {
group.leave()
}
group.notify(queue: DispatchQueue.main) {
self.refreshProgress.clear()
account.metadata.lastArticleFetchEndTime = Date()
if let error = feedProviderError {
completion(.failure(error))
} else {
completion(.success(()))
}
}
}
func syncArticleStatus(for account: Account, completion: ((Result<Void, Error>) -> Void)? = nil) {
completion?(.success(()))
@@ -154,11 +126,7 @@ final class LocalAccountDelegate: AccountDelegate, Logging {
}
// Username should be part of the URL on new feed adds
if let feedProvider = FeedProviderManager.shared.best(for: urlComponents) {
createProviderWebFeed(for: account, urlComponents: urlComponents, editedName: name, container: container, feedProvider: feedProvider, completion: completion)
} else {
createRSSWebFeed(for: account, url: url, editedName: name, container: container, completion: completion)
}
createRSSWebFeed(for: account, url: url, editedName: name, container: container, completion: completion)
}
func renameWebFeed(for account: Account, with feed: WebFeed, to name: String, completion: @escaping (Result<Void, Error>) -> Void) {
@@ -263,44 +231,6 @@ extension LocalAccountDelegate: LocalAccountRefresherDelegate {
private extension LocalAccountDelegate {
func createProviderWebFeed(for account: Account, urlComponents: URLComponents, editedName: String?, container: Container, feedProvider: FeedProvider, completion: @escaping (Result<WebFeed, Error>) -> Void) {
refreshProgress.addToNumberOfTasksAndRemaining(2)
feedProvider.metaData(urlComponents) { result in
self.refreshProgress.completeTask()
switch result {
case .success(let metaData):
guard let urlString = urlComponents.url?.absoluteString else {
completion(.failure(AccountError.createErrorNotFound))
return
}
let feed = account.createWebFeed(with: metaData.name, url: urlString, webFeedID: urlString, homePageURL: metaData.homePageURL)
feed.editedName = editedName
container.addWebFeed(feed)
feedProvider.refresh(feed) { result in
self.refreshProgress.completeTask()
switch result {
case .success(let parsedItems):
account.update(urlString, with: parsedItems) { _ in
completion(.success(feed))
}
case .failure(let error):
self.refreshProgress.clear()
completion(.failure(error))
}
}
case .failure:
self.refreshProgress.clear()
completion(.failure(AccountError.createErrorNotFound))
}
}
}
func createRSSWebFeed(for account: Account, url: URL, editedName: String?, container: Container, completion: @escaping (Result<WebFeed, Error>) -> Void) {
// We need to use a batch update here because we need to assign add the feed to the

View File

@@ -152,15 +152,10 @@ public final class WebFeed: Feed, Renamable, Hashable, ObservableObject {
public var isArticleExtractorAlwaysOn: Bool? {
get {
if isFeedProvider == true { return false } // not an option for FeedProviders
return metadata.isArticleExtractorAlwaysOn
metadata.isArticleExtractorAlwaysOn
}
set {
if isFeedProvider == true {
metadata.isArticleExtractorAlwaysOn = false
return
}
metadata.isArticleExtractorAlwaysOn = newValue
metadata.isArticleExtractorAlwaysOn = newValue
}
}
@@ -235,21 +230,6 @@ public final class WebFeed: Feed, Renamable, Hashable, ObservableObject {
}
}
// MARK: - Feed Provider
public var isFeedProvider: Bool {
get {
guard let webfeedURL = URL(string: url),
let components = URLComponents(url: webfeedURL, resolvingAgainstBaseURL: false) else {
return false
}
if FeedProviderManager.shared.best(for: components) == nil {
return false
}
return true
}
}
// MARK: - NotificationDisplayName
public var notificationDisplayName: String {
#if os(macOS)

View File

@@ -72,14 +72,14 @@ struct AppAssets {
return NSImage(systemSymbolName: "wind", accessibilityDescription: nil)!
}()
static var extensionPointMarsEdit: RSImage = {
return RSImage(named: "extensionPointMarsEdit")!
static var marsEditIcon: RSImage = {
return RSImage(named: "MarsEditIcon")!
}()
static var extensionPointMicroblog: RSImage = {
return RSImage(named: "extensionPointMicroblog")!
static var microblogIcon: RSImage = {
return RSImage(named: "MicroblogIcon")!
}()
static var faviconTemplateImage: RSImage = {
return RSImage(named: "faviconTemplateImage")!
}()

View File

@@ -141,7 +141,7 @@ private extension WebFeedInspectorViewController {
windowTitle = feed?.nameForDisplay ?? NSLocalizedString("window.title.feed-inspector", comment: "Feed Inspector")
view.needsLayout = true
if let webfeed = feed {
webfeed.isFeedProvider ? (isReaderViewAlwaysOnCheckBox?.isEnabled = false) : (isReaderViewAlwaysOnCheckBox?.isEnabled = true)
isReaderViewAlwaysOnCheckBox?.isEnabled = true
}
}

View File

@@ -1192,12 +1192,7 @@ private extension MainWindowController {
}
if let webfeed = currentTimelineViewController?.selectedArticles.first?.webFeed {
if webfeed.isFeedProvider {
toolbarButton.isEnabled = false
return false
} else {
toolbarButton.isEnabled = true
}
toolbarButton.isEnabled = true
}
guard let state = articleExtractor?.state else {

View File

@@ -304,19 +304,15 @@ private extension SidebarViewController {
}
menu.addItem(notificationMenuItem)
let articleExtractorText = NSLocalizedString("button.title.always-use-reader-view", comment: "Always Use Reader View")
let articleExtractorMenuItem = menuItem(articleExtractorText, #selector(toggleArticleExtractorFromContextMenu(_:)), webFeed)
if !webFeed.isFeedProvider {
let articleExtractorText = NSLocalizedString("button.title.always-use-reader-view", comment: "Always Use Reader View")
let articleExtractorMenuItem = menuItem(articleExtractorText, #selector(toggleArticleExtractorFromContextMenu(_:)), webFeed)
if webFeed.isArticleExtractorAlwaysOn == nil || webFeed.isArticleExtractorAlwaysOn! == false {
articleExtractorMenuItem.state = .off
} else {
articleExtractorMenuItem.state = .on
}
menu.addItem(articleExtractorMenuItem)
if webFeed.isArticleExtractorAlwaysOn == nil || webFeed.isArticleExtractorAlwaysOn! == false {
articleExtractorMenuItem.state = .off
} else {
articleExtractorMenuItem.state = .on
}
menu.addItem(articleExtractorMenuItem)
menu.addItem(NSMenuItem.separator())

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@@ -1,25 +0,0 @@
{
"images" : [
{
"filename" : "micro.blog.24.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "micro.blog.48.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "original"
}
}

View File

@@ -118,31 +118,7 @@ public final class WebFeedIconDownloader {
return nil
}
if let components = URLComponents(string: feed.url), let feedProvider = FeedProviderManager.shared.best(for: components) {
guard !urlsInProgress.contains(feed.url) else {
return nil
}
urlsInProgress.insert(feed.url)
feedProvider.iconURL(components) { result in
self.urlsInProgress.remove(feed.url)
switch result {
case .success(let feedProviderURL):
self.feedURLToIconURLCache[feed.url] = feedProviderURL
self.feedURLToIconURLCacheDirty = true
self.icon(forURL: feedProviderURL, feed: feed) { (image) in
if let image = image {
self.postFeedIconDidBecomeAvailableNotification(feed)
self.cache[feed] = IconImage(image)
}
}
case .failure:
checkFeedIconURL()
}
}
} else {
checkFeedIconURL()
}
checkFeedIconURL()
return nil
}

View File

@@ -71,8 +71,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
let documentThemesFolderPath = String(documentThemesFolder.suffix(from: documentAccountsFolder.index(documentThemesFolder.startIndex, offsetBy: 7)))
ArticleThemesManager.shared = ArticleThemesManager(folderPath: documentThemesFolderPath)
FeedProviderManager.shared.delegate = ExtensionPointManager.shared
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil)
}

View File

@@ -210,11 +210,7 @@ class ArticleViewController: UIViewController, MainControllerIdentifiable, Loggi
appearanceBarButtonItem.isEnabled = true
let permalinkPresent = article.preferredLink != nil
var isFeedProvider = false
if let webfeed = article.webFeed {
isFeedProvider = webfeed.isFeedProvider
}
articleExtractorButton.isEnabled = permalinkPresent && !AppDefaults.shared.isDeveloperBuild && !isFeedProvider
articleExtractorButton.isEnabled = permalinkPresent && !AppDefaults.shared.isDeveloperBuild
actionBarButtonItem.isEnabled = permalinkPresent
if article.status.read {

View File

@@ -31,14 +31,6 @@ struct WebFeedInspectorView: View {
Toggle(isOn: Binding(get: { webFeed.isNotifyAboutNewArticles ?? false }, set: { webFeed.isNotifyAboutNewArticles = $0 })) {
Text("toggle.title.notify-about-new-articles", comment: "New Article Notifications")
}
if webFeed.isFeedProvider == false {
Toggle(isOn: Binding(
get: { webFeed.isArticleExtractorAlwaysOn ?? false },
set: { webFeed.isArticleExtractorAlwaysOn = $0 })) {
Text("toggle.title.always-show-reader-view", comment: "Always Show Reader View")
}
}
}
Section(header: Text("label.text.home-page", comment: "Home Page")) {