Add code to process new article entries.
This commit is contained in:
parent
4418a4bb02
commit
983138366f
@ -801,16 +801,16 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||||||
/// Mark articleIDs statuses based on statusKey and flag.
|
/// Mark articleIDs statuses based on statusKey and flag.
|
||||||
/// Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
/// Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||||
/// Returns a set of new article statuses.
|
/// 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 {
|
guard !articleIDs.isEmpty else {
|
||||||
completion?(.success(Set<ArticleStatus>()))
|
completion?(.success(Set<String>()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
database.markAndFetchNew(articleIDs: articleIDs, statusKey: statusKey, flag: flag) { result in
|
database.markAndFetchNew(articleIDs: articleIDs, statusKey: statusKey, flag: flag) { result in
|
||||||
switch result {
|
switch result {
|
||||||
case .success(let newArticleStatuses):
|
case .success(let newArticleStatusIDs):
|
||||||
self.noteStatusesForArticleIDsDidChange(articleIDs)
|
self.noteStatusesForArticleIDsDidChange(articleIDs)
|
||||||
completion?(.success(newArticleStatuses))
|
completion?(.success(newArticleStatusIDs))
|
||||||
case .failure(let databaseError):
|
case .failure(let databaseError):
|
||||||
completion?(.failure(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.
|
/// 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.
|
/// 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)
|
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.
|
/// 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.
|
/// 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)
|
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.
|
/// 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.
|
/// 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)
|
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.
|
/// 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.
|
/// 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)
|
markAndFetchNew(articleIDs: articleIDs, statusKey: .starred, flag: false, completion: completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -893,7 +893,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
|||||||
|
|
||||||
public func debugDropConditionalGetInfo() {
|
public func debugDropConditionalGetInfo() {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
flattenedWebFeeds().forEach{ $0.debugDropConditionalGetInfo() }
|
flattenedWebFeeds().forEach{ $0.dropConditionalGetInfo() }
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -481,7 +481,11 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||||||
self.account = account
|
self.account = account
|
||||||
|
|
||||||
accountZone.delegate = CloudKitAcountZoneDelegate(account: account, refreshProgress: refreshProgress)
|
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
|
// Check to see if this is a new account and initialize anything we need
|
||||||
if account.externalID == nil {
|
if account.externalID == nil {
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import os.log
|
import os.log
|
||||||
import RSParser
|
import RSParser
|
||||||
|
import RSWeb
|
||||||
import CloudKit
|
import CloudKit
|
||||||
import SyncDatabase
|
import SyncDatabase
|
||||||
|
|
||||||
@ -19,11 +20,15 @@ class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate {
|
|||||||
weak var account: Account?
|
weak var account: Account?
|
||||||
var database: SyncDatabase
|
var database: SyncDatabase
|
||||||
weak var articlesZone: CloudKitArticlesZone?
|
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.account = account
|
||||||
self.database = database
|
self.database = database
|
||||||
self.articlesZone = articlesZone
|
self.articlesZone = articlesZone
|
||||||
|
self.refresher = refresher
|
||||||
|
self.refreshProgress = refreshProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
func cloudKitDidChange(record: CKRecord) {
|
func cloudKitDidChange(record: CKRecord) {
|
||||||
@ -82,8 +87,37 @@ private extension CloudKitArticlesZoneDelegate {
|
|||||||
let group = DispatchGroup()
|
let group = DispatchGroup()
|
||||||
|
|
||||||
group.enter()
|
group.enter()
|
||||||
account?.markAsUnread(updateableUnreadArticleIDs) { _ in
|
account?.markAsUnread(updateableUnreadArticleIDs) { result in
|
||||||
|
switch result {
|
||||||
|
case .success(let newArticleStatusIDs):
|
||||||
|
|
||||||
|
if newArticleStatusIDs.isEmpty {
|
||||||
group.leave()
|
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()
|
group.enter()
|
||||||
@ -119,7 +153,6 @@ private extension CloudKitArticlesZoneDelegate {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func makeParsedItem(_ articleRecord: CKRecord) -> ParsedItem? {
|
func makeParsedItem(_ articleRecord: CKRecord) -> ParsedItem? {
|
||||||
var parsedAuthors = Set<ParsedAuthor>()
|
var parsedAuthors = Set<ParsedAuthor>()
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@ protocol LocalAccountRefresherDelegate {
|
|||||||
|
|
||||||
final class LocalAccountRefresher {
|
final class LocalAccountRefresher {
|
||||||
|
|
||||||
|
private var completions = [() -> Void]()
|
||||||
private var isSuspended = false
|
private var isSuspended = false
|
||||||
var delegate: LocalAccountRefresherDelegate?
|
var delegate: LocalAccountRefresherDelegate?
|
||||||
|
|
||||||
@ -26,7 +27,10 @@ final class LocalAccountRefresher {
|
|||||||
return DownloadSession(delegate: self)
|
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)
|
downloadSession.downloadObjects(feeds as NSSet)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +158,8 @@ extension LocalAccountRefresher: DownloadSessionDelegate {
|
|||||||
|
|
||||||
func downloadSessionDidCompleteDownloadObjects(_ downloadSession: DownloadSession) {
|
func downloadSessionDidCompleteDownloadObjects(_ downloadSession: DownloadSession) {
|
||||||
delegate?.localAccountRefresherDidFinish(self)
|
delegate?.localAccountRefresherDidFinish(self)
|
||||||
|
completions.forEach({ $0() })
|
||||||
|
completions = [() -> Void]()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -221,9 +221,9 @@ public final class WebFeed: Feed, Renamable, Hashable {
|
|||||||
self.metadata = metadata
|
self.metadata = metadata
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Debug
|
// MARK: - API
|
||||||
|
|
||||||
public func debugDropConditionalGetInfo() {
|
public func dropConditionalGetInfo() {
|
||||||
conditionalGetInfo = nil
|
conditionalGetInfo = nil
|
||||||
contentHash = nil
|
contentHash = nil
|
||||||
}
|
}
|
||||||
|
@ -222,7 +222,7 @@ public final class ArticlesDatabase {
|
|||||||
return try articlesTable.mark(articles, statusKey, flag)
|
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)
|
articlesTable.markAndFetchNew(articleIDs, statusKey, flag, completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,7 +418,7 @@ final class ArticlesTable: DatabaseTable {
|
|||||||
return statuses
|
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
|
queue.runInTransaction { databaseResult in
|
||||||
switch databaseResult {
|
switch databaseResult {
|
||||||
case .success(let database):
|
case .success(let database):
|
||||||
|
@ -85,11 +85,11 @@ final class StatusesTable: DatabaseTable {
|
|||||||
return updatedStatuses
|
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 (statusesDictionary, newStatusIDs) = ensureStatusesForArticleIDs(articleIDs, flag, database)
|
||||||
let statuses = Set(statusesDictionary.values)
|
let statuses = Set(statusesDictionary.values)
|
||||||
mark(statuses, statusKey, flag, database)
|
mark(statuses, statusKey, flag, database)
|
||||||
return Set(newStatusIDs.compactMap({ statusesDictionary[$0] }))
|
return newStatusIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Fetching
|
// MARK: - Fetching
|
||||||
|
Loading…
x
Reference in New Issue
Block a user