Add code to process new article entries.

This commit is contained in:
Maurice Parker 2020-04-10 16:25:58 -05:00
parent 4418a4bb02
commit 983138366f
8 changed files with 65 additions and 22 deletions

View File

@ -801,16 +801,16 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
/// Mark articleIDs statuses based on statusKey and flag.
/// Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
/// Returns a set of new article statuses.
func markAndFetchNew(articleIDs: Set<String>, statusKey: ArticleStatus.Key, flag: Bool, completion: ArticleStatusesResultBlock? = nil) {
func markAndFetchNew(articleIDs: Set<String>, statusKey: ArticleStatus.Key, flag: Bool, completion: ArticleIDsCompletionBlock? = nil) {
guard !articleIDs.isEmpty else {
completion?(.success(Set<ArticleStatus>()))
completion?(.success(Set<String>()))
return
}
database.markAndFetchNew(articleIDs: articleIDs, statusKey: statusKey, flag: flag) { result in
switch result {
case .success(let newArticleStatuses):
case .success(let newArticleStatusIDs):
self.noteStatusesForArticleIDsDidChange(articleIDs)
completion?(.success(newArticleStatuses))
completion?(.success(newArticleStatusIDs))
case .failure(let databaseError):
completion?(.failure(databaseError))
}
@ -819,25 +819,25 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
/// Mark articleIDs as read. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
/// Returns a set of new article statuses.
func markAsRead(_ articleIDs: Set<String>, completion: ArticleStatusesResultBlock? = nil) {
func markAsRead(_ articleIDs: Set<String>, completion: ArticleIDsCompletionBlock? = nil) {
markAndFetchNew(articleIDs: articleIDs, statusKey: .read, flag: true, completion: completion)
}
/// Mark articleIDs as unread. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
/// Returns a set of new article statuses.
func markAsUnread(_ articleIDs: Set<String>, completion: ArticleStatusesResultBlock? = nil) {
func markAsUnread(_ articleIDs: Set<String>, completion: ArticleIDsCompletionBlock? = nil) {
markAndFetchNew(articleIDs: articleIDs, statusKey: .read, flag: false, completion: completion)
}
/// Mark articleIDs as starred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
/// Returns a set of new article statuses.
func markAsStarred(_ articleIDs: Set<String>, completion: ArticleStatusesResultBlock? = nil) {
func markAsStarred(_ articleIDs: Set<String>, completion: ArticleIDsCompletionBlock? = nil) {
markAndFetchNew(articleIDs: articleIDs, statusKey: .starred, flag: true, completion: completion)
}
/// Mark articleIDs as unstarred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
/// Returns a set of new article statuses.
func markAsUnstarred(_ articleIDs: Set<String>, completion: ArticleStatusesResultBlock? = nil) {
func markAsUnstarred(_ articleIDs: Set<String>, completion: ArticleIDsCompletionBlock? = nil) {
markAndFetchNew(articleIDs: articleIDs, statusKey: .starred, flag: false, completion: completion)
}
@ -893,7 +893,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
public func debugDropConditionalGetInfo() {
#if DEBUG
flattenedWebFeeds().forEach{ $0.debugDropConditionalGetInfo() }
flattenedWebFeeds().forEach{ $0.dropConditionalGetInfo() }
#endif
}

View File

@ -481,7 +481,11 @@ final class CloudKitAccountDelegate: AccountDelegate {
self.account = account
accountZone.delegate = CloudKitAcountZoneDelegate(account: account, refreshProgress: refreshProgress)
articlesZone.delegate = CloudKitArticlesZoneDelegate(account: account, database: database, articlesZone: articlesZone)
articlesZone.delegate = CloudKitArticlesZoneDelegate(account: account,
database: database,
articlesZone: articlesZone,
refresher: refresher,
refreshProgress: refreshProgress)
// Check to see if this is a new account and initialize anything we need
if account.externalID == nil {

View File

@ -9,6 +9,7 @@
import Foundation
import os.log
import RSParser
import RSWeb
import CloudKit
import SyncDatabase
@ -19,11 +20,15 @@ class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate {
weak var account: Account?
var database: SyncDatabase
weak var articlesZone: CloudKitArticlesZone?
weak var refresher: LocalAccountRefresher?
weak var refreshProgress: DownloadProgress?
init(account: Account, database: SyncDatabase, articlesZone: CloudKitArticlesZone) {
init(account: Account, database: SyncDatabase, articlesZone: CloudKitArticlesZone, refresher: LocalAccountRefresher?, refreshProgress: DownloadProgress?) {
self.account = account
self.database = database
self.articlesZone = articlesZone
self.refresher = refresher
self.refreshProgress = refreshProgress
}
func cloudKitDidChange(record: CKRecord) {
@ -82,8 +87,37 @@ private extension CloudKitArticlesZoneDelegate {
let group = DispatchGroup()
group.enter()
account?.markAsUnread(updateableUnreadArticleIDs) { _ in
account?.markAsUnread(updateableUnreadArticleIDs) { result in
switch result {
case .success(let newArticleStatusIDs):
if newArticleStatusIDs.isEmpty {
group.leave()
} else {
self.account?.fetchArticlesAsync(FetchType.articleIDs(newArticleStatusIDs)) { result in
switch result {
case .success(let articles):
if articles.isEmpty {
group.leave()
} else {
let webFeeds = Set(articles.compactMap({ $0.webFeed }))
webFeeds.forEach { $0.dropConditionalGetInfo() }
self.refreshProgress?.addToNumberOfTasksAndRemaining(webFeeds.count)
self.refresher?.refreshFeeds(webFeeds) {
group.leave()
}
}
case .failure:
group.leave()
}
}
}
case .failure:
group.leave()
}
}
group.enter()
@ -119,7 +153,6 @@ private extension CloudKitArticlesZoneDelegate {
}
func makeParsedItem(_ articleRecord: CKRecord) -> ParsedItem? {
var parsedAuthors = Set<ParsedAuthor>()

View File

@ -19,6 +19,7 @@ protocol LocalAccountRefresherDelegate {
final class LocalAccountRefresher {
private var completions = [() -> Void]()
private var isSuspended = false
var delegate: LocalAccountRefresherDelegate?
@ -26,7 +27,10 @@ final class LocalAccountRefresher {
return DownloadSession(delegate: self)
}()
public func refreshFeeds(_ feeds: Set<WebFeed>) {
public func refreshFeeds(_ feeds: Set<WebFeed>, completion: (() -> Void)? = nil) {
if let completion = completion {
completions.append(completion)
}
downloadSession.downloadObjects(feeds as NSSet)
}
@ -154,6 +158,8 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
func downloadSessionDidCompleteDownloadObjects(_ downloadSession: DownloadSession) {
delegate?.localAccountRefresherDidFinish(self)
completions.forEach({ $0() })
completions = [() -> Void]()
}
}

View File

@ -221,9 +221,9 @@ public final class WebFeed: Feed, Renamable, Hashable {
self.metadata = metadata
}
// MARK: - Debug
// MARK: - API
public func debugDropConditionalGetInfo() {
public func dropConditionalGetInfo() {
conditionalGetInfo = nil
contentHash = nil
}

View File

@ -222,7 +222,7 @@ public final class ArticlesDatabase {
return try articlesTable.mark(articles, statusKey, flag)
}
public func markAndFetchNew(articleIDs: Set<String>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping ArticleStatusesResultBlock) {
public func markAndFetchNew(articleIDs: Set<String>, statusKey: ArticleStatus.Key, flag: Bool, completion: @escaping ArticleIDsCompletionBlock) {
articlesTable.markAndFetchNew(articleIDs, statusKey, flag, completion)
}

View File

@ -418,7 +418,7 @@ final class ArticlesTable: DatabaseTable {
return statuses
}
func markAndFetchNew(_ articleIDs: Set<String>, _ statusKey: ArticleStatus.Key, _ flag: Bool, _ completion: @escaping ArticleStatusesResultBlock) {
func markAndFetchNew(_ articleIDs: Set<String>, _ statusKey: ArticleStatus.Key, _ flag: Bool, _ completion: @escaping ArticleIDsCompletionBlock) {
queue.runInTransaction { databaseResult in
switch databaseResult {
case .success(let database):

View File

@ -85,11 +85,11 @@ final class StatusesTable: DatabaseTable {
return updatedStatuses
}
func markAndFetchNew(_ articleIDs: Set<String>, _ statusKey: ArticleStatus.Key, _ flag: Bool, _ database: FMDatabase) -> Set<ArticleStatus> {
func markAndFetchNew(_ articleIDs: Set<String>, _ statusKey: ArticleStatus.Key, _ flag: Bool, _ database: FMDatabase) -> Set<String> {
let (statusesDictionary, newStatusIDs) = ensureStatusesForArticleIDs(articleIDs, flag, database)
let statuses = Set(statusesDictionary.values)
mark(statuses, statusKey, flag, database)
return Set(newStatusIDs.compactMap({ statusesDictionary[$0] }))
return newStatusIDs
}
// MARK: - Fetching