Add the unread statuses on receipt to CloudKit.
This commit is contained in:
parent
983138366f
commit
a8dcf3eeee
|
@ -715,7 +715,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
webFeedDictionariesNeedUpdate = true
|
||||
}
|
||||
|
||||
func update(_ webFeed: WebFeed, with parsedFeed: ParsedFeed, _ completion: @escaping DatabaseCompletionBlock) {
|
||||
func update(_ webFeed: WebFeed, with parsedFeed: ParsedFeed, _ completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
// Used only by an On My Mac or iCloud account.
|
||||
precondition(Thread.isMainThread)
|
||||
precondition(type == .onMyMac || type == .cloudKit)
|
||||
|
@ -723,14 +723,14 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
webFeed.takeSettings(from: parsedFeed)
|
||||
let parsedItems = parsedFeed.items
|
||||
guard !parsedItems.isEmpty else {
|
||||
completion(nil)
|
||||
completion(.success(NewAndUpdatedArticles()))
|
||||
return
|
||||
}
|
||||
|
||||
update(webFeed.webFeedID, with: parsedItems, completion: completion)
|
||||
}
|
||||
|
||||
func update(_ webFeedID: String, with parsedItems: Set<ParsedItem>, completion: @escaping DatabaseCompletionBlock) {
|
||||
func update(_ webFeedID: String, with parsedItems: Set<ParsedItem>, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
// Used only by an On My Mac or iCloud account.
|
||||
precondition(Thread.isMainThread)
|
||||
precondition(type == .onMyMac || type == .cloudKit)
|
||||
|
@ -739,9 +739,9 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||
switch updateArticlesResult {
|
||||
case .success(let newAndUpdatedArticles):
|
||||
self.sendNotificationAbout(newAndUpdatedArticles)
|
||||
completion(nil)
|
||||
completion(.success(newAndUpdatedArticles))
|
||||
case .failure(let databaseError):
|
||||
completion(databaseError)
|
||||
completion(.failure(databaseError))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import SyncDatabase
|
|||
import RSCore
|
||||
import RSParser
|
||||
import Articles
|
||||
import ArticlesDatabase
|
||||
import RSWeb
|
||||
|
||||
public enum CloudKitAccountDelegateError: String, Error {
|
||||
|
@ -50,7 +51,6 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
var accountMetadata: AccountMetadata?
|
||||
|
||||
var refreshProgress = DownloadProgress(numberOfTasks: 0)
|
||||
var refreshAllCompletion: ((Result<Void, Error>) -> Void)? = nil
|
||||
|
||||
init(dataFolder: String) {
|
||||
accountZone = CloudKitAccountZone(container: container)
|
||||
|
@ -79,13 +79,12 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
}
|
||||
|
||||
func refreshAll(for account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
guard refreshAllCompletion == nil else {
|
||||
guard refreshProgress.isComplete else {
|
||||
completion(.success(()))
|
||||
return
|
||||
}
|
||||
refreshAllCompletion = completion
|
||||
|
||||
refreshAll(for: account, downloadFeeds: true)
|
||||
refreshAll(for: account, downloadFeeds: true, completion: completion)
|
||||
}
|
||||
|
||||
func sendArticleStatus(for account: Account, completion: @escaping ((Result<Void, Error>) -> Void)) {
|
||||
|
@ -155,11 +154,10 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
}
|
||||
|
||||
func importOPML(for account:Account, opmlFile: URL, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
guard refreshAllCompletion == nil else {
|
||||
guard refreshProgress.isComplete else {
|
||||
completion(.success(()))
|
||||
return
|
||||
}
|
||||
refreshAllCompletion = completion
|
||||
|
||||
var fileData: Data?
|
||||
|
||||
|
@ -214,7 +212,7 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
}
|
||||
|
||||
self.accountZone.importOPML(rootExternalID: rootExternalID, items: normalizedItems) { _ in
|
||||
self.refreshAll(for: account, downloadFeeds: false)
|
||||
self.refreshAll(for: account, downloadFeeds: false, completion: completion)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -493,7 +491,7 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
switch result {
|
||||
case .success(let externalID):
|
||||
account.externalID = externalID
|
||||
self.refreshAll(for: account, downloadFeeds: false)
|
||||
self.refreshAll(for: account, downloadFeeds: false) { _ in }
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Error adding account container: %@", error.localizedDescription)
|
||||
}
|
||||
|
@ -533,7 +531,7 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
|
||||
private extension CloudKitAccountDelegate {
|
||||
|
||||
func refreshAll(for account: Account, downloadFeeds: Bool) {
|
||||
func refreshAll(for account: Account, downloadFeeds: Bool, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
|
||||
let intialWebFeedsCount = downloadFeeds ? account.flattenedWebFeeds().count : 0
|
||||
refreshProgress.addToNumberOfTasksAndRemaining(3 + intialWebFeedsCount)
|
||||
|
@ -541,8 +539,7 @@ private extension CloudKitAccountDelegate {
|
|||
func fail(_ error: Error) {
|
||||
self.processAccountError(account, error)
|
||||
self.refreshProgress.clear()
|
||||
self.refreshAllCompletion?(.failure(error))
|
||||
self.refreshAllCompletion = nil
|
||||
completion(.failure(error))
|
||||
}
|
||||
|
||||
BatchUpdate.shared.start()
|
||||
|
@ -569,12 +566,24 @@ private extension CloudKitAccountDelegate {
|
|||
self.refreshProgress.completeTask()
|
||||
|
||||
guard downloadFeeds else {
|
||||
self.refreshAllCompletion?(.success(()))
|
||||
self.refreshAllCompletion = nil
|
||||
completion(.success(()))
|
||||
return
|
||||
}
|
||||
|
||||
self.refresher?.refreshFeeds(webFeeds)
|
||||
self.refresher?.refreshFeeds(webFeeds) {
|
||||
|
||||
account.metadata.lastArticleFetchEndTime = Date()
|
||||
|
||||
self.sendArticleStatus(for: account) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
completion(.success(()))
|
||||
case .failure(let error):
|
||||
fail(error)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
case .failure(let error):
|
||||
fail(error)
|
||||
|
@ -605,6 +614,15 @@ private extension CloudKitAccountDelegate {
|
|||
}
|
||||
|
||||
extension CloudKitAccountDelegate: LocalAccountRefresherDelegate {
|
||||
|
||||
func localAccountRefresher(_ refresher: LocalAccountRefresher, didProcess newAndUpdatedArticles: NewAndUpdatedArticles) {
|
||||
if let newArticles = newAndUpdatedArticles.newArticles {
|
||||
let syncStatuses = newArticles.map { article in
|
||||
return SyncStatus(articleID: article.articleID, key: .read, flag: false)
|
||||
}
|
||||
database.insertStatuses(syncStatuses)
|
||||
}
|
||||
}
|
||||
|
||||
func localAccountRefresher(_ refresher: LocalAccountRefresher, requestCompletedFor: WebFeed) {
|
||||
refreshProgress.completeTask()
|
||||
|
@ -612,9 +630,6 @@ extension CloudKitAccountDelegate: LocalAccountRefresherDelegate {
|
|||
|
||||
func localAccountRefresherDidFinish(_ refresher: LocalAccountRefresher) {
|
||||
self.refreshProgress.clear()
|
||||
account?.metadata.lastArticleFetchEndTime = Date()
|
||||
refreshAllCompletion?(.success(()))
|
||||
refreshAllCompletion = nil
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -138,9 +138,9 @@ private extension CloudKitArticlesZoneDelegate {
|
|||
for receivedStarredArticle in receivedStarredArticles {
|
||||
if let parsedItem = makeParsedItem(receivedStarredArticle) {
|
||||
group.enter()
|
||||
self.account?.update(parsedItem.feedURL, with: Set([parsedItem])) { databaseError in
|
||||
self.account?.update(parsedItem.feedURL, with: Set([parsedItem])) { result in
|
||||
group.leave()
|
||||
if let databaseError = databaseError {
|
||||
if case .failure(let databaseError) = result {
|
||||
os_log(.error, log: self.log, "Error occurred while storing starred items: %@", databaseError.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import Foundation
|
|||
import RSCore
|
||||
import RSParser
|
||||
import Articles
|
||||
import ArticlesDatabase
|
||||
import RSWeb
|
||||
|
||||
public enum LocalAccountDelegateError: String, Error {
|
||||
|
@ -233,6 +234,9 @@ final class LocalAccountDelegate: AccountDelegate {
|
|||
|
||||
extension LocalAccountDelegate: LocalAccountRefresherDelegate {
|
||||
|
||||
func localAccountRefresher(_ refresher: LocalAccountRefresher, didProcess newAndUpdatedArticles: NewAndUpdatedArticles) {
|
||||
}
|
||||
|
||||
func localAccountRefresher(_ refresher: LocalAccountRefresher, requestCompletedFor: WebFeed) {
|
||||
refreshProgress.completeTask()
|
||||
}
|
||||
|
|
|
@ -11,8 +11,10 @@ import RSCore
|
|||
import RSParser
|
||||
import RSWeb
|
||||
import Articles
|
||||
import ArticlesDatabase
|
||||
|
||||
protocol LocalAccountRefresherDelegate {
|
||||
func localAccountRefresher(_ refresher: LocalAccountRefresher, didProcess: NewAndUpdatedArticles)
|
||||
func localAccountRefresher(_ refresher: LocalAccountRefresher, requestCompletedFor: WebFeed)
|
||||
func localAccountRefresherDidFinish(_ refresher: LocalAccountRefresher)
|
||||
}
|
||||
|
@ -97,12 +99,12 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
|
|||
return
|
||||
}
|
||||
|
||||
account.update(feed, with: parsedFeed) { error in
|
||||
if error == nil {
|
||||
account.update(feed, with: parsedFeed) { result in
|
||||
if case .success(let newAndUpdatedArticles) = result {
|
||||
self.delegate?.localAccountRefresher(self, didProcess: newAndUpdatedArticles)
|
||||
if let httpResponse = response as? HTTPURLResponse {
|
||||
feed.conditionalGetInfo = HTTPConditionalGetInfo(urlResponse: httpResponse)
|
||||
}
|
||||
|
||||
feed.contentHash = dataHash
|
||||
}
|
||||
completion()
|
||||
|
@ -157,9 +159,9 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
|
|||
}
|
||||
|
||||
func downloadSessionDidCompleteDownloadObjects(_ downloadSession: DownloadSession) {
|
||||
delegate?.localAccountRefresherDidFinish(self)
|
||||
completions.forEach({ $0() })
|
||||
completions = [() -> Void]()
|
||||
delegate?.localAccountRefresherDidFinish(self)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -27,6 +27,16 @@ public typealias SingleUnreadCountCompletionBlock = (SingleUnreadCountResult) ->
|
|||
public struct NewAndUpdatedArticles {
|
||||
public let newArticles: Set<Article>?
|
||||
public let updatedArticles: Set<Article>?
|
||||
|
||||
public init() {
|
||||
self.newArticles = Set<Article>()
|
||||
self.updatedArticles = Set<Article>()
|
||||
}
|
||||
|
||||
public init(newArticles: Set<Article>?, updatedArticles: Set<Article>?) {
|
||||
self.newArticles = newArticles
|
||||
self.updatedArticles = updatedArticles
|
||||
}
|
||||
}
|
||||
|
||||
public typealias UpdateArticlesResult = Result<NewAndUpdatedArticles, DatabaseError>
|
||||
|
|
Loading…
Reference in New Issue