diff --git a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift index 07079b5fe..8db5d4bbe 100644 --- a/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift +++ b/Account/Sources/Account/CloudKit/CloudKitAccountDelegate.swift @@ -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) { @@ -570,123 +565,19 @@ private extension CloudKitAccountDelegate { } - func combinedRefresh(_ account: Account, _ webFeeds: Set, completion: @escaping (Result) -> Void) { - - var refresherWebFeeds = Set() - 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, completion: @escaping (Result) -> 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) -> 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) -> Void) { diff --git a/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift b/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift index cfe18af77..5642f1881 100644 --- a/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift +++ b/Account/Sources/Account/LocalAccount/LocalAccountDelegate.swift @@ -41,57 +41,29 @@ final class LocalAccountDelegate: AccountDelegate, Logging { completion() } - func refreshAll(for account: Account, completion: @escaping (Result) -> Void) { - guard refreshProgress.isComplete else { - completion(.success(())) - return - } + func refreshAll(for account: Account, completion: @escaping (Result) -> Void) { + guard refreshProgress.isComplete else { + completion(.success(())) + return + } - var refresherWebFeeds = Set() - 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)? = 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) { @@ -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) -> 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) -> Void) { // We need to use a batch update here because we need to assign add the feed to the diff --git a/Account/Sources/Account/WebFeed.swift b/Account/Sources/Account/WebFeed.swift index aad148c41..c8b41f7d9 100644 --- a/Account/Sources/Account/WebFeed.swift +++ b/Account/Sources/Account/WebFeed.swift @@ -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) diff --git a/Mac/AppAssets.swift b/Mac/AppAssets.swift index 79a32cb85..a8647baf5 100644 --- a/Mac/AppAssets.swift +++ b/Mac/AppAssets.swift @@ -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")! }() diff --git a/Mac/Inspector/WebFeedInspectorViewController.swift b/Mac/Inspector/WebFeedInspectorViewController.swift index fb8ceecd0..816ea0842 100644 --- a/Mac/Inspector/WebFeedInspectorViewController.swift +++ b/Mac/Inspector/WebFeedInspectorViewController.swift @@ -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 } } diff --git a/Mac/MainWindow/MainWindowController.swift b/Mac/MainWindow/MainWindowController.swift index 4d6169d36..e327af466 100644 --- a/Mac/MainWindow/MainWindowController.swift +++ b/Mac/MainWindow/MainWindowController.swift @@ -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 { diff --git a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift index 0d05dc4e5..598ddafed 100644 --- a/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift +++ b/Mac/MainWindow/Sidebar/SidebarViewController+ContextualMenus.swift @@ -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()) diff --git a/Mac/Resources/Assets.xcassets/extensionPointMarsEdit.imageset/Contents.json b/Mac/Resources/Assets.xcassets/MarsEditIcon.imageset/Contents.json similarity index 100% rename from Mac/Resources/Assets.xcassets/extensionPointMarsEdit.imageset/Contents.json rename to Mac/Resources/Assets.xcassets/MarsEditIcon.imageset/Contents.json diff --git a/Mac/Resources/Assets.xcassets/extensionPointMarsEdit.imageset/MarsEdit4Icon24.png b/Mac/Resources/Assets.xcassets/MarsEditIcon.imageset/MarsEdit4Icon24.png similarity index 100% rename from Mac/Resources/Assets.xcassets/extensionPointMarsEdit.imageset/MarsEdit4Icon24.png rename to Mac/Resources/Assets.xcassets/MarsEditIcon.imageset/MarsEdit4Icon24.png diff --git a/Mac/Resources/Assets.xcassets/extensionPointMarsEdit.imageset/MarsEdit4Icon48.png b/Mac/Resources/Assets.xcassets/MarsEditIcon.imageset/MarsEdit4Icon48.png similarity index 100% rename from Mac/Resources/Assets.xcassets/extensionPointMarsEdit.imageset/MarsEdit4Icon48.png rename to Mac/Resources/Assets.xcassets/MarsEditIcon.imageset/MarsEdit4Icon48.png diff --git a/Mac/Resources/Assets.xcassets/extensionPointMicroblog.imageset/micro.blog.24.png b/Mac/Resources/Assets.xcassets/MicroblogIcon.imageset/micro.blog.24.png similarity index 100% rename from Mac/Resources/Assets.xcassets/extensionPointMicroblog.imageset/micro.blog.24.png rename to Mac/Resources/Assets.xcassets/MicroblogIcon.imageset/micro.blog.24.png diff --git a/Mac/Resources/Assets.xcassets/extensionPointMicroblog.imageset/micro.blog.48.png b/Mac/Resources/Assets.xcassets/MicroblogIcon.imageset/micro.blog.48.png similarity index 100% rename from Mac/Resources/Assets.xcassets/extensionPointMicroblog.imageset/micro.blog.48.png rename to Mac/Resources/Assets.xcassets/MicroblogIcon.imageset/micro.blog.48.png diff --git a/Mac/Resources/Assets.xcassets/extensionPointMicroblog.imageset/Contents.json b/Mac/Resources/Assets.xcassets/extensionPointMicroblog.imageset/Contents.json deleted file mode 100644 index acddc80fb..000000000 --- a/Mac/Resources/Assets.xcassets/extensionPointMicroblog.imageset/Contents.json +++ /dev/null @@ -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" - } -} diff --git a/Shared/Images/WebFeedIconDownloader.swift b/Shared/Images/WebFeedIconDownloader.swift index 6bdb648ab..06ba2b15a 100644 --- a/Shared/Images/WebFeedIconDownloader.swift +++ b/Shared/Images/WebFeedIconDownloader.swift @@ -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 } diff --git a/iOS/AppDelegate.swift b/iOS/AppDelegate.swift index 4cca26407..da6cccc5c 100644 --- a/iOS/AppDelegate.swift +++ b/iOS/AppDelegate.swift @@ -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) } diff --git a/iOS/Article/ArticleViewController.swift b/iOS/Article/ArticleViewController.swift index ac5aae104..f3761afcb 100644 --- a/iOS/Article/ArticleViewController.swift +++ b/iOS/Article/ArticleViewController.swift @@ -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 { diff --git a/iOS/Inspector/WebFeedInspectorView.swift b/iOS/Inspector/WebFeedInspectorView.swift index 1cf127e46..180bbbb53 100644 --- a/iOS/Inspector/WebFeedInspectorView.swift +++ b/iOS/Inspector/WebFeedInspectorView.swift @@ -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")) {