Make fetchStarredArticles an async call. Also have it respect subscribed-to feed IDs.

This commit is contained in:
Brent Simmons 2019-12-07 22:23:44 -08:00
parent a561ea9484
commit 0b87531f2f
6 changed files with 103 additions and 91 deletions

View File

@ -674,13 +674,13 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
}
public func fetchUnreadArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
return database.fetchUnreadArticleIDsAsync(webFeedIDs: flattenedWebFeeds().webFeedIDs(), callback: callback)
database.fetchUnreadArticleIDsAsync(webFeedIDs: flattenedWebFeeds().webFeedIDs(), callback: callback)
}
public func fetchStarredArticleIDs() -> Set<String> {
return database.fetchStarredArticleIDs()
public func fetchStarredArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
database.fetchStarredArticleIDsAsync(webFeedIDs: flattenedWebFeeds().webFeedIDs(), callback: callback)
}
public func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
return database.fetchArticleIDsForStatusesWithoutArticles()
}

View File

@ -1224,27 +1224,27 @@ private extension FeedbinAccountDelegate {
}
let feedbinStarredArticleIDs = Set(articleIDs.map { String($0) } )
let currentStarredArticleIDs = account.fetchStarredArticleIDs()
// Mark articles as starred
let deltaStarredArticleIDs = feedbinStarredArticleIDs.subtracting(currentStarredArticleIDs)
let markStarredArticles = account.fetchArticles(.articleIDs(deltaStarredArticleIDs))
account.update(markStarredArticles, statusKey: .starred, flag: true)
account.fetchStarredArticleIDs { currentStarredArticleIDs in
// Mark articles as starred
let deltaStarredArticleIDs = feedbinStarredArticleIDs.subtracting(currentStarredArticleIDs)
let markStarredArticles = account.fetchArticles(.articleIDs(deltaStarredArticleIDs))
account.update(markStarredArticles, statusKey: .starred, flag: true)
// Save any starred statuses for articles we haven't yet received
let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID })
let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs)
account.ensureStatuses(missingStarredArticleIDs, true, .starred, true)
// Save any starred statuses for articles we haven't yet received
let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID })
let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs)
account.ensureStatuses(missingStarredArticleIDs, true, .starred, true)
// Mark articles as unstarred
let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(feedbinStarredArticleIDs)
let markUnstarredArticles = account.fetchArticles(.articleIDs(deltaUnstarredArticleIDs))
account.update(markUnstarredArticles, statusKey: .starred, flag: false)
// Mark articles as unstarred
let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(feedbinStarredArticleIDs)
let markUnstarredArticles = account.fetchArticles(.articleIDs(deltaUnstarredArticleIDs))
account.update(markUnstarredArticles, statusKey: .starred, flag: false)
// Save any unstarred statuses for articles we haven't yet received
let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID })
let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs)
account.ensureStatuses(missingUnstarredArticleIDs, true, .starred, false)
// Save any unstarred statuses for articles we haven't yet received
let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID })
let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs)
account.ensureStatuses(missingUnstarredArticleIDs, true, .starred, false)
}
}
func deleteTagging(for account: Account, with feed: WebFeed, from container: Container?, completion: @escaping (Result<Void, Error>) -> Void) {

View File

@ -35,36 +35,36 @@ final class FeedlySetStarredArticlesOperation: FeedlyOperation {
let group = DispatchGroup()
let remoteStarredArticleIds = allStarredEntryIdsProvider.entryIds
let localStarredArticleIDs = account.fetchStarredArticleIDs()
// Mark articles as starred
let deltaStarredArticleIDs = remoteStarredArticleIds.subtracting(localStarredArticleIDs)
let markStarredArticles = account.fetchArticles(.articleIDs(deltaStarredArticleIDs))
account.update(markStarredArticles, statusKey: .starred, flag: true)
account.fetchStarredArticleIDs { localStarredArticleIDs in
// Mark articles as starred
let deltaStarredArticleIDs = remoteStarredArticleIds.subtracting(localStarredArticleIDs)
let markStarredArticles = self.account.fetchArticles(.articleIDs(deltaStarredArticleIDs))
self.account.update(markStarredArticles, statusKey: .starred, flag: true)
// Save any starred statuses for articles we haven't yet received
let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID })
let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs)
group.enter()
account.ensureStatuses(missingStarredArticleIDs, true, .starred, true) {
group.leave()
}
// Save any starred statuses for articles we haven't yet received
let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID })
let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs)
group.enter()
self.account.ensureStatuses(missingStarredArticleIDs, true, .starred, true) {
group.leave()
}
// Mark articles as unstarred
let deltaUnstarredArticleIDs = localStarredArticleIDs.subtracting(remoteStarredArticleIds)
let markUnstarredArticles = account.fetchArticles(.articleIDs(deltaUnstarredArticleIDs))
account.update(markUnstarredArticles, statusKey: .starred, flag: false)
// Mark articles as unstarred
let deltaUnstarredArticleIDs = localStarredArticleIDs.subtracting(remoteStarredArticleIds)
let markUnstarredArticles = self.account.fetchArticles(.articleIDs(deltaUnstarredArticleIDs))
self.account.update(markUnstarredArticles, statusKey: .starred, flag: false)
// Save any unstarred statuses for articles we haven't yet received
let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID })
let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs)
group.enter()
account.ensureStatuses(missingUnstarredArticleIDs, true, .starred, false) {
group.leave()
}
group.notify(queue: .main) {
self.didFinish()
// Save any unstarred statuses for articles we haven't yet received
let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID })
let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs)
group.enter()
self.account.ensureStatuses(missingUnstarredArticleIDs, true, .starred, false) {
group.leave()
}
group.notify(queue: .main) {
self.didFinish()
}
}
}
}

