diff --git a/Library/Sources/AppUIMain/Views/App/OnboardingModifier.swift b/Library/Sources/AppUIMain/Views/App/OnboardingModifier.swift index 860d4a02..8d4a0612 100644 --- a/Library/Sources/AppUIMain/Views/App/OnboardingModifier.swift +++ b/Library/Sources/AppUIMain/Views/App/OnboardingModifier.swift @@ -29,6 +29,9 @@ import SwiftUI struct OnboardingModifier: ViewModifier { + @EnvironmentObject + private var migrationManager: MigrationManager + @Environment(\.isUITesting) private var isUITesting @@ -87,6 +90,10 @@ private extension OnboardingModifier { switch step { case .migrateV3: + guard migrationManager.hasMigratableProfiles else { + advance() + return + } modalRoute = .migrateProfiles case .community: isPresentingCommunity = true diff --git a/Library/Sources/CommonLibrary/Business/MigrationManager.swift b/Library/Sources/CommonLibrary/Business/MigrationManager.swift index 1afb9da6..6cb15d42 100644 --- a/Library/Sources/CommonLibrary/Business/MigrationManager.swift +++ b/Library/Sources/CommonLibrary/Business/MigrationManager.swift @@ -62,6 +62,10 @@ public final class MigrationManager: ObservableObject { // MARK: - Public interface extension MigrationManager { + public var hasMigratableProfiles: Bool { + profileStrategy.hasMigratableProfiles + } + public func fetchMigratableProfiles() async throws -> [MigratableProfile] { try await profileStrategy.fetchMigratableProfiles() } @@ -173,7 +177,8 @@ private extension MigrationManager { // MARK: - Dummy private final class DummyProfileStrategy: ProfileMigrationStrategy { - public init() { + var hasMigratableProfiles: Bool { + false } public func fetchMigratableProfiles() async throws -> [MigratableProfile] { diff --git a/Library/Sources/CommonLibrary/Strategy/ProfileMigrationStrategy.swift b/Library/Sources/CommonLibrary/Strategy/ProfileMigrationStrategy.swift index bac7ed46..06d4ea90 100644 --- a/Library/Sources/CommonLibrary/Strategy/ProfileMigrationStrategy.swift +++ b/Library/Sources/CommonLibrary/Strategy/ProfileMigrationStrategy.swift @@ -27,6 +27,8 @@ import Foundation import PassepartoutKit public protocol ProfileMigrationStrategy { + var hasMigratableProfiles: Bool { get} + func fetchMigratableProfiles() async throws -> [MigratableProfile] func fetchProfile(withId profileId: UUID) async throws -> Profile? diff --git a/Library/Sources/LegacyV2/Strategy/CDProfileRepositoryV2.swift b/Library/Sources/LegacyV2/Strategy/CDProfileRepositoryV2.swift index 08012fbc..bafa7828 100644 --- a/Library/Sources/LegacyV2/Strategy/CDProfileRepositoryV2.swift +++ b/Library/Sources/LegacyV2/Strategy/CDProfileRepositoryV2.swift @@ -42,6 +42,22 @@ final class CDProfileRepositoryV2: Sendable { self.context = context } + var hasMigratableProfiles: Bool { + do { + return try context.performAndWait { [weak self] in + guard let self else { + return false + } + let entities = try CDProfile.fetchRequest().execute() + return !entities.compactMap { + ($0.encryptedJSON ?? $0.json) != nil + }.isEmpty + } + } catch { + return false + } + } + func migratableProfiles() async throws -> [MigratableProfile] { try await fetchProfiles( prefetch: { @@ -49,7 +65,7 @@ final class CDProfileRepositoryV2: Sendable { }, map: { $0.compactMap { - guard $0.value.encryptedJSON ?? $0.value.json != nil else { + guard ($0.value.encryptedJSON ?? $0.value.json) != nil else { pp_log(.App.migration, .error, "ProfileV2 \($0.key) is not migratable: missing JSON") return nil } diff --git a/Library/Sources/LegacyV2/Strategy/ProfileV2MigrationStrategy.swift b/Library/Sources/LegacyV2/Strategy/ProfileV2MigrationStrategy.swift index 2a67d5c1..2812f16d 100644 --- a/Library/Sources/LegacyV2/Strategy/ProfileV2MigrationStrategy.swift +++ b/Library/Sources/LegacyV2/Strategy/ProfileV2MigrationStrategy.swift @@ -74,6 +74,10 @@ public final class ProfileV2MigrationStrategy: ProfileMigrationStrategy, Sendabl // MARK: - ProfileMigrationStrategy extension ProfileV2MigrationStrategy { + public var hasMigratableProfiles: Bool { + profilesRepository.hasMigratableProfiles + } + public func fetchMigratableProfiles() async throws -> [MigratableProfile] { try await profilesRepository.migratableProfiles() } diff --git a/Library/Tests/CommonLibraryTests/Mock/MockProfileMigrationStrategy.swift b/Library/Tests/CommonLibraryTests/Mock/MockProfileMigrationStrategy.swift index 44573573..aceec9a8 100644 --- a/Library/Tests/CommonLibraryTests/Mock/MockProfileMigrationStrategy.swift +++ b/Library/Tests/CommonLibraryTests/Mock/MockProfileMigrationStrategy.swift @@ -34,6 +34,10 @@ final class MockProfileMigrationStrategy: ProfileMigrationStrategy { var failedProfiles: Set = [] + var hasMigratableProfiles: Bool { + !migratedProfiles.isEmpty + } + func fetchMigratableProfiles() async throws -> [MigratableProfile] { migratableProfiles }