Erase shared profiles from iCloud correctly (#827)

Do not delete CloudKit zone. Instead, delete Core Data entities and let
sync do the rest. It's also a "more standard" approach.

Deleting the zone right after the entities legitimately makes deletion
ineffective, because it probably spoils sync.
This commit is contained in:
Davide 2024-11-07 12:43:24 +01:00 committed by GitHub
parent 142efa84d0
commit b128b3bf13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 24 additions and 11 deletions

View File

@ -120,4 +120,8 @@ extension CoreDataRepository: ProfileRepository where T == Profile {
public func removeProfiles(withIds profileIds: [Profile.ID]) async throws { public func removeProfiles(withIds profileIds: [Profile.ID]) async throws {
try await removeEntities(withIds: profileIds) try await removeEntities(withIds: profileIds)
} }
public func removeAllProfiles() async throws {
try await removeEntities(withIds: nil)
}
} }

View File

@ -88,10 +88,6 @@ private extension SettingsSectionGroup {
do { do {
pp_log(.app, .info, "Erase CloudKit profiles...") pp_log(.app, .info, "Erase CloudKit profiles...")
try await profileManager.eraseRemotelySharedProfiles() try await profileManager.eraseRemotelySharedProfiles()
let containerId = BundleConfiguration.mainString(for: .cloudKitId)
pp_log(.app, .info, "Erase CloudKit store with identifier \(containerId)...")
try await Utils.eraseCloudKitStore(fromContainerWithId: containerId)
} catch { } catch {
pp_log(.app, .error, "Unable to erase CloudKit store: \(error)") pp_log(.app, .error, "Unable to erase CloudKit store: \(error)")
} }

View File

@ -60,4 +60,9 @@ public final class InMemoryProfileRepository: ProfileRepository {
!ids.contains($0.id) !ids.contains($0.id)
} }
} }
public func removeAllProfiles() async throws {
pp_log(.App.profiles, .info, "Remove all profiles")
profiles = []
}
} }

View File

@ -85,6 +85,10 @@ public final class NEProfileRepository: ProfileRepository {
removedIds.insert(id) removedIds.insert(id)
} }
} }
public func removeAllProfiles() async throws {
try await removeProfiles(withIds: profilesSubject.value.map(\.id))
}
} }
private extension NEProfileRepository { private extension NEProfileRepository {

View File

@ -226,7 +226,7 @@ extension ProfileManager {
public func eraseRemotelySharedProfiles() async throws { public func eraseRemotelySharedProfiles() async throws {
pp_log(.App.profiles, .notice, "Erase remotely shared profiles...") pp_log(.App.profiles, .notice, "Erase remotely shared profiles...")
try await remoteRepository?.removeProfiles(withIds: Array(allRemoteProfiles.keys)) try await remoteRepository?.removeAllProfiles()
} }
} }

View File

@ -33,4 +33,6 @@ public protocol ProfileRepository {
func saveProfile(_ profile: Profile) async throws func saveProfile(_ profile: Profile) async throws
func removeProfiles(withIds profileIds: [Profile.ID]) async throws func removeProfiles(withIds profileIds: [Profile.ID]) async throws
func removeAllProfiles() async throws
} }

View File

@ -139,16 +139,18 @@ public actor CoreDataRepository<CD, T>: NSObject,
} }
} }
public func removeEntities(withIds ids: [UUID]) async throws { public func removeEntities(withIds ids: [UUID]?) async throws {
try await context.perform { [weak self] in try await context.perform { [weak self] in
guard let self else { guard let self else {
return return
} }
let request = newFetchRequest() let request = newFetchRequest()
if let ids {
request.predicate = NSPredicate( request.predicate = NSPredicate(
format: "any uuid in %@", format: "any uuid in %@",
ids ids
) )
}
do { do {
let existing = try context.fetch(request) let existing = try context.fetch(request)
existing.forEach(context.delete) existing.forEach(context.delete)

View File

@ -56,5 +56,5 @@ public protocol Repository {
func saveEntities(_ entities: [Entity]) async throws func saveEntities(_ entities: [Entity]) async throws
func removeEntities(withIds ids: [UUID]) async throws func removeEntities(withIds ids: [UUID]?) async throws
} }