View File

@ -942,27 +942,27 @@ private extension ReaderAPIAccountDelegate {
}
let feedbinStarredArticleIDs = Set(articleIDs.map { String($0) } )
let currentStarredArticleIDs = account.fetchStarredArticleIDs()
// Mark articles as starred
let deltaStarredArticleIDs = feedbinStarredArticleIDs.subtracting(currentStarredArticleIDs)
let markStarredArticles = account.fetchArticles(.articleIDs(deltaStarredArticleIDs))
account.update(markStarredArticles, statusKey: .starred, flag: true)
account.fetchStarredArticleIDs { currentStarredArticleIDs in
// Mark articles as starred
let deltaStarredArticleIDs = feedbinStarredArticleIDs.subtracting(currentStarredArticleIDs)
let markStarredArticles = account.fetchArticles(.articleIDs(deltaStarredArticleIDs))
account.update(markStarredArticles, statusKey: .starred, flag: true)
// Save any starred statuses for articles we haven't yet received
let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID })
let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs)
account.ensureStatuses(missingStarredArticleIDs, true, .starred, true)
// Save any starred statuses for articles we haven't yet received
let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID })
let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs)
account.ensureStatuses(missingStarredArticleIDs, true, .starred, true)
// Mark articles as unstarred
let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(feedbinStarredArticleIDs)
let markUnstarredArticles = account.fetchArticles(.articleIDs(deltaUnstarredArticleIDs))
account.update(markUnstarredArticles, statusKey: .starred, flag: false)
// Mark articles as unstarred
let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(feedbinStarredArticleIDs)
let markUnstarredArticles = account.fetchArticles(.articleIDs(deltaUnstarredArticleIDs))
account.update(markUnstarredArticles, statusKey: .starred, flag: false)
// Save any unstarred statuses for articles we haven't yet received
let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID })
let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs)
account.ensureStatuses(missingUnstarredArticleIDs, true, .starred, false)
// Save any unstarred statuses for articles we haven't yet received
let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID })
let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs)
account.ensureStatuses(missingUnstarredArticleIDs, true, .starred, false)
}
}

