Save starred articles to iCloud.

This commit is contained in:
Maurice Parker 2020-04-02 18:06:47 -05:00
parent f97194b9be
commit d6b094b37e
2 changed files with 116 additions and 11 deletions

View File

@ -86,17 +86,34 @@ final class CloudKitAccountDelegate: AccountDelegate {
return return
} }
self.articlesZone.sendArticleStatus(syncStatuses) { result in let starredArticleIDs = syncStatuses.filter({ $0.key == .starred && $0.flag == true }).map({ $0.articleID })
switch result { account.fetchArticlesAsync(.articleIDs(Set(starredArticleIDs))) { result in
case .success:
self.database.deleteSelectedForProcessing(syncStatuses.map({ $0.articleID }) ) func processWithArticles(_ starredArticles: Set<Article>) {
os_log(.debug, log: self.log, "Done sending article statuses.")
completion(.success(())) self.articlesZone.sendArticleStatus(syncStatuses, starredArticles: starredArticles) { result in
case .failure(let error): switch result {
self.database.resetSelectedForProcessing(syncStatuses.map({ $0.articleID }) ) case .success:
completion(.failure(error)) self.database.deleteSelectedForProcessing(syncStatuses.map({ $0.articleID }) )
os_log(.debug, log: self.log, "Done sending article statuses.")
completion(.success(()))
case .failure(let error):
self.database.resetSelectedForProcessing(syncStatuses.map({ $0.articleID }) )
completion(.failure(error))
}
}
} }
switch result {
case .success(let starredArticles):
processWithArticles(starredArticles)
case .failure(let databaseError):
completion(.failure(databaseError))
}
} }
} }
switch result { switch result {

View File

@ -10,6 +10,7 @@ import Foundation
import os.log import os.log
import RSWeb import RSWeb
import CloudKit import CloudKit
import Articles
import SyncDatabase import SyncDatabase
final class CloudKitArticlesZone: CloudKitZone { final class CloudKitArticlesZone: CloudKitZone {
@ -24,6 +25,37 @@ final class CloudKitArticlesZone: CloudKitZone {
weak var database: CKDatabase? weak var database: CKDatabase?
var delegate: CloudKitZoneDelegate? = nil var delegate: CloudKitZoneDelegate? = nil
struct CloudKitArticle {
static let recordType = "Article"
struct Fields {
static let articleStatus = "articleStatus"
static let webFeedID = "webFeedID"
static let uniqueID = "uniqueID"
static let title = "title"
static let contentHTML = "contentHTML"
static let contentText = "contentText"
static let url = "url"
static let externalURL = "externalURL"
static let summary = "summary"
static let imageURL = "imageURL"
static let datePublished = "datePublished"
static let dateModified = "dateModified"
static let authors = "authors"
}
}
struct CloudKitAuthor {
static let recordType = "Author"
struct Fields {
static let article = "article"
static let authorID = "authorID"
static let name = "name"
static let url = "url"
static let avatarURL = "avatarURL"
static let emailAddress = "emailAddress"
}
}
struct CloudKitArticleStatus { struct CloudKitArticleStatus {
static let recordType = "ArticleStatus" static let recordType = "ArticleStatus"
struct Fields { struct Fields {
@ -38,7 +70,17 @@ final class CloudKitArticlesZone: CloudKitZone {
self.database = container.privateCloudDatabase self.database = container.privateCloudDatabase
} }
func sendArticleStatus(_ syncStatuses: [SyncStatus], completion: @escaping ((Result<Void, Error>) -> Void)) { func sendArticleStatus(_ syncStatuses: [SyncStatus], starredArticles: Set<Article>, completion: @escaping ((Result<Void, Error>) -> Void)) {
var records = makeStatusRecords(syncStatuses)
records.append(contentsOf: makeArticleRecords(starredArticles))
modify(recordsToSave: records, recordIDsToDelete: [], completion: completion)
}
}
private extension CloudKitArticlesZone {
func makeStatusRecords(_ syncStatuses: [SyncStatus]) -> [CKRecord] {
var records = [String: CKRecord]() var records = [String: CKRecord]()
for status in syncStatuses { for status in syncStatuses {
@ -60,7 +102,53 @@ final class CloudKitArticlesZone: CloudKitZone {
} }
} }
modify(recordsToSave: Array(records.values), recordIDsToDelete: [], completion: completion) return Array(records.values)
}
func makeArticleRecords(_ articles: Set<Article>) -> [CKRecord] {
var records = [CKRecord]()
for article in articles {
let record = CKRecord(recordType: CloudKitArticle.recordType, recordID: generateRecordID())
let articleStatusRecordID = CKRecord.ID(recordName: article.articleID, zoneID: Self.zoneID)
record[CloudKitArticle.Fields.articleStatus] = CKRecord.Reference(recordID: articleStatusRecordID, action: .deleteSelf)
record[CloudKitArticle.Fields.webFeedID] = article.webFeedID
record[CloudKitArticle.Fields.uniqueID] = article.uniqueID
record[CloudKitArticle.Fields.title] = article.title
record[CloudKitArticle.Fields.contentHTML] = article.contentHTML
record[CloudKitArticle.Fields.contentText] = article.contentText
record[CloudKitArticle.Fields.url] = article.url
record[CloudKitArticle.Fields.externalURL] = article.externalURL
record[CloudKitArticle.Fields.summary] = article.summary
record[CloudKitArticle.Fields.imageURL] = article.imageURL
record[CloudKitArticle.Fields.datePublished] = article.datePublished
record[CloudKitArticle.Fields.dateModified] = article.dateModified
records.append(record)
if let authors = article.authors {
for author in authors {
records.append(makeAuthorRecord(record, author))
}
}
}
return records
}
func makeAuthorRecord(_ articleRecord: CKRecord, _ author: Author) -> CKRecord {
let record = CKRecord(recordType: CloudKitAuthor.recordType, recordID: generateRecordID())
record[CloudKitAuthor.Fields.article] = CKRecord.Reference(record: articleRecord, action: .deleteSelf)
record[CloudKitAuthor.Fields.authorID] = author.authorID
record[CloudKitAuthor.Fields.name] = author.name
record[CloudKitAuthor.Fields.url] = author.url
record[CloudKitAuthor.Fields.avatarURL] = author.avatarURL
record[CloudKitAuthor.Fields.emailAddress] = author.emailAddress
return record
} }
} }