Restore Wallet Coord Flow
- Restore wallet flow redesign made as rewired navigation to a whole new flow
This commit is contained in:
parent
02dfcb41b6
commit
ab3226aced
|
@ -96,7 +96,7 @@ let package = Package(
|
|||
.package(url: "https://github.com/pointfreeco/swift-composable-architecture", from: "1.18.0"),
|
||||
.package(url: "https://github.com/pointfreeco/swift-case-paths", from: "1.5.6"),
|
||||
.package(url: "https://github.com/pointfreeco/swift-url-routing", from: "0.6.2"),
|
||||
.package(url: "https://github.com/zcash-hackworks/MnemonicSwift", from: "2.2.4"),
|
||||
.package(url: "https://github.com/zcash-hackworks/MnemonicSwift", from: "2.2.5"),
|
||||
.package(url: "https://github.com/Electric-Coin-Company/zcash-swift-wallet-sdk", from: "2.2.11"),
|
||||
.package(url: "https://github.com/flexa/flexa-ios.git", from: "1.0.9"),
|
||||
.package(url: "https://github.com/pacu/zcash-swift-payment-uri", from: "0.1.0-beta.10"),
|
||||
|
@ -501,6 +501,7 @@ let package = Package(
|
|||
.target(
|
||||
name: "OnboardingFlow",
|
||||
dependencies: [
|
||||
"CoordFlows",
|
||||
"Generated",
|
||||
"ImportWallet",
|
||||
"Models",
|
||||
|
|
|
@ -26,4 +26,6 @@ public struct MnemonicClient {
|
|||
public var asWords: (String) -> [String] = { _ in [] }
|
||||
/// Validates whether the given mnemonic is correct
|
||||
public var isValid: (String) throws -> Void
|
||||
/// Suggests mnemonic words for a given prefix
|
||||
public var suggestWords: (String) -> [String] = { _ in [] }
|
||||
}
|
||||
|
|
|
@ -26,6 +26,9 @@ extension MnemonicClient: DependencyKey {
|
|||
},
|
||||
isValid: { mnemonic in
|
||||
try Mnemonic.validate(mnemonic: mnemonic)
|
||||
},
|
||||
suggestWords: { prefix in
|
||||
MnemonicLanguageType.english.words().filter { $0.hasPrefix(prefix) }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ extension MnemonicClient {
|
|||
|
||||
return mnemonic.components(separatedBy: " ")
|
||||
},
|
||||
isValid: { _ in }
|
||||
isValid: { _ in },
|
||||
suggestWords: { _ in [] }
|
||||
)
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ extension MnemonicClient: TestDependencyKey {
|
|||
randomMnemonicWords: unimplemented("\(Self.self).randomMnemonicWords", placeholder: []),
|
||||
toSeed: unimplemented("\(Self.self).toSeed", placeholder: []),
|
||||
asWords: unimplemented("\(Self.self).asWords", placeholder: []),
|
||||
isValid: unimplemented("\(Self.self).isValid", placeholder: {}())
|
||||
isValid: unimplemented("\(Self.self).isValid", placeholder: {}()),
|
||||
suggestWords: unimplemented("\(Self.self).suggestWords", placeholder: [])
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -24,6 +25,7 @@ extension MnemonicClient {
|
|||
randomMnemonicWords: { [] },
|
||||
toSeed: { _ in [] },
|
||||
asWords: { _ in [] },
|
||||
isValid: { _ in }
|
||||
isValid: { _ in },
|
||||
suggestWords: { _ in [] }
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
//
|
||||
// RestoreWalletCoordFlowCoordinator.swift
|
||||
// Zashi
|
||||
//
|
||||
// Created by Lukáš Korba on 27-03-2025.
|
||||
//
|
||||
|
||||
import ComposableArchitecture
|
||||
import Generated
|
||||
|
||||
// Path
|
||||
|
||||
extension RestoreWalletCoordFlow {
|
||||
public func coordinatorReduce() -> Reduce<RestoreWalletCoordFlow.State, RestoreWalletCoordFlow.Action> {
|
||||
Reduce { state, action in
|
||||
switch action {
|
||||
// MARK: - Self
|
||||
|
||||
// case .path(.element(id: _, action: .requestZec(.requestTapped))):
|
||||
// state.path.append(.requestZecSummary(state.requestZecState))
|
||||
// return .none
|
||||
|
||||
default: return .none
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
//
|
||||
// RestoreWalletCoordFlowStore.swift
|
||||
// Zashi
|
||||
//
|
||||
// Created by Lukáš Korba on 27-03-2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import ComposableArchitecture
|
||||
import ZcashLightClientKit
|
||||
|
||||
// Path
|
||||
|
||||
@Reducer
|
||||
public struct RestoreWalletCoordFlow {
|
||||
@Reducer
|
||||
public enum Path {
|
||||
}
|
||||
|
||||
@ObservableState
|
||||
public struct State {
|
||||
public var path = StackState<Path.State>()
|
||||
// public var zecKeyboardState = ZecKeyboard.State.initial
|
||||
|
||||
public init() { }
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
case path(StackActionOf<Path>)
|
||||
// case zecKeyboard(ZecKeyboard.Action)
|
||||
}
|
||||
|
||||
public init() { }
|
||||
|
||||
public var body: some Reducer<State, Action> {
|
||||
coordinatorReduce()
|
||||
|
||||
// Scope(state: \.zecKeyboardState, action: \.zecKeyboard) {
|
||||
// ZecKeyboard()
|
||||
// }
|
||||
|
||||
Reduce { state, action in
|
||||
switch action {
|
||||
default: return .none
|
||||
}
|
||||
}
|
||||
.forEach(\.path, action: \.path)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// RestoreWalletCoordFlowView.swift
|
||||
// Zashi
|
||||
//
|
||||
// Created by Lukáš Korba on 27-03-2025.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import ComposableArchitecture
|
||||
|
||||
import UIComponents
|
||||
import Generated
|
||||
|
||||
// Path
|
||||
|
||||
public struct RestoreWalletCoordFlowView: View {
|
||||
@Environment(\.colorScheme) var colorScheme
|
||||
|
||||
@Perception.Bindable var store: StoreOf<RestoreWalletCoordFlow>
|
||||
|
||||
public init(store: StoreOf<RestoreWalletCoordFlow>) {
|
||||
self.store = store
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
WithPerceptionTracking {
|
||||
NavigationStack(path: $store.scope(state: \.path, action: \.path)) {
|
||||
Text("RestoreWalletCoordFlowView")
|
||||
// ZecKeyboardView(
|
||||
// store:
|
||||
// store.scope(
|
||||
// state: \.zecKeyboardState,
|
||||
// action: \.zecKeyboard
|
||||
// ),
|
||||
// tokenName: tokenName
|
||||
// )
|
||||
// .navigationBarHidden(true)
|
||||
} destination: { store in
|
||||
// switch store.case {
|
||||
// case let .requestZec(store):
|
||||
// RequestZecView(store: store, tokenName: tokenName)
|
||||
// }
|
||||
}
|
||||
.navigationBarHidden(!store.path.isEmpty)
|
||||
}
|
||||
.padding(.horizontal, 4)
|
||||
.applyScreenBackground()
|
||||
.zashiBack()
|
||||
.screenTitle(L10n.General.request)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
NavigationView {
|
||||
RestoreWalletCoordFlowView(store: RestoreWalletCoordFlow.placeholder)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Placeholders
|
||||
|
||||
extension RestoreWalletCoordFlow.State {
|
||||
public static let initial = RestoreWalletCoordFlow.State()
|
||||
}
|
||||
|
||||
extension RestoreWalletCoordFlow {
|
||||
public static let placeholder = StoreOf<RestoreWalletCoordFlow>(
|
||||
initialState: .initial
|
||||
) {
|
||||
RestoreWalletCoordFlow()
|
||||
}
|
||||
}
|
|
@ -13,11 +13,12 @@ import Models
|
|||
import ImportWallet
|
||||
import SecurityWarning
|
||||
import ZcashLightClientKit
|
||||
import CoordFlows
|
||||
|
||||
@Reducer
|
||||
public struct OnboardingFlow {
|
||||
@ObservableState
|
||||
public struct State: Equatable {
|
||||
public struct State {
|
||||
public enum Destination: Equatable, CaseIterable {
|
||||
case createNewWallet
|
||||
case importExistingWallet
|
||||
|
@ -25,27 +26,31 @@ public struct OnboardingFlow {
|
|||
|
||||
public var destination: Destination?
|
||||
public var walletConfig: WalletConfig
|
||||
public var importWalletState: ImportWallet.State
|
||||
// public var importWalletState: ImportWallet.State
|
||||
public var securityWarningState: SecurityWarning.State
|
||||
|
||||
// Path
|
||||
public var restoreWalletCoordFlowState = RestoreWalletCoordFlow.State.initial
|
||||
|
||||
public init(
|
||||
destination: Destination? = nil,
|
||||
walletConfig: WalletConfig,
|
||||
importWalletState: ImportWallet.State,
|
||||
// importWalletState: ImportWallet.State,
|
||||
securityWarningState: SecurityWarning.State
|
||||
) {
|
||||
self.destination = destination
|
||||
self.walletConfig = walletConfig
|
||||
self.importWalletState = importWalletState
|
||||
// self.importWalletState = importWalletState
|
||||
self.securityWarningState = securityWarningState
|
||||
}
|
||||
}
|
||||
|
||||
public enum Action: Equatable {
|
||||
public enum Action {
|
||||
case createNewWallet
|
||||
case importExistingWallet
|
||||
case importWallet(ImportWallet.Action)
|
||||
// case importWallet(ImportWallet.Action)
|
||||
case onAppear
|
||||
case restoreWalletCoordFlow(RestoreWalletCoordFlow.Action)
|
||||
case securityWarning(SecurityWarning.Action)
|
||||
case updateDestination(OnboardingFlow.State.Destination?)
|
||||
}
|
||||
|
@ -53,14 +58,18 @@ public struct OnboardingFlow {
|
|||
public init() { }
|
||||
|
||||
public var body: some Reducer<State, Action> {
|
||||
Scope(state: \.importWalletState, action: \.importWallet) {
|
||||
ImportWallet()
|
||||
}
|
||||
// Scope(state: \.importWalletState, action: \.importWallet) {
|
||||
// ImportWallet()
|
||||
// }
|
||||
|
||||
Scope(state: \.securityWarningState, action: \.securityWarning) {
|
||||
SecurityWarning()
|
||||
}
|
||||
|
||||
Scope(state: \.restoreWalletCoordFlowState, action: \.restoreWalletCoordFlow) {
|
||||
RestoreWalletCoordFlow()
|
||||
}
|
||||
|
||||
Reduce { state, action in
|
||||
switch action {
|
||||
case .onAppear:
|
||||
|
@ -78,11 +87,14 @@ public struct OnboardingFlow {
|
|||
state.destination = .importExistingWallet
|
||||
return .none
|
||||
|
||||
case .importWallet:
|
||||
return .none
|
||||
// case .importWallet:
|
||||
// return .none
|
||||
|
||||
case .securityWarning:
|
||||
return .none
|
||||
|
||||
case .restoreWalletCoordFlow:
|
||||
return .none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import ImportWallet
|
|||
import SecurityWarning
|
||||
import ZcashLightClientKit
|
||||
import UIComponents
|
||||
import CoordFlows
|
||||
|
||||
public struct PlainOnboardingView: View {
|
||||
@Perception.Bindable var store: StoreOf<OnboardingFlow>
|
||||
|
@ -49,17 +50,17 @@ public struct PlainOnboardingView: View {
|
|||
}
|
||||
.padding(.bottom, 24)
|
||||
}
|
||||
.navigationLinkEmpty(
|
||||
isActive: store.bindingFor(.importExistingWallet),
|
||||
destination: {
|
||||
ImportWalletView(
|
||||
store: store.scope(
|
||||
state: \.importWalletState,
|
||||
action: \.importWallet
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
// .navigationLinkEmpty(
|
||||
// isActive: store.bindingFor(.importExistingWallet),
|
||||
// destination: {
|
||||
// ImportWalletView(
|
||||
// store: store.scope(
|
||||
// state: \.importWalletState,
|
||||
// action: \.importWallet
|
||||
// )
|
||||
// )
|
||||
// }
|
||||
// )
|
||||
.navigationLinkEmpty(
|
||||
isActive: store.bindingFor(.createNewWallet),
|
||||
destination: {
|
||||
|
@ -71,6 +72,17 @@ public struct PlainOnboardingView: View {
|
|||
)
|
||||
}
|
||||
)
|
||||
.navigationLinkEmpty(
|
||||
isActive: store.bindingFor(.importExistingWallet),
|
||||
destination: {
|
||||
RestoreWalletCoordFlowView(
|
||||
store: store.scope(
|
||||
state: \.restoreWalletCoordFlowState,
|
||||
action: \.restoreWalletCoordFlow
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.screenHorizontalPadding()
|
||||
|
@ -84,7 +96,6 @@ public struct PlainOnboardingView: View {
|
|||
Store(
|
||||
initialState: OnboardingFlow.State(
|
||||
walletConfig: .initial,
|
||||
importWalletState: .initial,
|
||||
securityWarningState: .initial
|
||||
)
|
||||
) {
|
||||
|
@ -110,7 +121,6 @@ extension OnboardingFlow.State {
|
|||
public static var initial: Self {
|
||||
.init(
|
||||
walletConfig: .initial,
|
||||
importWalletState: .initial,
|
||||
securityWarningState: .initial
|
||||
)
|
||||
}
|
||||
|
|
|
@ -60,9 +60,10 @@ extension Root {
|
|||
|| (state.destinationState.destination == .deeplinkWarning && destination == .home) else {
|
||||
return .none
|
||||
}
|
||||
guard state.destinationState.destination != .onboarding && state.onboardingState.destination != .importExistingWallet && state.onboardingState.importWalletState.destination != .restoreInfo else {
|
||||
return .none
|
||||
}
|
||||
// RESTORE
|
||||
// guard state.destinationState.destination != .onboarding && state.onboardingState.destination != .importExistingWallet && state.onboardingState.importWalletState.destination != .restoreInfo else {
|
||||
// return .none
|
||||
// }
|
||||
state.destinationState.destination = destination
|
||||
return .none
|
||||
|
||||
|
|
|
@ -555,10 +555,12 @@ extension Root {
|
|||
}
|
||||
if state.appInitializationState == .keysMissing && state.onboardingState.destination == .importExistingWallet {
|
||||
state.appInitializationState = .uninitialized
|
||||
return .concatenate(
|
||||
.cancel(id: SynchronizerCancelId),
|
||||
.send(.onboarding(.importWallet(.updateDestination(.birthday))))
|
||||
)
|
||||
// RESTORE
|
||||
return .cancel(id: SynchronizerCancelId)
|
||||
// return .concatenate(
|
||||
// .cancel(id: SynchronizerCancelId),
|
||||
// .send(.onboarding(.importWallet(.updateDestination(.birthday))))
|
||||
// )
|
||||
} else if state.appInitializationState == .keysMissing && state.onboardingState.destination == .createNewWallet {
|
||||
state.appInitializationState = .uninitialized
|
||||
return .concatenate(
|
||||
|
@ -645,39 +647,43 @@ extension Root {
|
|||
await send(.onboarding(.importExistingWallet))
|
||||
}
|
||||
|
||||
case .onboarding(.importWallet(.nextTapped)):
|
||||
if state.appInitializationState == .keysMissing {
|
||||
let seedPhrase = state.onboardingState.importWalletState.importedSeedPhrase
|
||||
return .run { send in
|
||||
do {
|
||||
let seedBytes = try mnemonic.toSeed(seedPhrase)
|
||||
let result = try await sdkSynchronizer.isSeedRelevantToAnyDerivedAccount(seedBytes)
|
||||
await send(.initialization(.seedValidationResult(result)))
|
||||
} catch {
|
||||
await send(.initialization(.seedValidationResult(false)))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state.onboardingState.importWalletState.destination = .birthday
|
||||
return .none
|
||||
}
|
||||
// RESTORE
|
||||
// case .onboarding(.importWallet(.nextTapped)):
|
||||
// if state.appInitializationState == .keysMissing {
|
||||
// let seedPhrase = state.onboardingState.importWalletState.importedSeedPhrase
|
||||
// return .run { send in
|
||||
// do {
|
||||
// let seedBytes = try mnemonic.toSeed(seedPhrase)
|
||||
// let result = try await sdkSynchronizer.isSeedRelevantToAnyDerivedAccount(seedBytes)
|
||||
// await send(.initialization(.seedValidationResult(result)))
|
||||
// } catch {
|
||||
// await send(.initialization(.seedValidationResult(false)))
|
||||
// }
|
||||
// }
|
||||
// } else {
|
||||
// state.onboardingState.importWalletState.destination = .birthday
|
||||
// return .none
|
||||
// }
|
||||
|
||||
case .onboarding(.importWallet(.restoreInfo(.gotItTapped))):
|
||||
state.destinationState.destination = .home
|
||||
return .none
|
||||
// RESTORE
|
||||
// case .onboarding(.importWallet(.restoreInfo(.gotItTapped))):
|
||||
// state.destinationState.destination = .home
|
||||
// return .none
|
||||
|
||||
case .onboarding(.importWallet(.initializeSDK)):
|
||||
state.isRestoringWallet = true
|
||||
userDefaults.setValue(true, Constants.udIsRestoringWallet)
|
||||
state.$walletStatus.withLock { $0 = .restoring }
|
||||
return .concatenate(
|
||||
.send(.initialization(.initializeSDK(.restoreWallet))),
|
||||
.send(.initialization(.checkBackupPhraseValidation))
|
||||
)
|
||||
// RESTORE
|
||||
// case .onboarding(.importWallet(.initializeSDK)):
|
||||
// state.isRestoringWallet = true
|
||||
// userDefaults.setValue(true, Constants.udIsRestoringWallet)
|
||||
// state.$walletStatus.withLock { $0 = .restoring }
|
||||
// return .concatenate(
|
||||
// .send(.initialization(.initializeSDK(.restoreWallet))),
|
||||
// .send(.initialization(.checkBackupPhraseValidation))
|
||||
// )
|
||||
|
||||
case .initialization(.seedValidationResult(let validSeed)):
|
||||
if validSeed {
|
||||
state.onboardingState.importWalletState.destination = .birthday
|
||||
// RESTORE
|
||||
// state.onboardingState.importWalletState.destination = .birthday
|
||||
} else {
|
||||
state.alert = AlertState.differentSeed()
|
||||
}
|
||||
|
|
|
@ -131,8 +131,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/zcash-hackworks/MnemonicSwift",
|
||||
"state" : {
|
||||
"revision" : "716a2c32ac2bbd8a1499ac834077df42b75edc85",
|
||||
"version" : "2.2.4"
|
||||
"revision" : "2d7f3e76e904621e111efada6cc9575f39543bb2",
|
||||
"version" : "2.2.5"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue