Filter async requests based on ReadFilter.
This commit is contained in:
parent
adbb5b6392
commit
6d8fca01ea
|
@ -11,8 +11,8 @@ import RSCore
|
|||
|
||||
public enum ReadFilter {
|
||||
case read
|
||||
case all
|
||||
case none
|
||||
case unavailable
|
||||
}
|
||||
|
||||
public protocol Feed: FeedIdentifiable, ArticleFetcher, DisplayNameProvider, UnreadCountProvider {
|
||||
|
|
|
@ -14,7 +14,7 @@ import Articles
|
|||
public final class WebFeed: Feed, Renamable, Hashable {
|
||||
|
||||
public var defaultReadFilter: ReadFilter {
|
||||
return .all
|
||||
return .none
|
||||
}
|
||||
|
||||
public var feedID: FeedIdentifier? {
|
||||
|
|
|
@ -1000,7 +1000,7 @@ private extension TimelineViewController {
|
|||
// if it’s been superseded by a newer fetch, or the timeline was emptied, etc., it won’t get called.
|
||||
precondition(Thread.isMainThread)
|
||||
cancelPendingAsyncFetches()
|
||||
let fetchOperation = FetchRequestOperation(id: fetchSerialNumber, representedObjects: representedObjects) { [weak self] (articles, operation) in
|
||||
let fetchOperation = FetchRequestOperation(id: fetchSerialNumber, readFilter: .none, representedObjects: representedObjects) { [weak self] (articles, operation) in
|
||||
precondition(Thread.isMainThread)
|
||||
guard !operation.isCanceled, let strongSelf = self, operation.id == strongSelf.fetchSerialNumber else {
|
||||
return
|
||||
|
|
|
@ -14,7 +14,7 @@ import Account
|
|||
final class SmartFeed: PseudoFeed {
|
||||
|
||||
public var defaultReadFilter: ReadFilter {
|
||||
return .all
|
||||
return .none
|
||||
}
|
||||
|
||||
var feedID: FeedIdentifier? {
|
||||
|
|
|
@ -20,7 +20,7 @@ import Articles
|
|||
final class UnreadFeed: PseudoFeed {
|
||||
|
||||
public var defaultReadFilter: ReadFilter {
|
||||
return .none
|
||||
return .unavailable
|
||||
}
|
||||
|
||||
var feedID: FeedIdentifier? {
|
||||
|
|
|
@ -19,14 +19,16 @@ typealias FetchRequestOperationResultBlock = (Set<Article>, FetchRequestOperatio
|
|||
final class FetchRequestOperation {
|
||||
|
||||
let id: Int
|
||||
let readFilter: ReadFilter
|
||||
let resultBlock: FetchRequestOperationResultBlock
|
||||
var isCanceled = false
|
||||
var isFinished = false
|
||||
private let representedObjects: [Any]
|
||||
|
||||
init(id: Int, representedObjects: [Any], resultBlock: @escaping FetchRequestOperationResultBlock) {
|
||||
init(id: Int, readFilter: ReadFilter, representedObjects: [Any], resultBlock: @escaping FetchRequestOperationResultBlock) {
|
||||
precondition(Thread.isMainThread)
|
||||
self.id = id
|
||||
self.readFilter = readFilter
|
||||
self.representedObjects = representedObjects
|
||||
self.resultBlock = resultBlock
|
||||
}
|
||||
|
@ -60,25 +62,38 @@ final class FetchRequestOperation {
|
|||
let numberOfFetchers = articleFetchers.count
|
||||
var fetchersReturned = 0
|
||||
var fetchedArticles = Set<Article>()
|
||||
for articleFetcher in articleFetchers {
|
||||
articleFetcher.fetchArticlesAsync { (articles) in
|
||||
precondition(Thread.isMainThread)
|
||||
guard !self.isCanceled else {
|
||||
callCompletionIfNeeded()
|
||||
return
|
||||
}
|
||||
|
||||
assert(!self.isFinished)
|
||||
|
||||
func process(articles: Set<Article>) {
|
||||
precondition(Thread.isMainThread)
|
||||
guard !self.isCanceled else {
|
||||
callCompletionIfNeeded()
|
||||
return
|
||||
}
|
||||
|
||||
assert(!self.isFinished)
|
||||
|
||||
fetchedArticles.formUnion(articles)
|
||||
fetchersReturned += 1
|
||||
if fetchersReturned == numberOfFetchers {
|
||||
self.isFinished = true
|
||||
self.resultBlock(fetchedArticles, self)
|
||||
callCompletionIfNeeded()
|
||||
fetchedArticles.formUnion(articles)
|
||||
fetchersReturned += 1
|
||||
if fetchersReturned == numberOfFetchers {
|
||||
self.isFinished = true
|
||||
self.resultBlock(fetchedArticles, self)
|
||||
callCompletionIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
for articleFetcher in articleFetchers {
|
||||
if readFilter == .read {
|
||||
articleFetcher.fetchUnreadArticlesAsync { (articles) in
|
||||
process(articles: articles)
|
||||
}
|
||||
} else {
|
||||
articleFetcher.fetchArticlesAsync { (articles) in
|
||||
process(articles: articles)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ class MasterTimelineViewController: UITableViewController, UndoableCommandRunner
|
|||
// MARK: Actions
|
||||
@IBAction func toggleFilter(_ sender: Any) {
|
||||
switch coordinator.articleReadFilter {
|
||||
case .all:
|
||||
case .none:
|
||||
filterButton.image = AppAssets.filterActiveImage
|
||||
coordinator.hideUnreadArticles()
|
||||
case .read:
|
||||
|
@ -497,7 +497,7 @@ private extension MasterTimelineViewController {
|
|||
}
|
||||
|
||||
switch coordinator.articleReadFilter {
|
||||
case .all:
|
||||
case .none:
|
||||
filterButton.isHidden = false
|
||||
filterButton.image = AppAssets.filterInactiveImage
|
||||
case .read:
|
||||
|
@ -548,7 +548,7 @@ private extension MasterTimelineViewController {
|
|||
self?.configure(cell, article: article)
|
||||
return cell
|
||||
})
|
||||
dataSource.defaultRowAnimation = .left
|
||||
dataSource.defaultRowAnimation = .middle
|
||||
return dataSource
|
||||
}
|
||||
|
||||
|
|
|
@ -116,7 +116,7 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
return treeControllerDelegate.isUnreadFiltered
|
||||
}
|
||||
|
||||
var articleReadFilter: ReadFilter = .all
|
||||
var articleReadFilter: ReadFilter = .none
|
||||
|
||||
var rootNode: Node {
|
||||
return treeController.rootNode
|
||||
|
@ -473,11 +473,17 @@ class SceneCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
}
|
||||
|
||||
func showAllArticles() {
|
||||
articleReadFilter = .all
|
||||
articleReadFilter = .none
|
||||
fetchAndReplaceArticlesAsync {
|
||||
self.rebuildBackingStores()
|
||||
}
|
||||
}
|
||||
|
||||
func hideUnreadArticles() {
|
||||
articleReadFilter = .read
|
||||
fetchAndReplaceArticlesAsync {
|
||||
self.rebuildBackingStores()
|
||||
}
|
||||
}
|
||||
|
||||
func expand(_ node: Node) {
|
||||
|
@ -1139,7 +1145,7 @@ private extension SceneCoordinator {
|
|||
func setTimelineFeed(_ feed: Feed?, completion: (() -> Void)? = nil) {
|
||||
timelineFeed = feed
|
||||
timelineMiddleIndexPath = nil
|
||||
articleReadFilter = feed?.defaultReadFilter ?? .all
|
||||
articleReadFilter = feed?.defaultReadFilter ?? .none
|
||||
|
||||
fetchAndReplaceArticlesAsync {
|
||||
self.masterTimelineViewController?.reinitializeArticles()
|
||||
|
@ -1480,7 +1486,7 @@ private extension SceneCoordinator {
|
|||
precondition(Thread.isMainThread)
|
||||
cancelPendingAsyncFetches()
|
||||
|
||||
let fetchOperation = FetchRequestOperation(id: fetchSerialNumber, representedObjects: representedObjects) { [weak self] (articles, operation) in
|
||||
let fetchOperation = FetchRequestOperation(id: fetchSerialNumber, readFilter: articleReadFilter, representedObjects: representedObjects) { [weak self] (articles, operation) in
|
||||
precondition(Thread.isMainThread)
|
||||
guard !operation.isCanceled, let strongSelf = self, operation.id == strongSelf.fetchSerialNumber else {
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue