Fix build errors triggered by previous commit.
This commit is contained in:
parent
fe017d042a
commit
60dd9ad82a
|
@ -21,6 +21,7 @@ import CloudKitExtras
|
||||||
import CommonErrors
|
import CommonErrors
|
||||||
import FeedFinder
|
import FeedFinder
|
||||||
import LocalAccount
|
import LocalAccount
|
||||||
|
import CloudKitSync
|
||||||
|
|
||||||
enum CloudKitAccountDelegateError: LocalizedError {
|
enum CloudKitAccountDelegateError: LocalizedError {
|
||||||
case invalidParameter
|
case invalidParameter
|
||||||
|
@ -204,13 +205,17 @@ enum CloudKitAccountDelegateError: LocalizedError {
|
||||||
|
|
||||||
func renameFeed(for account: Account, with feed: Feed, to name: String) async throws {
|
func renameFeed(for account: Account, with feed: Feed, to name: String) async throws {
|
||||||
|
|
||||||
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
guard let feedExternalID = feed.externalID else {
|
||||||
|
throw LocalAccountDelegateError.invalidParameter
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshProgress.addTask()
|
||||||
defer { refreshProgress.completeTask() }
|
defer { refreshProgress.completeTask() }
|
||||||
|
|
||||||
let editedName = name.isEmpty ? nil : name
|
let editedName = name.isEmpty ? nil : name
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await accountZone.renameFeed(feed, editedName: editedName)
|
try await accountZone.renameFeed(externalID: feedExternalID, editedName: editedName)
|
||||||
feed.editedName = name
|
feed.editedName = name
|
||||||
} catch {
|
} catch {
|
||||||
processAccountError(account, error)
|
processAccountError(account, error)
|
||||||
|
@ -240,11 +245,15 @@ enum CloudKitAccountDelegateError: LocalizedError {
|
||||||
|
|
||||||
func moveFeed(for account: Account, with feed: Feed, from sourceContainer: Container, to destinationContainer: Container) async throws {
|
func moveFeed(for account: Account, with feed: Feed, from sourceContainer: Container, to destinationContainer: Container) async throws {
|
||||||
|
|
||||||
|
guard let feedExternalID = feed.externalID, let sourceContainerExternalID = sourceContainer.externalID, let destinationContainerExternalID = destinationContainer.externalID else {
|
||||||
|
throw LocalAccountDelegateError.invalidParameter
|
||||||
|
}
|
||||||
|
|
||||||
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
||||||
defer { refreshProgress.completeTask() }
|
defer { refreshProgress.completeTask() }
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await accountZone.moveFeed(feed, from: sourceContainer, to: destinationContainer)
|
try await accountZone.moveFeed(externalID: feedExternalID, from: sourceContainerExternalID, to: destinationContainerExternalID)
|
||||||
sourceContainer.removeFeed(feed)
|
sourceContainer.removeFeed(feed)
|
||||||
destinationContainer.addFeed(feed)
|
destinationContainer.addFeed(feed)
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -255,11 +264,15 @@ enum CloudKitAccountDelegateError: LocalizedError {
|
||||||
|
|
||||||
func addFeed(for account: Account, with feed: Feed, to container: any Container) async throws {
|
func addFeed(for account: Account, with feed: Feed, to container: any Container) async throws {
|
||||||
|
|
||||||
|
guard let feedExternalID = feed.externalID, let containerExternalID = container.externalID else {
|
||||||
|
throw LocalAccountDelegateError.invalidParameter
|
||||||
|
}
|
||||||
|
|
||||||
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
||||||
defer { refreshProgress.completeTask() }
|
defer { refreshProgress.completeTask() }
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await accountZone.addFeed(feed, to: container)
|
try await accountZone.addFeed(externalID: feedExternalID, to: containerExternalID)
|
||||||
container.addFeed(feed)
|
container.addFeed(feed)
|
||||||
} catch {
|
} catch {
|
||||||
processAccountError(account, error)
|
processAccountError(account, error)
|
||||||
|
@ -296,11 +309,15 @@ enum CloudKitAccountDelegateError: LocalizedError {
|
||||||
|
|
||||||
func renameFolder(for account: Account, with folder: Folder, to name: String) async throws {
|
func renameFolder(for account: Account, with folder: Folder, to name: String) async throws {
|
||||||
|
|
||||||
|
guard let folderExternalID = folder.externalID else {
|
||||||
|
throw CloudKitAccountDelegateError.invalidParameter
|
||||||
|
}
|
||||||
|
|
||||||
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
||||||
defer { refreshProgress.completeTask() }
|
defer { refreshProgress.completeTask() }
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await accountZone.renameFolder(folder, to: name)
|
try await accountZone.renameFolder(externalID: folderExternalID, to: name)
|
||||||
folder.name = name
|
folder.name = name
|
||||||
} catch {
|
} catch {
|
||||||
processAccountError(account, error)
|
processAccountError(account, error)
|
||||||
|
@ -310,11 +327,15 @@ enum CloudKitAccountDelegateError: LocalizedError {
|
||||||
|
|
||||||
func removeFolder(for account: Account, with folder: Folder) async throws {
|
func removeFolder(for account: Account, with folder: Folder) async throws {
|
||||||
|
|
||||||
|
guard let folderExternalID = folder.externalID else {
|
||||||
|
throw CloudKitAccountDelegateError.invalidParameter
|
||||||
|
}
|
||||||
|
|
||||||
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
||||||
defer { refreshProgress.completeTask() }
|
defer { refreshProgress.completeTask() }
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let feedExternalIDs = try await accountZone.findFeedExternalIDs(for: folder)
|
let feedExternalIDs = try await accountZone.findFeedExternalIDs(for: folderExternalID)
|
||||||
|
|
||||||
let feeds = feedExternalIDs.compactMap { account.existingFeed(withExternalID: $0) }
|
let feeds = feedExternalIDs.compactMap { account.existingFeed(withExternalID: $0) }
|
||||||
var errorOccurred = false
|
var errorOccurred = false
|
||||||
|
@ -334,7 +355,7 @@ enum CloudKitAccountDelegateError: LocalizedError {
|
||||||
throw CloudKitAccountDelegateError.unknown
|
throw CloudKitAccountDelegateError.unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
try await accountZone.removeFolder(folder)
|
try await accountZone.removeFolder(externalID: folderExternalID)
|
||||||
account.removeFolder(folder: folder)
|
account.removeFolder(folder: folder)
|
||||||
|
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -519,6 +540,10 @@ private extension CloudKitAccountDelegate {
|
||||||
|
|
||||||
func createRSSFeed(for account: Account, url: URL, editedName: String?, container: Container, validateFeed: Bool) async throws -> Feed {
|
func createRSSFeed(for account: Account, url: URL, editedName: String?, container: Container, validateFeed: Bool) async throws -> Feed {
|
||||||
|
|
||||||
|
guard let containerExternalID = container.externalID else {
|
||||||
|
throw CloudKitAccountDelegateError.invalidParameter
|
||||||
|
}
|
||||||
|
|
||||||
func addDeadFeed() async throws -> Feed {
|
func addDeadFeed() async throws -> Feed {
|
||||||
|
|
||||||
let feed = account.createFeed(with: editedName,
|
let feed = account.createFeed(with: editedName,
|
||||||
|
@ -531,7 +556,7 @@ private extension CloudKitAccountDelegate {
|
||||||
let externalID = try await accountZone.createFeed(url: url.absoluteString,
|
let externalID = try await accountZone.createFeed(url: url.absoluteString,
|
||||||
name: editedName,
|
name: editedName,
|
||||||
editedName: nil, homePageURL: nil,
|
editedName: nil, homePageURL: nil,
|
||||||
container: container)
|
containerExternalID: containerExternalID)
|
||||||
feed.externalID = externalID
|
feed.externalID = externalID
|
||||||
return feed
|
return feed
|
||||||
} catch {
|
} catch {
|
||||||
|
@ -579,11 +604,11 @@ private extension CloudKitAccountDelegate {
|
||||||
do {
|
do {
|
||||||
try await account.update(feed: feed, with: parsedFeed)
|
try await account.update(feed: feed, with: parsedFeed)
|
||||||
|
|
||||||
let externalID = try await self.accountZone.createFeed(url: bestFeedSpecifier.urlString,
|
let externalID = try await accountZone.createFeed(url: bestFeedSpecifier.urlString,
|
||||||
name: parsedFeed.title,
|
name: parsedFeed.title,
|
||||||
editedName: editedName,
|
editedName: editedName,
|
||||||
homePageURL: parsedFeed.homePageURL,
|
homePageURL: parsedFeed.homePageURL,
|
||||||
container: container)
|
containerExternalID: containerExternalID)
|
||||||
|
|
||||||
feed.externalID = externalID
|
feed.externalID = externalID
|
||||||
sendNewArticlesToTheCloud(account, feed)
|
sendNewArticlesToTheCloud(account, feed)
|
||||||
|
@ -687,15 +712,15 @@ private extension CloudKitAccountDelegate {
|
||||||
|
|
||||||
func removeFeedFromCloud(for account: Account, with feed: Feed, from container: Container) async throws {
|
func removeFeedFromCloud(for account: Account, with feed: Feed, from container: Container) async throws {
|
||||||
|
|
||||||
|
guard let feedExternalID = feed.externalID, let containerExternalID = container.externalID else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
||||||
defer { refreshProgress.completeTask() }
|
defer { refreshProgress.completeTask() }
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await accountZone.removeFeed(feed, from: container)
|
try await accountZone.removeFeed(externalID: feedExternalID, from: containerExternalID)
|
||||||
|
|
||||||
guard let feedExternalID = feed.externalID else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
try await articlesZone.deleteArticles(feedExternalID)
|
try await articlesZone.deleteArticles(feedExternalID)
|
||||||
feed.dropConditionalGetInfo()
|
feed.dropConditionalGetInfo()
|
||||||
|
|
|
@ -12,6 +12,7 @@ import Web
|
||||||
import CloudKit
|
import CloudKit
|
||||||
import Articles
|
import Articles
|
||||||
import CloudKitExtras
|
import CloudKitExtras
|
||||||
|
import CloudKitSync
|
||||||
|
|
||||||
@MainActor final class CloudKitAcountZoneDelegate: CloudKitZoneDelegate {
|
@MainActor final class CloudKitAcountZoneDelegate: CloudKitZoneDelegate {
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import os.log
|
import os.log
|
||||||
import Core
|
import Core
|
||||||
|
import CloudKitSync
|
||||||
|
|
||||||
class CloudKitRemoteNotificationOperation: MainThreadOperation {
|
class CloudKitRemoteNotificationOperation: MainThreadOperation {
|
||||||
|
|
||||||
|
|
|
@ -22,43 +22,43 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor final class CloudKitAccountZone: CloudKitZone {
|
@MainActor public final class CloudKitAccountZone: CloudKitZone {
|
||||||
|
|
||||||
let zoneID: CKRecordZone.ID
|
public let zoneID: CKRecordZone.ID
|
||||||
|
|
||||||
let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "CloudKit")
|
public let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "CloudKit")
|
||||||
|
|
||||||
weak var container: CKContainer?
|
public weak var container: CKContainer?
|
||||||
weak var database: CKDatabase?
|
public weak var database: CKDatabase?
|
||||||
var delegate: CloudKitZoneDelegate?
|
public var delegate: CloudKitZoneDelegate?
|
||||||
|
|
||||||
struct CloudKitFeed {
|
public struct CloudKitFeed {
|
||||||
static let recordType = "AccountWebFeed"
|
public static let recordType = "AccountWebFeed"
|
||||||
struct Fields {
|
public struct Fields {
|
||||||
static let url = "url"
|
public static let url = "url"
|
||||||
static let name = "name"
|
public static let name = "name"
|
||||||
static let editedName = "editedName"
|
public static let editedName = "editedName"
|
||||||
static let homePageURL = "homePageURL"
|
public static let homePageURL = "homePageURL"
|
||||||
static let containerExternalIDs = "containerExternalIDs"
|
public static let containerExternalIDs = "containerExternalIDs"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CloudKitContainer {
|
public struct CloudKitContainer {
|
||||||
static let recordType = "AccountContainer"
|
public static let recordType = "AccountContainer"
|
||||||
struct Fields {
|
public struct Fields {
|
||||||
static let isAccount = "isAccount"
|
public static let isAccount = "isAccount"
|
||||||
static let name = "name"
|
public static let name = "name"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init(container: CKContainer) {
|
public init(container: CKContainer) {
|
||||||
self.container = container
|
self.container = container
|
||||||
self.database = container.privateCloudDatabase
|
self.database = container.privateCloudDatabase
|
||||||
self.zoneID = CKRecordZone.ID(zoneName: "Account", ownerName: CKCurrentUserDefaultName)
|
self.zoneID = CKRecordZone.ID(zoneName: "Account", ownerName: CKCurrentUserDefaultName)
|
||||||
migrateChangeToken()
|
migrateChangeToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
func importOPML(rootExternalID: String, items: [RSOPMLItem]) async throws {
|
public func importOPML(rootExternalID: String, items: [RSOPMLItem]) async throws {
|
||||||
|
|
||||||
var records = [CKRecord]()
|
var records = [CKRecord]()
|
||||||
var feedRecords = [String: CKRecord]()
|
var feedRecords = [String: CKRecord]()
|
||||||
|
@ -94,7 +94,7 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Persist a web feed record to iCloud and return the external key
|
/// Persist a web feed record to iCloud and return the external key
|
||||||
func createFeed(url: String, name: String?, editedName: String?, homePageURL: String?, containerExternalID: String) async throws -> String {
|
public func createFeed(url: String, name: String?, editedName: String?, homePageURL: String?, containerExternalID: String) async throws -> String {
|
||||||
|
|
||||||
let recordID = CKRecord.ID(recordName: url.md5String, zoneID: zoneID)
|
let recordID = CKRecord.ID(recordName: url.md5String, zoneID: zoneID)
|
||||||
let record = CKRecord(recordType: CloudKitFeed.recordType, recordID: recordID)
|
let record = CKRecord(recordType: CloudKitFeed.recordType, recordID: recordID)
|
||||||
|
@ -114,7 +114,7 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rename the given web feed
|
/// Rename the given web feed
|
||||||
func renameFeed(externalID: String, editedName: String?) async throws {
|
public func renameFeed(externalID: String, editedName: String?) async throws {
|
||||||
|
|
||||||
let recordID = CKRecord.ID(recordName: externalID, zoneID: zoneID)
|
let recordID = CKRecord.ID(recordName: externalID, zoneID: zoneID)
|
||||||
let record = CKRecord(recordType: CloudKitFeed.recordType, recordID: recordID)
|
let record = CKRecord(recordType: CloudKitFeed.recordType, recordID: recordID)
|
||||||
|
@ -125,7 +125,7 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
|
|
||||||
/// Removes a web feed from a container and optionally deletes it, returning true if deleted
|
/// Removes a web feed from a container and optionally deletes it, returning true if deleted
|
||||||
@discardableResult
|
@discardableResult
|
||||||
func removeFeed(externalID: String, from containerExternalID: String) async throws -> Bool {
|
public func removeFeed(externalID: String, from containerExternalID: String) async throws -> Bool {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
let record = try await fetch(externalID: externalID)
|
let record = try await fetch(externalID: externalID)
|
||||||
|
@ -155,7 +155,7 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func moveFeed(externalID: String, from sourceContainerExternalID: String, to destinationContainerExternalID: String) async throws {
|
public func moveFeed(externalID: String, from sourceContainerExternalID: String, to destinationContainerExternalID: String) async throws {
|
||||||
|
|
||||||
let record = try await fetch(externalID: externalID)
|
let record = try await fetch(externalID: externalID)
|
||||||
|
|
||||||
|
@ -168,7 +168,7 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func addFeed(externalID: String, to containerExternalID: String) async throws {
|
public func addFeed(externalID: String, to containerExternalID: String) async throws {
|
||||||
|
|
||||||
let record = try await fetch(externalID: externalID)
|
let record = try await fetch(externalID: externalID)
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func findFeedExternalIDs(for folderExternalID: String) async throws -> [String] {
|
public func findFeedExternalIDs(for folderExternalID: String) async throws -> [String] {
|
||||||
|
|
||||||
let predicate = NSPredicate(format: "containerExternalIDs CONTAINS %@", folderExternalID)
|
let predicate = NSPredicate(format: "containerExternalIDs CONTAINS %@", folderExternalID)
|
||||||
let ckQuery = CKQuery(recordType: CloudKitFeed.recordType, predicate: predicate)
|
let ckQuery = CKQuery(recordType: CloudKitFeed.recordType, predicate: predicate)
|
||||||
|
@ -191,7 +191,7 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
return feedExternalIDs
|
return feedExternalIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
func findOrCreateAccount() async throws -> String {
|
public func findOrCreateAccount() async throws -> String {
|
||||||
|
|
||||||
guard let database else { throw CloudKitAccountZoneError.unknown }
|
guard let database else { throw CloudKitAccountZoneError.unknown }
|
||||||
|
|
||||||
|
@ -224,12 +224,12 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFolder(name: String) async throws -> String {
|
public func createFolder(name: String) async throws -> String {
|
||||||
|
|
||||||
return try await createContainer(name: name, isAccount: false)
|
return try await createContainer(name: name, isAccount: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func renameFolder(externalID: String, to name: String) async throws {
|
public func renameFolder(externalID: String, to name: String) async throws {
|
||||||
|
|
||||||
let recordID = CKRecord.ID(recordName: externalID, zoneID: zoneID)
|
let recordID = CKRecord.ID(recordName: externalID, zoneID: zoneID)
|
||||||
let record = CKRecord(recordType: CloudKitContainer.recordType, recordID: recordID)
|
let record = CKRecord(recordType: CloudKitContainer.recordType, recordID: recordID)
|
||||||
|
@ -238,7 +238,7 @@ enum CloudKitAccountZoneError: LocalizedError {
|
||||||
try await save(record)
|
try await save(record)
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeFolder(externalID: String) async throws {
|
public func removeFolder(externalID: String) async throws {
|
||||||
|
|
||||||
try await delete(externalID: externalID)
|
try await delete(externalID: externalID)
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ struct AddAccountsView: View {
|
||||||
.padding()
|
.padding()
|
||||||
}
|
}
|
||||||
|
|
||||||
var localAccount: some View {
|
@MainActor var localAccount: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("Local")
|
Text("Local")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
|
@ -192,7 +192,7 @@ struct AddAccountsView: View {
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder
|
@ViewBuilder
|
||||||
var webAccounts: some View {
|
@MainActor var webAccounts: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("Web")
|
Text("Web")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
|
@ -230,7 +230,7 @@ struct AddAccountsView: View {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var selfhostedAccounts: some View {
|
@MainActor var selfhostedAccounts: some View {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
Text("Self-hosted")
|
Text("Self-hosted")
|
||||||
.font(.headline)
|
.font(.headline)
|
||||||
|
|
Loading…
Reference in New Issue