Add an optional limit parameter to the smart feeds. Fixes #2627
This commit is contained in:
parent
7e791a2e7d
commit
9c761c80df
@ -53,9 +53,9 @@ public enum AccountType: Int, Codable {
|
||||
}
|
||||
|
||||
public enum FetchType {
|
||||
case starred
|
||||
case unread
|
||||
case today
|
||||
case starred(Int?)
|
||||
case unread(Int?)
|
||||
case today(Int?)
|
||||
case folder(Folder, Bool)
|
||||
case webFeed(WebFeed)
|
||||
case articleIDs(Set<String>)
|
||||
@ -674,12 +674,12 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||
|
||||
public func fetchArticles(_ fetchType: FetchType) throws -> Set<Article> {
|
||||
switch fetchType {
|
||||
case .starred:
|
||||
return try fetchStarredArticles()
|
||||
case .unread:
|
||||
return try fetchUnreadArticles()
|
||||
case .today:
|
||||
return try fetchTodayArticles()
|
||||
case .starred(let limit):
|
||||
return try fetchStarredArticles(limit: limit)
|
||||
case .unread(let limit):
|
||||
return try fetchUnreadArticles(limit: limit)
|
||||
case .today(let limit):
|
||||
return try fetchTodayArticles(limit: limit)
|
||||
case .folder(let folder, let readFilter):
|
||||
if readFilter {
|
||||
return try fetchUnreadArticles(folder: folder)
|
||||
@ -699,12 +699,12 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||
|
||||
public func fetchArticlesAsync(_ fetchType: FetchType, _ completion: @escaping ArticleSetResultBlock) {
|
||||
switch fetchType {
|
||||
case .starred:
|
||||
fetchStarredArticlesAsync(completion)
|
||||
case .unread:
|
||||
fetchUnreadArticlesAsync(completion)
|
||||
case .today:
|
||||
fetchTodayArticlesAsync(completion)
|
||||
case .starred(let limit):
|
||||
fetchStarredArticlesAsync(limit: limit, completion)
|
||||
case .unread(let limit):
|
||||
fetchUnreadArticlesAsync(limit: limit, completion)
|
||||
case .today(let limit):
|
||||
fetchTodayArticlesAsync(limit: limit, completion)
|
||||
case .folder(let folder, let readFilter):
|
||||
if readFilter {
|
||||
return fetchUnreadArticlesAsync(folder: folder, completion)
|
||||
@ -1046,28 +1046,28 @@ extension Account: WebFeedMetadataDelegate {
|
||||
|
||||
private extension Account {
|
||||
|
||||
func fetchStarredArticles() throws -> Set<Article> {
|
||||
return try database.fetchStarredArticles(flattenedWebFeeds().webFeedIDs())
|
||||
func fetchStarredArticles(limit: Int?) throws -> Set<Article> {
|
||||
return try database.fetchStarredArticles(flattenedWebFeeds().webFeedIDs(), limit)
|
||||
}
|
||||
|
||||
func fetchStarredArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
|
||||
database.fetchedStarredArticlesAsync(flattenedWebFeeds().webFeedIDs(), completion)
|
||||
func fetchStarredArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
database.fetchedStarredArticlesAsync(flattenedWebFeeds().webFeedIDs(), limit, completion)
|
||||
}
|
||||
|
||||
func fetchUnreadArticles() throws -> Set<Article> {
|
||||
return try fetchUnreadArticles(forContainer: self)
|
||||
func fetchUnreadArticles(limit: Int?) throws -> Set<Article> {
|
||||
return try fetchUnreadArticles(forContainer: self, limit: limit)
|
||||
}
|
||||
|
||||
func fetchUnreadArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
|
||||
fetchUnreadArticlesAsync(forContainer: self, completion)
|
||||
func fetchUnreadArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
fetchUnreadArticlesAsync(forContainer: self, limit: limit, completion)
|
||||
}
|
||||
|
||||
func fetchTodayArticles() throws -> Set<Article> {
|
||||
return try database.fetchTodayArticles(flattenedWebFeeds().webFeedIDs())
|
||||
func fetchTodayArticles(limit: Int?) throws -> Set<Article> {
|
||||
return try database.fetchTodayArticles(flattenedWebFeeds().webFeedIDs(), limit)
|
||||
}
|
||||
|
||||
func fetchTodayArticlesAsync(_ completion: @escaping ArticleSetResultBlock) {
|
||||
database.fetchTodayArticlesAsync(flattenedWebFeeds().webFeedIDs(), completion)
|
||||
func fetchTodayArticlesAsync(limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
database.fetchTodayArticlesAsync(flattenedWebFeeds().webFeedIDs(), limit, completion)
|
||||
}
|
||||
|
||||
func fetchArticles(folder: Folder) throws -> Set<Article> {
|
||||
@ -1079,11 +1079,11 @@ private extension Account {
|
||||
}
|
||||
|
||||
func fetchUnreadArticles(folder: Folder) throws -> Set<Article> {
|
||||
return try fetchUnreadArticles(forContainer: folder)
|
||||
return try fetchUnreadArticles(forContainer: folder, limit: nil)
|
||||
}
|
||||
|
||||
func fetchUnreadArticlesAsync(folder: Folder, _ completion: @escaping ArticleSetResultBlock) {
|
||||
fetchUnreadArticlesAsync(forContainer: folder, completion)
|
||||
fetchUnreadArticlesAsync(forContainer: folder, limit: nil, completion)
|
||||
}
|
||||
|
||||
func fetchArticles(webFeed: WebFeed) throws -> Set<Article> {
|
||||
@ -1129,7 +1129,7 @@ private extension Account {
|
||||
}
|
||||
|
||||
func fetchUnreadArticles(webFeed: WebFeed) throws -> Set<Article> {
|
||||
let articles = try database.fetchUnreadArticles(Set([webFeed.webFeedID]))
|
||||
let articles = try database.fetchUnreadArticles(Set([webFeed.webFeedID]), nil)
|
||||
validateUnreadCount(webFeed, articles)
|
||||
return articles
|
||||
}
|
||||
@ -1154,16 +1154,16 @@ private extension Account {
|
||||
}
|
||||
}
|
||||
|
||||
func fetchUnreadArticles(forContainer container: Container) throws -> Set<Article> {
|
||||
func fetchUnreadArticles(forContainer container: Container, limit: Int?) throws -> Set<Article> {
|
||||
let feeds = container.flattenedWebFeeds()
|
||||
let articles = try database.fetchUnreadArticles(feeds.webFeedIDs())
|
||||
let articles = try database.fetchUnreadArticles(feeds.webFeedIDs(), limit)
|
||||
validateUnreadCountsAfterFetchingUnreadArticles(feeds, articles)
|
||||
return articles
|
||||
}
|
||||
|
||||
func fetchUnreadArticlesAsync(forContainer container: Container, _ completion: @escaping ArticleSetResultBlock) {
|
||||
func fetchUnreadArticlesAsync(forContainer container: Container, limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
let webFeeds = container.flattenedWebFeeds()
|
||||
database.fetchUnreadArticlesAsync(webFeeds.webFeedIDs()) { [weak self] (articleSetResult) in
|
||||
database.fetchUnreadArticlesAsync(webFeeds.webFeedIDs(), limit) { [weak self] (articleSetResult) in
|
||||
switch articleSetResult {
|
||||
case .success(let articles):
|
||||
self?.validateUnreadCountsAfterFetchingUnreadArticles(webFeeds, articles)
|
||||
|
@ -102,16 +102,16 @@ public final class ArticlesDatabase {
|
||||
return try articlesTable.fetchArticles(articleIDs: articleIDs)
|
||||
}
|
||||
|
||||
public func fetchUnreadArticles(_ webFeedIDs: Set<String>) throws -> Set<Article> {
|
||||
return try articlesTable.fetchUnreadArticles(webFeedIDs)
|
||||
public func fetchUnreadArticles(_ webFeedIDs: Set<String>, _ limit: Int?) throws -> Set<Article> {
|
||||
return try articlesTable.fetchUnreadArticles(webFeedIDs, limit)
|
||||
}
|
||||
|
||||
public func fetchTodayArticles(_ webFeedIDs: Set<String>) throws -> Set<Article> {
|
||||
return try articlesTable.fetchArticlesSince(webFeedIDs, todayCutoffDate())
|
||||
public func fetchTodayArticles(_ webFeedIDs: Set<String>, _ limit: Int?) throws -> Set<Article> {
|
||||
return try articlesTable.fetchArticlesSince(webFeedIDs, todayCutoffDate(), limit)
|
||||
}
|
||||
|
||||
public func fetchStarredArticles(_ webFeedIDs: Set<String>) throws -> Set<Article> {
|
||||
return try articlesTable.fetchStarredArticles(webFeedIDs)
|
||||
public func fetchStarredArticles(_ webFeedIDs: Set<String>, _ limit: Int?) throws -> Set<Article> {
|
||||
return try articlesTable.fetchStarredArticles(webFeedIDs, limit)
|
||||
}
|
||||
|
||||
public func fetchArticlesMatching(_ searchString: String, _ webFeedIDs: Set<String>) throws -> Set<Article> {
|
||||
@ -136,16 +136,16 @@ public final class ArticlesDatabase {
|
||||
articlesTable.fetchArticlesAsync(articleIDs: articleIDs, completion)
|
||||
}
|
||||
|
||||
public func fetchUnreadArticlesAsync(_ webFeedIDs: Set<String>, _ completion: @escaping ArticleSetResultBlock) {
|
||||
articlesTable.fetchUnreadArticlesAsync(webFeedIDs, completion)
|
||||
public func fetchUnreadArticlesAsync(_ webFeedIDs: Set<String>, _ limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
articlesTable.fetchUnreadArticlesAsync(webFeedIDs, limit, completion)
|
||||
}
|
||||
|
||||
public func fetchTodayArticlesAsync(_ webFeedIDs: Set<String>, _ completion: @escaping ArticleSetResultBlock) {
|
||||
articlesTable.fetchArticlesSinceAsync(webFeedIDs, todayCutoffDate(), completion)
|
||||
public func fetchTodayArticlesAsync(_ webFeedIDs: Set<String>, _ limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
articlesTable.fetchArticlesSinceAsync(webFeedIDs, todayCutoffDate(), limit, completion)
|
||||
}
|
||||
|
||||
public func fetchedStarredArticlesAsync(_ webFeedIDs: Set<String>, _ completion: @escaping ArticleSetResultBlock) {
|
||||
articlesTable.fetchStarredArticlesAsync(webFeedIDs, completion)
|
||||
public func fetchedStarredArticlesAsync(_ webFeedIDs: Set<String>, _ limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
articlesTable.fetchStarredArticlesAsync(webFeedIDs, limit, completion)
|
||||
}
|
||||
|
||||
public func fetchArticlesMatchingAsync(_ searchString: String, _ webFeedIDs: Set<String>, _ completion: @escaping ArticleSetResultBlock) {
|
||||
|
@ -75,32 +75,32 @@ final class ArticlesTable: DatabaseTable {
|
||||
|
||||
// MARK: - Fetching Unread Articles
|
||||
|
||||
func fetchUnreadArticles(_ webFeedIDs: Set<String>) throws -> Set<Article> {
|
||||
return try fetchArticles{ self.fetchUnreadArticles(webFeedIDs, $0) }
|
||||
func fetchUnreadArticles(_ webFeedIDs: Set<String>, _ limit: Int?) throws -> Set<Article> {
|
||||
return try fetchArticles{ self.fetchUnreadArticles(webFeedIDs, limit, $0) }
|
||||
}
|
||||
|
||||
func fetchUnreadArticlesAsync(_ webFeedIDs: Set<String>, _ completion: @escaping ArticleSetResultBlock) {
|
||||
fetchArticlesAsync({ self.fetchUnreadArticles(webFeedIDs, $0) }, completion)
|
||||
func fetchUnreadArticlesAsync(_ webFeedIDs: Set<String>, _ limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
fetchArticlesAsync({ self.fetchUnreadArticles(webFeedIDs, limit, $0) }, completion)
|
||||
}
|
||||
|
||||
// MARK: - Fetching Today Articles
|
||||
|
||||
func fetchArticlesSince(_ webFeedIDs: Set<String>, _ cutoffDate: Date) throws -> Set<Article> {
|
||||
return try fetchArticles{ self.fetchArticlesSince(webFeedIDs, cutoffDate, $0) }
|
||||
func fetchArticlesSince(_ webFeedIDs: Set<String>, _ cutoffDate: Date, _ limit: Int?) throws -> Set<Article> {
|
||||
return try fetchArticles{ self.fetchArticlesSince(webFeedIDs, cutoffDate, limit, $0) }
|
||||
}
|
||||
|
||||
func fetchArticlesSinceAsync(_ webFeedIDs: Set<String>, _ cutoffDate: Date, _ completion: @escaping ArticleSetResultBlock) {
|
||||
fetchArticlesAsync({ self.fetchArticlesSince(webFeedIDs, cutoffDate, $0) }, completion)
|
||||
func fetchArticlesSinceAsync(_ webFeedIDs: Set<String>, _ cutoffDate: Date, _ limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
fetchArticlesAsync({ self.fetchArticlesSince(webFeedIDs, cutoffDate, limit, $0) }, completion)
|
||||
}
|
||||
|
||||
// MARK: - Fetching Starred Articles
|
||||
|
||||
func fetchStarredArticles(_ webFeedIDs: Set<String>) throws -> Set<Article> {
|
||||
return try fetchArticles{ self.fetchStarredArticles(webFeedIDs, $0) }
|
||||
func fetchStarredArticles(_ webFeedIDs: Set<String>, _ limit: Int?) throws -> Set<Article> {
|
||||
return try fetchArticles{ self.fetchStarredArticles(webFeedIDs, limit, $0) }
|
||||
}
|
||||
|
||||
func fetchStarredArticlesAsync(_ webFeedIDs: Set<String>, _ completion: @escaping ArticleSetResultBlock) {
|
||||
fetchArticlesAsync({ self.fetchStarredArticles(webFeedIDs, $0) }, completion)
|
||||
func fetchStarredArticlesAsync(_ webFeedIDs: Set<String>, _ limit: Int?, _ completion: @escaping ArticleSetResultBlock) {
|
||||
fetchArticlesAsync({ self.fetchStarredArticles(webFeedIDs, limit, $0) }, completion)
|
||||
}
|
||||
|
||||
// MARK: - Fetching Search Articles
|
||||
@ -819,14 +819,17 @@ private extension ArticlesTable {
|
||||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||
}
|
||||
|
||||
func fetchUnreadArticles(_ webFeedIDs: Set<String>, _ database: FMDatabase) -> Set<Article> {
|
||||
func fetchUnreadArticles(_ webFeedIDs: Set<String>, _ limit: Int?, _ database: FMDatabase) -> Set<Article> {
|
||||
// select * from articles natural join statuses where feedID in ('http://ranchero.com/xml/rss.xml') and read=0
|
||||
if webFeedIDs.isEmpty {
|
||||
return Set<Article>()
|
||||
}
|
||||
let parameters = webFeedIDs.map { $0 as AnyObject }
|
||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
|
||||
let whereClause = "feedID in \(placeholders) and read=0"
|
||||
var whereClause = "feedID in \(placeholders) and read=0"
|
||||
if let limit = limit {
|
||||
whereClause.append(" order by coalesce(datePublished, dateModified, dateArrived) desc limit \(limit)")
|
||||
}
|
||||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||
}
|
||||
|
||||
@ -844,7 +847,7 @@ private extension ArticlesTable {
|
||||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||
}
|
||||
|
||||
func fetchArticlesSince(_ webFeedIDs: Set<String>, _ cutoffDate: Date, _ database: FMDatabase) -> Set<Article> {
|
||||
func fetchArticlesSince(_ webFeedIDs: Set<String>, _ cutoffDate: Date, _ limit: Int?, _ database: FMDatabase) -> Set<Article> {
|
||||
// select * from articles natural join statuses where feedID in ('http://ranchero.com/xml/rss.xml') and (datePublished > ? || (datePublished is null and dateArrived > ?)
|
||||
//
|
||||
// datePublished may be nil, so we fall back to dateArrived.
|
||||
@ -853,18 +856,24 @@ private extension ArticlesTable {
|
||||
}
|
||||
let parameters = webFeedIDs.map { $0 as AnyObject } + [cutoffDate as AnyObject, cutoffDate as AnyObject]
|
||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
|
||||
let whereClause = "feedID in \(placeholders) and (datePublished > ? or (datePublished is null and dateArrived > ?))"
|
||||
var whereClause = "feedID in \(placeholders) and (datePublished > ? or (datePublished is null and dateArrived > ?))"
|
||||
if let limit = limit {
|
||||
whereClause.append(" order by coalesce(datePublished, dateModified, dateArrived) desc limit \(limit)")
|
||||
}
|
||||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||
}
|
||||
|
||||
func fetchStarredArticles(_ webFeedIDs: Set<String>, _ database: FMDatabase) -> Set<Article> {
|
||||
func fetchStarredArticles(_ webFeedIDs: Set<String>, _ limit: Int?, _ database: FMDatabase) -> Set<Article> {
|
||||
// select * from articles natural join statuses where feedID in ('http://ranchero.com/xml/rss.xml') and starred=1;
|
||||
if webFeedIDs.isEmpty {
|
||||
return Set<Article>()
|
||||
}
|
||||
let parameters = webFeedIDs.map { $0 as AnyObject }
|
||||
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
|
||||
let whereClause = "feedID in \(placeholders) and starred=1"
|
||||
var whereClause = "feedID in \(placeholders) and starred=1"
|
||||
if let limit = limit {
|
||||
whereClause.append(" order by coalesce(datePublished, dateModified, dateArrived) desc limit \(limit)")
|
||||
}
|
||||
return fetchArticlesWithWhereClause(database, whereClause: whereClause, parameters: parameters)
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ struct StarredFeedDelegate: SmartFeedDelegate {
|
||||
}
|
||||
|
||||
let nameForDisplay = NSLocalizedString("Starred", comment: "Starred pseudo-feed title")
|
||||
let fetchType: FetchType = .starred
|
||||
let fetchType: FetchType = .starred(nil)
|
||||
var smallIcon: IconImage? {
|
||||
return AppAssets.starredFeedImage
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ struct TodayFeedDelegate: SmartFeedDelegate {
|
||||
}
|
||||
|
||||
let nameForDisplay = NSLocalizedString("Today", comment: "Today pseudo-feed title")
|
||||
let fetchType = FetchType.today
|
||||
let fetchType = FetchType.today(nil)
|
||||
var smallIcon: IconImage? {
|
||||
return AppAssets.todayFeedImage
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ final class UnreadFeed: PseudoFeed {
|
||||
}
|
||||
|
||||
let nameForDisplay = NSLocalizedString("All Unread", comment: "All Unread pseudo-feed title")
|
||||
let fetchType = FetchType.unread
|
||||
let fetchType = FetchType.unread(nil)
|
||||
|
||||
var unreadCount = 0 {
|
||||
didSet {
|
||||
|
Loading…
x
Reference in New Issue
Block a user