diff --git a/RadixWallet/Features/ProfileBackupsFeature/RestoreProfileFromBackup/Coordinator/RestoreProfileFromBackupCoordinator+View.swift b/RadixWallet/Features/ProfileBackupsFeature/RestoreProfileFromBackup/Coordinator/RestoreProfileFromBackupCoordinator+View.swift index ff4464dda4..d456ce8d4d 100644 --- a/RadixWallet/Features/ProfileBackupsFeature/RestoreProfileFromBackup/Coordinator/RestoreProfileFromBackupCoordinator+View.swift +++ b/RadixWallet/Features/ProfileBackupsFeature/RestoreProfileFromBackup/Coordinator/RestoreProfileFromBackupCoordinator+View.swift @@ -12,34 +12,35 @@ extension RestoreProfileFromBackupCoordinator { } public var body: some SwiftUI.View { - NavigationStackStore( - store.scope(state: \.path, action: { .child(.path($0)) }) - ) { - path(for: store.scope(state: \.root, action: { .child(.root($0)) })) - } destination: { - path(for: $0) - } + SelectBackup.View(store: store.selectBackup) + .destinations(with: store) } + } +} + +private extension StoreOf { + var selectBackup: StoreOf { + scope(state: \.selectBackup, action: \.child.selectBackup) + } + + var destination: PresentationStoreOf { + func scopeState(state: State) -> PresentationState { + state.$destination + } + return scope(state: scopeState, action: Action.destination) + } +} + +@MainActor +private extension View { + func destinations(with store: StoreOf) -> some View { + let destinationStore = store.destination + return importMnemonics(with: destinationStore) + } - private func path( - for store: StoreOf - ) -> some SwiftUI.View { - SwitchStore(store) { state in - switch state { - case .selectBackup: - CaseLet( - /RestoreProfileFromBackupCoordinator.Path.State.selectBackup, - action: RestoreProfileFromBackupCoordinator.Path.Action.selectBackup, - then: { SelectBackup.View(store: $0) } - ) - case .importMnemonicsFlow: - CaseLet( - /RestoreProfileFromBackupCoordinator.Path.State.importMnemonicsFlow, - action: RestoreProfileFromBackupCoordinator.Path.Action.importMnemonicsFlow, - then: { ImportMnemonicsFlowCoordinator.View(store: $0) } - ) - } - } + private func importMnemonics(with destinationStore: PresentationStoreOf) -> some View { + sheet(store: destinationStore.scope(state: \.importMnemonicsFlow, action: \.importMnemonicsFlow)) { + ImportMnemonicsFlowCoordinator.View(store: $0) } } } diff --git a/RadixWallet/Features/ProfileBackupsFeature/RestoreProfileFromBackup/Coordinator/RestoreProfileFromBackupCoordinator.swift b/RadixWallet/Features/ProfileBackupsFeature/RestoreProfileFromBackup/Coordinator/RestoreProfileFromBackupCoordinator.swift index 2008a972ad..3ae9cae7d8 100644 --- a/RadixWallet/Features/ProfileBackupsFeature/RestoreProfileFromBackup/Coordinator/RestoreProfileFromBackupCoordinator.swift +++ b/RadixWallet/Features/ProfileBackupsFeature/RestoreProfileFromBackup/Coordinator/RestoreProfileFromBackupCoordinator.swift @@ -11,32 +11,25 @@ public struct ProfileSelection: Sendable, Hashable { // MARK: - RestoreProfileFromBackupCoordinator public struct RestoreProfileFromBackupCoordinator: Sendable, FeatureReducer { public struct State: Sendable, Hashable { - public var root: Path.State - public var path: StackState = .init() + public var selectBackup = SelectBackup.State() public var profileSelection: ProfileSelection? - public init() { - self.root = .selectBackup(.init()) - } + @PresentationState + public var destination: Destination.State? } - public struct Path: Sendable, Hashable, Reducer { + public struct Destination: DestinationReducer { @CasePathable public enum State: Sendable, Hashable { - case selectBackup(SelectBackup.State) case importMnemonicsFlow(ImportMnemonicsFlowCoordinator.State) } @CasePathable public enum Action: Sendable, Equatable { - case selectBackup(SelectBackup.Action) case importMnemonicsFlow(ImportMnemonicsFlowCoordinator.Action) } public var body: some ReducerOf { - Scope(state: \.selectBackup, action: \.selectBackup) { - SelectBackup() - } Scope(state: \.importMnemonicsFlow, action: \.importMnemonicsFlow) { ImportMnemonicsFlowCoordinator() } @@ -44,13 +37,12 @@ public struct RestoreProfileFromBackupCoordinator: Sendable, FeatureReducer { } public enum InternalAction: Sendable, Equatable { - case delayedAppendToPath(RestoreProfileFromBackupCoordinator.Path.State) + case startImportMnemonicsFlow(Profile) } @CasePathable public enum ChildAction: Sendable, Equatable { - case root(Path.Action) - case path(StackActionOf) + case selectBackup(SelectBackup.Action) } public enum DelegateAction: Sendable, Equatable { @@ -69,44 +61,50 @@ public struct RestoreProfileFromBackupCoordinator: Sendable, FeatureReducer { public init() {} public var body: some ReducerOf { - Scope(state: \.root, action: \.child.root) { - Path() + Scope(state: \.selectBackup, action: \.child.selectBackup) { + SelectBackup() } - Reduce(core) - .forEach(\.path, action: \.child.path) { - Path() + .ifLet(destinationPath, action: /Action.destination) { + Destination() } } - public func reduce(into state: inout State, internalAction: InternalAction) -> Effect { - switch internalAction { - case let .delayedAppendToPath(destination): - state.path.append(destination) - return .none - } - } + private let destinationPath: WritableKeyPath> = \.$destination public func reduce(into state: inout State, childAction: ChildAction) -> Effect { switch childAction { - case let .root(.selectBackup(.delegate(.selectedProfile(profile, containsLegacyP2PLinks)))): + case let .selectBackup(.delegate(.selectedProfile(profile, containsLegacyP2PLinks))): state.profileSelection = .init(profile: profile, containsP2PLinks: containsLegacyP2PLinks) return .run { send in try? await clock.sleep(for: .milliseconds(300)) _ = await radixConnectClient.loadP2PLinksAndConnectAll() - await send(.internal(.delayedAppendToPath( - .importMnemonicsFlow(.init(context: .fromOnboarding(profile: profile))) - ))) + await send(.internal(.startImportMnemonicsFlow(profile))) } - case .root(.selectBackup(.delegate(.backToStartOfOnboarding))): + case .selectBackup(.delegate(.backToStartOfOnboarding)): return .send(.delegate(.backToStartOfOnboarding)) - case .root(.selectBackup(.delegate(.profileCreatedFromImportedBDFS))): + case .selectBackup(.delegate(.profileCreatedFromImportedBDFS)): return .send(.delegate(.profileCreatedFromImportedBDFS)) - case let .path(.element(_, action: .importMnemonicsFlow(.delegate(.finishedImportingMnemonics(skipList, _, notYetSavedNewMainBDFS))))): + default: + return .none + } + } + + public func reduce(into state: inout State, internalAction: InternalAction) -> Effect { + switch internalAction { + case let .startImportMnemonicsFlow(profile): + state.destination = .importMnemonicsFlow(.init(context: .fromOnboarding(profile: profile))) + return .none + } + } + + public func reduce(into state: inout State, presentedAction: Destination.Action) -> Effect { + switch presentedAction { + case let .importMnemonicsFlow(.delegate(.finishedImportingMnemonics(skipList, _, notYetSavedNewMainBDFS))): loggerGlobal.notice("Starting import snapshot process...") guard let profileSelection = state.profileSelection else { preconditionFailure("Expected to have a profile") @@ -130,8 +128,8 @@ public struct RestoreProfileFromBackupCoordinator: Sendable, FeatureReducer { errorQueue.schedule(error) } - case let .path(.element(_, action: .importMnemonicsFlow(.delegate(.finishedEarly(didFail))))): - state.path.removeLast() + case let .importMnemonicsFlow(.delegate(.finishedEarly(didFail))): + state.destination = nil return .run { send in await radixConnectClient.disconnectAll() if didFail {