View File

@ -154,15 +154,16 @@ public final class ArticlesDatabase {
// MARK: - Status
/// Fetch the articleIDs of unread articles for feeds specified by webFeedIDs.
/// Fetch the articleIDs of unread articles in feeds specified by webFeedIDs.
public func fetchUnreadArticleIDsAsync(webFeedIDs: Set<String>, callback: @escaping (Set<String>) -> Void) {
articlesTable.fetchUnreadArticleIDsAsync(webFeedIDs, callback)
}
public func fetchStarredArticleIDs() -> Set<String> {
return articlesTable.fetchStarredArticleIDs()
/// Fetch the articleIDs of starred articles in feeds specified by webFeedIDs.
public func fetchStarredArticleIDsAsync(webFeedIDs: Set<String>, callback: @escaping (Set<String>) -> Void) {
articlesTable.fetchStarredArticleIDsAsync(webFeedIDs, callback)
}
public func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
return articlesTable.fetchArticleIDsForStatusesWithoutArticles()
}

View File

@ -401,28 +401,12 @@ final class ArticlesTable: DatabaseTable {
// MARK: - Statuses
func fetchUnreadArticleIDs() -> Set<String>{
return statusesTable.fetchUnreadArticleIDs()
func fetchUnreadArticleIDsAsync(_ webFeedIDs: Set<String>, _ callback: @escaping (Set<String>) -> Void) {
fetchArticleIDsAsync(.read, false, webFeedIDs, callback)
}
func fetchUnreadArticleIDsAsync(_ webFeedIDs: Set<String>, _ callback: @escaping (Set<String>) -> Void) {
queue.runInDatabase { database in
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
let sql = "select articleID from articles natural join statuses where feedID in \(placeholders) and read=0 and userDeleted=0;"
let parameters = Array(webFeedIDs) as [Any]
guard let resultSet = database.executeQuery(sql, withArgumentsIn: parameters) else {
DispatchQueue.main.async {
callback(Set<String>())
}
return
}
let articleIDs = resultSet.mapToSet{ $0.string(forColumnIndex: 0) }
DispatchQueue.main.async {
callback(articleIDs)
}
}
func fetchStarredArticleIDsAsync(_ webFeedIDs: Set<String>, _ callback: @escaping (Set<String>) -> Void) {
fetchArticleIDsAsync(.starred, true, webFeedIDs, callback)
}
func fetchStarredArticleIDs() -> Set<String> {
@ -668,6 +652,33 @@ private extension ArticlesTable {
return articlesWithResultSet(resultSet, database)
}
func fetchArticleIDsAsync(_ statusKey: ArticleStatus.Key, _ value: Bool, _ webFeedIDs: Set<String>, _ callback: @escaping (Set<String>) -> Void) {
queue.runInDatabase { database in
let placeholders = NSString.rs_SQLValueList(withPlaceholders: UInt(webFeedIDs.count))!
var sql = "select articleID from articles natural join statuses where feedID in \(placeholders) and \(statusKey.rawValue)="
sql += value ? "1" : "0"
if statusKey != .userDeleted {
sql += " and userDeleted=0"
}
sql += ";"
let parameters = Array(webFeedIDs) as [Any]
guard let resultSet = database.executeQuery(sql, withArgumentsIn: parameters) else {
DispatchQueue.main.async {
callback(Set<String>())
}
return
}
let articleIDs = resultSet.mapToSet{ $0.string(forColumnIndex: 0) }
DispatchQueue.main.async {
callback(articleIDs)
}
}
}
// MARK: - Saving Parsed Items
func callUpdateArticlesCompletionBlock(_ newArticles: Set<Article>?, _ updatedArticles: Set<Article>?, _ completion: @escaping UpdateArticlesCompletionBlock) {