Implement add, move, delete folder operations for feeds.
This commit is contained in:
parent
df1faa368f
commit
90376dac03
|
@ -207,7 +207,7 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
}
|
||||
|
||||
func removeWebFeed(for account: Account, with feed: WebFeed, from container: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
accountZone.removeWebFeed(feed) { result in
|
||||
accountZone.removeWebFeed(feed, from: container) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
container.removeWebFeed(feed)
|
||||
|
@ -218,20 +218,33 @@ final class CloudKitAccountDelegate: AccountDelegate {
|
|||
}
|
||||
}
|
||||
|
||||
func moveWebFeed(for account: Account, with feed: WebFeed, from: Container, to: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
from.removeWebFeed(feed)
|
||||
to.addWebFeed(feed)
|
||||
completion(.success(()))
|
||||
func moveWebFeed(for account: Account, with feed: WebFeed, from fromContainer: Container, to toContainer: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
accountZone.moveWebFeed(feed, from: fromContainer, to: toContainer) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
fromContainer.removeWebFeed(feed)
|
||||
toContainer.addWebFeed(feed)
|
||||
completion(.success(()))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addWebFeed(for account: Account, with feed: WebFeed, to container: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
container.addWebFeed(feed)
|
||||
completion(.success(()))
|
||||
accountZone.addWebFeed(feed, to: container) { result in
|
||||
switch result {
|
||||
case .success:
|
||||
container.addWebFeed(feed)
|
||||
completion(.success(()))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func restoreWebFeed(for account: Account, feed: WebFeed, container: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
container.addWebFeed(feed)
|
||||
completion(.success(()))
|
||||
addWebFeed(for: account, with: feed, to: container, completion: completion)
|
||||
}
|
||||
|
||||
func createFolder(for account: Account, name: String, completion: @escaping (Result<Folder, Error>) -> Void) {
|
||||
|
|
|
@ -94,8 +94,72 @@ final class CloudKitAccountZone: CloudKitZone {
|
|||
}
|
||||
|
||||
/// Deletes a web feed from iCloud
|
||||
func removeWebFeed(_ webFeed: WebFeed, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
delete(externalID: webFeed.externalID , completion: completion)
|
||||
func removeWebFeed(_ webFeed: WebFeed, from: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
guard let fromContainerExternalID = from.externalID else {
|
||||
completion(.failure(CloudKitZoneError.invalidParameter))
|
||||
return
|
||||
}
|
||||
|
||||
fetch(externalID: webFeed.externalID) { result in
|
||||
switch result {
|
||||
case .success(let record):
|
||||
if let containerExternalIDs = record[CloudKitWebFeed.Fields.containerExternalIDs] as? [String] {
|
||||
var containerExternalIDSet = Set(containerExternalIDs)
|
||||
containerExternalIDSet.remove(fromContainerExternalID)
|
||||
if containerExternalIDSet.isEmpty {
|
||||
self.delete(externalID: webFeed.externalID , completion: completion)
|
||||
} else {
|
||||
record[CloudKitWebFeed.Fields.containerExternalIDs] = Array(containerExternalIDSet)
|
||||
self.save(record, completion: completion)
|
||||
}
|
||||
}
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func moveWebFeed(_ webFeed: WebFeed, from: Container, to: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
guard let fromContainerExternalID = from.externalID, let toContainerExternalID = to.externalID else {
|
||||
completion(.failure(CloudKitZoneError.invalidParameter))
|
||||
return
|
||||
}
|
||||
|
||||
fetch(externalID: webFeed.externalID) { result in
|
||||
switch result {
|
||||
case .success(let record):
|
||||
if let containerExternalIDs = record[CloudKitWebFeed.Fields.containerExternalIDs] as? [String] {
|
||||
var containerExternalIDSet = Set(containerExternalIDs)
|
||||
containerExternalIDSet.remove(fromContainerExternalID)
|
||||
containerExternalIDSet.insert(toContainerExternalID)
|
||||
record[CloudKitWebFeed.Fields.containerExternalIDs] = Array(containerExternalIDSet)
|
||||
self.save(record, completion: completion)
|
||||
}
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addWebFeed(_ webFeed: WebFeed, to: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
guard let toContainerExternalID = to.externalID else {
|
||||
completion(.failure(CloudKitZoneError.invalidParameter))
|
||||
return
|
||||
}
|
||||
|
||||
fetch(externalID: webFeed.externalID) { result in
|
||||
switch result {
|
||||
case .success(let record):
|
||||
if let containerExternalIDs = record[CloudKitWebFeed.Fields.containerExternalIDs] as? [String] {
|
||||
var containerExternalIDSet = Set(containerExternalIDs)
|
||||
containerExternalIDSet.insert(toContainerExternalID)
|
||||
record[CloudKitWebFeed.Fields.containerExternalIDs] = Array(containerExternalIDSet)
|
||||
self.save(record, completion: completion)
|
||||
}
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func findOrCreateAccount(completion: @escaping (Result<String, Error>) -> Void) {
|
||||
|
|
|
@ -62,8 +62,8 @@ class CloudKitAcountZoneDelegate: CloudKitZoneDelegate {
|
|||
}
|
||||
|
||||
func removeWebFeed(_ externalID: String) {
|
||||
if let webFeed = account?.existingWebFeed(withExternalID: externalID) {
|
||||
account?.removeWebFeed(webFeed)
|
||||
if let webFeed = account?.existingWebFeed(withExternalID: externalID), let containers = account?.existingContainers(withWebFeed: webFeed) {
|
||||
containers.forEach { $0.removeWebFeed(webFeed) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ private extension CloudKitAcountZoneDelegate {
|
|||
container.removeWebFeed(webFeed)
|
||||
}
|
||||
case .insert(_, let externalID, _):
|
||||
if let container = existingContainers.first(where: { $0.externalID == externalID }) {
|
||||
if let container = account.existingContainer(withExternalID: externalID) {
|
||||
container.addWebFeed(webFeed)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ extension CloudKitZone {
|
|||
case .success:
|
||||
break
|
||||
case .retry(let timeToWait):
|
||||
self.retryOperationIfPossible(retryAfter: timeToWait) {
|
||||
self.retryIfPossible(after: timeToWait) {
|
||||
self.subscribe()
|
||||
}
|
||||
default:
|
||||
|
@ -96,20 +96,6 @@ extension CloudKitZone {
|
|||
}
|
||||
}
|
||||
|
||||
func save(_ record: CKRecord, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
modify(recordsToSave: [record], recordIDsToDelete: [], completion: completion)
|
||||
}
|
||||
|
||||
func delete(externalID: String?, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
guard let externalID = externalID else {
|
||||
completion(.failure(CloudKitZoneError.invalidParameter))
|
||||
return
|
||||
}
|
||||
|
||||
let recordID = CKRecord.ID(recordName: externalID, zoneID: Self.zoneID)
|
||||
modify(recordsToSave: [], recordIDsToDelete: [recordID], completion: completion)
|
||||
}
|
||||
|
||||
func query(_ query: CKQuery, completion: @escaping (Result<[CKRecord], Error>) -> Void) {
|
||||
guard let database = database else {
|
||||
completion(.failure(CloudKitZoneError.unknown))
|
||||
|
@ -125,7 +111,7 @@ extension CloudKitZone {
|
|||
completion(.failure(CloudKitZoneError.unknown))
|
||||
}
|
||||
case .retry(let timeToWait):
|
||||
self.retryOperationIfPossible(retryAfter: timeToWait) {
|
||||
self.retryIfPossible(after: timeToWait) {
|
||||
self.query(query, completion: completion)
|
||||
}
|
||||
default:
|
||||
|
@ -134,6 +120,50 @@ extension CloudKitZone {
|
|||
}
|
||||
}
|
||||
|
||||
func fetch(externalID: String?, completion: @escaping (Result<CKRecord, Error>) -> Void) {
|
||||
guard let externalID = externalID else {
|
||||
completion(.failure(CloudKitZoneError.invalidParameter))
|
||||
return
|
||||
}
|
||||
|
||||
let recordID = CKRecord.ID(recordName: externalID, zoneID: Self.zoneID)
|
||||
|
||||
database?.fetch(withRecordID: recordID) { record, error in
|
||||
switch CloudKitZoneResult.resolve(error) {
|
||||
case .success:
|
||||
DispatchQueue.main.async {
|
||||
if let record = record {
|
||||
completion(.success(record))
|
||||
} else {
|
||||
completion(.failure(CloudKitZoneError.unknown))
|
||||
}
|
||||
}
|
||||
case .retry(let timeToWait):
|
||||
self.retryIfPossible(after: timeToWait) {
|
||||
self.fetch(externalID: externalID, completion: completion)
|
||||
}
|
||||
default:
|
||||
DispatchQueue.main.async {
|
||||
completion(.failure(error!))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func save(_ record: CKRecord, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
modify(recordsToSave: [record], recordIDsToDelete: [], completion: completion)
|
||||
}
|
||||
|
||||
func delete(externalID: String?, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
guard let externalID = externalID else {
|
||||
completion(.failure(CloudKitZoneError.invalidParameter))
|
||||
return
|
||||
}
|
||||
|
||||
let recordID = CKRecord.ID(recordName: externalID, zoneID: Self.zoneID)
|
||||
modify(recordsToSave: [], recordIDsToDelete: [recordID], completion: completion)
|
||||
}
|
||||
|
||||
func modify(recordsToSave: [CKRecord], recordIDsToDelete: [CKRecord.ID], completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
let op = CKModifyRecordsOperation(recordsToSave: recordsToSave, recordIDsToDelete: recordIDsToDelete)
|
||||
|
||||
|
@ -173,7 +203,7 @@ extension CloudKitZone {
|
|||
completion(.failure(CloudKitZoneError.userDeletedZone))
|
||||
}
|
||||
case .retry(let timeToWait):
|
||||
self.retryOperationIfPossible(retryAfter: timeToWait) {
|
||||
self.retryIfPossible(after: timeToWait) {
|
||||
self.modify(recordsToSave: recordsToSave, recordIDsToDelete: recordIDsToDelete, completion: completion)
|
||||
}
|
||||
case .limitExceeded:
|
||||
|
@ -230,7 +260,7 @@ extension CloudKitZone {
|
|||
self.changeToken = token
|
||||
}
|
||||
case .retry(let timeToWait):
|
||||
self.retryOperationIfPossible(retryAfter: timeToWait) {
|
||||
self.retryIfPossible(after: timeToWait) {
|
||||
self.fetchChangesInZone(completion: completion)
|
||||
}
|
||||
default:
|
||||
|
@ -299,8 +329,8 @@ private extension CloudKitZone {
|
|||
}
|
||||
}
|
||||
|
||||
func retryOperationIfPossible(retryAfter: Double, block: @escaping () -> ()) {
|
||||
let delayTime = DispatchTime.now() + retryAfter
|
||||
func retryIfPossible(after: Double, block: @escaping () -> ()) {
|
||||
let delayTime = DispatchTime.now() + after
|
||||
DispatchQueue.main.asyncAfter(deadline: delayTime, execute: {
|
||||
block()
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue