Fix build errors triggered by previous commit.

This commit is contained in:
Brent Simmons 2024-04-20 10:32:57 -07:00
parent fe017d042a
commit 60dd9ad82a
5 changed files with 81 additions and 54 deletions

View File

@ -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()

View File

@ -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 {

View File

@ -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 {

View File

@ -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)
} }

View File

@ -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)