Refactored starred article passing to make it more reliable
This commit is contained in:
parent
f143248e08
commit
10a87ccfb6
@ -41,19 +41,7 @@ final class CloudKitArticlesZone: CloudKitZone {
|
|||||||
static let imageURL = "imageURL"
|
static let imageURL = "imageURL"
|
||||||
static let datePublished = "datePublished"
|
static let datePublished = "datePublished"
|
||||||
static let dateModified = "dateModified"
|
static let dateModified = "dateModified"
|
||||||
static let authors = "authors"
|
static let parsedAuthors = "parsedAuthors"
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,47 +72,6 @@ final class CloudKitArticlesZone: CloudKitZone {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchArticle(articleID: String, completion: @escaping ((Result<(String, ParsedItem), Error>) -> Void)) {
|
|
||||||
|
|
||||||
let statusRecordID = CKRecord.ID(recordName: articleID, zoneID: Self.zoneID)
|
|
||||||
let statusRecordRef = CKRecord.Reference(recordID: statusRecordID, action: .deleteSelf)
|
|
||||||
let predicate = NSPredicate(format: "articleStatus = %@", statusRecordRef)
|
|
||||||
let ckQuery = CKQuery(recordType: CloudKitArticle.recordType, predicate: predicate)
|
|
||||||
|
|
||||||
query(ckQuery) { result in
|
|
||||||
|
|
||||||
switch result {
|
|
||||||
case .success(let articleRecords):
|
|
||||||
if articleRecords.count == 1 {
|
|
||||||
let articleRecord = articleRecords[0]
|
|
||||||
|
|
||||||
let articleRef = CKRecord.Reference(record: articleRecord, action: .deleteSelf)
|
|
||||||
let predicate = NSPredicate(format: "article = %@", articleRef)
|
|
||||||
let ckQuery = CKQuery(recordType: CloudKitAuthor.recordType, predicate: predicate)
|
|
||||||
|
|
||||||
self.query(ckQuery) { result in
|
|
||||||
switch result {
|
|
||||||
case .success(let authorRecords):
|
|
||||||
if let webFeedID = articleRecord[CloudKitArticle.Fields.webFeedID] as? String, let parsedItem = self.makeParsedItem(articleRecord, authorRecords) {
|
|
||||||
completion(.success((webFeedID, parsedItem)))
|
|
||||||
} else {
|
|
||||||
completion(.failure(CloudKitZoneError.unknown))
|
|
||||||
}
|
|
||||||
case .failure(let error):
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
completion(.failure(CloudKitZoneError.unknown))
|
|
||||||
}
|
|
||||||
case .failure(let error):
|
|
||||||
completion(.failure(error))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension CloudKitArticlesZone {
|
private extension CloudKitArticlesZone {
|
||||||
@ -210,58 +157,26 @@ private extension CloudKitArticlesZone {
|
|||||||
articleRecord[CloudKitArticle.Fields.datePublished] = article.datePublished
|
articleRecord[CloudKitArticle.Fields.datePublished] = article.datePublished
|
||||||
articleRecord[CloudKitArticle.Fields.dateModified] = article.dateModified
|
articleRecord[CloudKitArticle.Fields.dateModified] = article.dateModified
|
||||||
|
|
||||||
records.append(articleRecord)
|
let encoder = JSONEncoder()
|
||||||
|
var parsedAuthors = [String]()
|
||||||
|
|
||||||
if let authors = article.authors {
|
if let authors = article.authors {
|
||||||
for author in authors {
|
for author in authors {
|
||||||
let authorRecord = CKRecord(recordType: CloudKitAuthor.recordType, recordID: generateRecordID())
|
let parsedAuthor = ParsedAuthor(name: author.name,
|
||||||
authorRecord[CloudKitAuthor.Fields.article] = CKRecord.Reference(record: articleRecord, action: .deleteSelf)
|
url: author.url,
|
||||||
authorRecord[CloudKitAuthor.Fields.authorID] = author.authorID
|
avatarURL: author.avatarURL,
|
||||||
authorRecord[CloudKitAuthor.Fields.name] = author.name
|
emailAddress: author.emailAddress)
|
||||||
authorRecord[CloudKitAuthor.Fields.url] = author.url
|
if let data = try? encoder.encode(parsedAuthor), let encodedParsedAuthor = String(data: data, encoding: .utf8) {
|
||||||
authorRecord[CloudKitAuthor.Fields.avatarURL] = author.avatarURL
|
parsedAuthors.append(encodedParsedAuthor)
|
||||||
authorRecord[CloudKitAuthor.Fields.emailAddress] = author.emailAddress
|
}
|
||||||
records.append(authorRecord)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
articleRecord[CloudKitArticle.Fields.parsedAuthors] = parsedAuthors
|
||||||
|
|
||||||
|
records.append(articleRecord)
|
||||||
return records
|
return records
|
||||||
}
|
}
|
||||||
|
|
||||||
func makeParsedItem(_ articleRecord: CKRecord, _ authorRecords: [CKRecord]) -> ParsedItem? {
|
|
||||||
var parsedAuthors = Set<ParsedAuthor>()
|
|
||||||
|
|
||||||
for authorRecord in authorRecords {
|
|
||||||
let parsedAuthor = ParsedAuthor(name: authorRecord[CloudKitAuthor.Fields.name] as? String,
|
|
||||||
url: authorRecord[CloudKitAuthor.Fields.url] as? String,
|
|
||||||
avatarURL: authorRecord[CloudKitAuthor.Fields.avatarURL] as? String,
|
|
||||||
emailAddress: authorRecord[CloudKitAuthor.Fields.emailAddress] as? String)
|
|
||||||
parsedAuthors.insert(parsedAuthor)
|
|
||||||
}
|
|
||||||
|
|
||||||
guard let uniqueID = articleRecord[CloudKitArticle.Fields.uniqueID] as? String,
|
|
||||||
let feedURL = articleRecord[CloudKitArticle.Fields.webFeedID] as? String else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let parsedItem = ParsedItem(syncServiceID: nil,
|
|
||||||
uniqueID: uniqueID,
|
|
||||||
feedURL: feedURL,
|
|
||||||
url: articleRecord[CloudKitArticle.Fields.url] as? String,
|
|
||||||
externalURL: articleRecord[CloudKitArticle.Fields.externalURL] as? String,
|
|
||||||
title: articleRecord[CloudKitArticle.Fields.title] as? String,
|
|
||||||
contentHTML: articleRecord[CloudKitArticle.Fields.contentHTML] as? String,
|
|
||||||
contentText: articleRecord[CloudKitArticle.Fields.contentText] as? String,
|
|
||||||
summary: articleRecord[CloudKitArticle.Fields.summary] as? String,
|
|
||||||
imageURL: articleRecord[CloudKitArticle.Fields.imageURL] as? String,
|
|
||||||
bannerImageURL: articleRecord[CloudKitArticle.Fields.imageURL] as? String,
|
|
||||||
datePublished: articleRecord[CloudKitArticle.Fields.datePublished] as? Date,
|
|
||||||
dateModified: articleRecord[CloudKitArticle.Fields.dateModified] as? Date,
|
|
||||||
authors: parsedAuthors,
|
|
||||||
tags: nil,
|
|
||||||
attachments: nil)
|
|
||||||
|
|
||||||
return parsedItem
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import os.log
|
import os.log
|
||||||
|
import RSParser
|
||||||
import CloudKit
|
import CloudKit
|
||||||
import SyncDatabase
|
import SyncDatabase
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ class CloudKitArticlesZoneDelegate: CloudKitZoneDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func cloudKitDidChange(record: CKRecord) {
|
func cloudKitDidChange(record: CKRecord) {
|
||||||
// Process everything in the batch method
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func cloudKitDidDelete(recordKey: CloudKitRecordKey) {
|
func cloudKitDidDelete(recordKey: CloudKitRecordKey) {
|
||||||
@ -66,10 +67,12 @@ private extension CloudKitArticlesZoneDelegate {
|
|||||||
|
|
||||||
func process(records: [CKRecord], pendingReadStatusArticleIDs: Set<String>, pendingStarredStatusArticleIDs: Set<String>, completion: @escaping (Result<Void, Error>) -> Void) {
|
func process(records: [CKRecord], pendingReadStatusArticleIDs: Set<String>, pendingStarredStatusArticleIDs: Set<String>, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
|
||||||
let receivedUnreadArticleIDs = Set(records.filter( { $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.read] == "0" }).map({ $0.externalID }))
|
let receivedUnreadArticleIDs = Set(records.filter({ $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.read] == "0" }).map({ $0.externalID }))
|
||||||
let receivedReadArticleIDs = Set(records.filter( { $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.read] == "1" }).map({ $0.externalID }))
|
let receivedReadArticleIDs = Set(records.filter({ $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.read] == "1" }).map({ $0.externalID }))
|
||||||
let receivedUnstarredArticleIDs = Set(records.filter( { $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.starred] == "0" }).map({ $0.externalID }))
|
let receivedUnstarredArticleIDs = Set(records.filter({ $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.starred] == "0" }).map({ $0.externalID }))
|
||||||
let receivedStarredArticleIDs = Set(records.filter( { $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.starred] == "1" }).map({ $0.externalID }))
|
let receivedStarredArticleIDs = Set(records.filter({ $0[CloudKitArticlesZone.CloudKitArticleStatus.Fields.starred] == "1" }).map({ $0.externalID }))
|
||||||
|
|
||||||
|
let receivedStarredArticles = records.filter({ $0.recordType == CloudKitArticlesZone.CloudKitArticle.recordType })
|
||||||
|
|
||||||
let updateableUnreadArticleIDs = receivedUnreadArticleIDs.subtracting(pendingReadStatusArticleIDs)
|
let updateableUnreadArticleIDs = receivedUnreadArticleIDs.subtracting(pendingReadStatusArticleIDs)
|
||||||
let updateableReadArticleIDs = receivedReadArticleIDs.subtracting(pendingReadStatusArticleIDs)
|
let updateableReadArticleIDs = receivedReadArticleIDs.subtracting(pendingReadStatusArticleIDs)
|
||||||
@ -98,23 +101,15 @@ private extension CloudKitArticlesZoneDelegate {
|
|||||||
group.leave()
|
group.leave()
|
||||||
}
|
}
|
||||||
|
|
||||||
for updateableStarredArticleID in updateableStarredArticleIDs {
|
for receivedStarredArticle in receivedStarredArticles {
|
||||||
|
if let parsedItem = makeParsedItem(receivedStarredArticle), let statusRef = receivedStarredArticle[CloudKitArticlesZone.CloudKitArticle.Fields.articleStatus] as? CKRecord.Reference {
|
||||||
group.enter()
|
group.enter()
|
||||||
articlesZone?.fetchArticle(articleID: updateableStarredArticleID) { result in
|
self.account?.update(statusRef.recordID.externalID, with: Set([parsedItem])) { databaseError in
|
||||||
switch result {
|
|
||||||
case .success(let (webFeedID, parsedItem)):
|
|
||||||
self.account?.update(webFeedID, with: Set([parsedItem])) { databaseError in
|
|
||||||
group.leave()
|
group.leave()
|
||||||
if let databaseError = databaseError {
|
if let databaseError = databaseError {
|
||||||
os_log(.error, log: self.log, "Error occurred while storing starred items: %@", databaseError.localizedDescription)
|
os_log(.error, log: self.log, "Error occurred while storing starred items: %@", databaseError.localizedDescription)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .failure(let error):
|
|
||||||
group.leave()
|
|
||||||
os_log(.error, log: self.log, "Error occurred while retrieving starred items: %@", error.localizedDescription)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,4 +119,43 @@ private extension CloudKitArticlesZoneDelegate {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func makeParsedItem(_ articleRecord: CKRecord) -> ParsedItem? {
|
||||||
|
var parsedAuthors = Set<ParsedAuthor>()
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
|
||||||
|
if let encodedParsedAuthors = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.parsedAuthors] as? [String] {
|
||||||
|
for encodedParsedAuthor in encodedParsedAuthors {
|
||||||
|
if let data = encodedParsedAuthor.data(using: .utf8), let parsedAuthor = try? decoder.decode(ParsedAuthor.self, from: data) {
|
||||||
|
parsedAuthors.insert(parsedAuthor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let uniqueID = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.uniqueID] as? String,
|
||||||
|
let feedURL = articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.webFeedID] as? String else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let parsedItem = ParsedItem(syncServiceID: nil,
|
||||||
|
uniqueID: uniqueID,
|
||||||
|
feedURL: feedURL,
|
||||||
|
url: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.url] as? String,
|
||||||
|
externalURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.externalURL] as? String,
|
||||||
|
title: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.title] as? String,
|
||||||
|
contentHTML: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentHTML] as? String,
|
||||||
|
contentText: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.contentText] as? String,
|
||||||
|
summary: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.summary] as? String,
|
||||||
|
imageURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.imageURL] as? String,
|
||||||
|
bannerImageURL: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.imageURL] as? String,
|
||||||
|
datePublished: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.datePublished] as? Date,
|
||||||
|
dateModified: articleRecord[CloudKitArticlesZone.CloudKitArticle.Fields.dateModified] as? Date,
|
||||||
|
authors: parsedAuthors,
|
||||||
|
tags: nil,
|
||||||
|
attachments: nil)
|
||||||
|
|
||||||
|
return parsedItem
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 47ba87875fbd026dccc2c4d4382a98cb4a1f1fbc
|
Subproject commit a977d8e84af8645fc8268ac843e8a79b3644b133
|
Loading…
x
Reference in New Issue
Block a user