- previous profile screen connected to the receive ZEC button - receive ZEC is now simplified to show only QR code + UA with small "i" icon leading to address details - profile's UA address copy to pasteboard added - home's settings button connected to settings screen - settings screen updated, test crash report and rescan blockchain moved to debug menu - root reducer's debug code move to a separate file - unit tests updated + debug tests provided
This commit is contained in:
parent
f1c9b06123
commit
49d858d22a
|
@ -447,6 +447,9 @@
|
||||||
9E7FE0F628327F6F00C374E8 /* ScanUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0F528327F6F00C374E8 /* ScanUIView.swift */; };
|
9E7FE0F628327F6F00C374E8 /* ScanUIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0F528327F6F00C374E8 /* ScanUIView.swift */; };
|
||||||
9E7FE0F92832824C00C374E8 /* QRCodeScanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0F82832824C00C374E8 /* QRCodeScanView.swift */; };
|
9E7FE0F92832824C00C374E8 /* QRCodeScanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7FE0F82832824C00C374E8 /* QRCodeScanView.swift */; };
|
||||||
9E852D5C29AF8EB200CF4AC1 /* RecoveryPhraseValidationFlowFeatureFlagTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E852D5B29AF8EB200CF4AC1 /* RecoveryPhraseValidationFlowFeatureFlagTests.swift */; };
|
9E852D5C29AF8EB200CF4AC1 /* RecoveryPhraseValidationFlowFeatureFlagTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E852D5B29AF8EB200CF4AC1 /* RecoveryPhraseValidationFlowFeatureFlagTests.swift */; };
|
||||||
|
9E852D6129B098F400CF4AC1 /* RootDebug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E852D6029B098F400CF4AC1 /* RootDebug.swift */; };
|
||||||
|
9E852D6229B098F400CF4AC1 /* RootDebug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E852D6029B098F400CF4AC1 /* RootDebug.swift */; };
|
||||||
|
9E852D6529B0A86300CF4AC1 /* DebugTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E852D6429B0A86300CF4AC1 /* DebugTests.swift */; };
|
||||||
9E92AF0828530EBF007367AD /* View+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E92AF0728530EBF007367AD /* View+UIImage.swift */; };
|
9E92AF0828530EBF007367AD /* View+UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E92AF0728530EBF007367AD /* View+UIImage.swift */; };
|
||||||
9E94C62028AA7DEE008256E9 /* BalanceBreakdownTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E94C61F28AA7DEE008256E9 /* BalanceBreakdownTests.swift */; };
|
9E94C62028AA7DEE008256E9 /* BalanceBreakdownTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E94C61F28AA7DEE008256E9 /* BalanceBreakdownTests.swift */; };
|
||||||
9E94C62328AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E94C62228AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift */; };
|
9E94C62328AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E94C62228AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift */; };
|
||||||
|
@ -770,6 +773,8 @@
|
||||||
9E7FE0F528327F6F00C374E8 /* ScanUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanUIView.swift; sourceTree = "<group>"; };
|
9E7FE0F528327F6F00C374E8 /* ScanUIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScanUIView.swift; sourceTree = "<group>"; };
|
||||||
9E7FE0F82832824C00C374E8 /* QRCodeScanView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScanView.swift; sourceTree = "<group>"; };
|
9E7FE0F82832824C00C374E8 /* QRCodeScanView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRCodeScanView.swift; sourceTree = "<group>"; };
|
||||||
9E852D5B29AF8EB200CF4AC1 /* RecoveryPhraseValidationFlowFeatureFlagTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecoveryPhraseValidationFlowFeatureFlagTests.swift; sourceTree = "<group>"; };
|
9E852D5B29AF8EB200CF4AC1 /* RecoveryPhraseValidationFlowFeatureFlagTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecoveryPhraseValidationFlowFeatureFlagTests.swift; sourceTree = "<group>"; };
|
||||||
|
9E852D6029B098F400CF4AC1 /* RootDebug.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootDebug.swift; sourceTree = "<group>"; };
|
||||||
|
9E852D6429B0A86300CF4AC1 /* DebugTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugTests.swift; sourceTree = "<group>"; };
|
||||||
9E92AF0728530EBF007367AD /* View+UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+UIImage.swift"; sourceTree = "<group>"; };
|
9E92AF0728530EBF007367AD /* View+UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+UIImage.swift"; sourceTree = "<group>"; };
|
||||||
9E94C61F28AA7DEE008256E9 /* BalanceBreakdownTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceBreakdownTests.swift; sourceTree = "<group>"; };
|
9E94C61F28AA7DEE008256E9 /* BalanceBreakdownTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceBreakdownTests.swift; sourceTree = "<group>"; };
|
||||||
9E94C62228AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceBreakdownSnapshotTests.swift; sourceTree = "<group>"; };
|
9E94C62228AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BalanceBreakdownSnapshotTests.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1852,6 +1857,7 @@
|
||||||
children = (
|
children = (
|
||||||
9EAFEB812805793200199FC9 /* RootTests.swift */,
|
9EAFEB812805793200199FC9 /* RootTests.swift */,
|
||||||
9E391131284644580073DD9A /* AppInitializationTests.swift */,
|
9E391131284644580073DD9A /* AppInitializationTests.swift */,
|
||||||
|
9E852D6429B0A86300CF4AC1 /* DebugTests.swift */,
|
||||||
);
|
);
|
||||||
path = RootTests;
|
path = RootTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -2104,6 +2110,7 @@
|
||||||
F9971A4C27680DC400A2DB75 /* RootView.swift */,
|
F9971A4C27680DC400A2DB75 /* RootView.swift */,
|
||||||
9E9ADA7E2938F5EC0071767B /* RootDestination.swift */,
|
9E9ADA7E2938F5EC0071767B /* RootDestination.swift */,
|
||||||
9E9ADA7C2938F4C00071767B /* RootInitialization.swift */,
|
9E9ADA7C2938F4C00071767B /* RootInitialization.swift */,
|
||||||
|
9E852D6029B098F400CF4AC1 /* RootDebug.swift */,
|
||||||
);
|
);
|
||||||
path = Root;
|
path = Root;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -2686,6 +2693,7 @@
|
||||||
0D26AF01299E8196005260EE /* RecoveryPhraseDisplayView.swift in Sources */,
|
0D26AF01299E8196005260EE /* RecoveryPhraseDisplayView.swift in Sources */,
|
||||||
0D26AF02299E8196005260EE /* URIParser.swift in Sources */,
|
0D26AF02299E8196005260EE /* URIParser.swift in Sources */,
|
||||||
0D26AF03299E8196005260EE /* URIParserLive.swift in Sources */,
|
0D26AF03299E8196005260EE /* URIParserLive.swift in Sources */,
|
||||||
|
9E852D6229B098F400CF4AC1 /* RootDebug.swift in Sources */,
|
||||||
34F682ED29A763FD0022C079 /* WalletConfigProvider.swift in Sources */,
|
34F682ED29A763FD0022C079 /* WalletConfigProvider.swift in Sources */,
|
||||||
0D26AF04299E8196005260EE /* LocalAuthenticationTestKey.swift in Sources */,
|
0D26AF04299E8196005260EE /* LocalAuthenticationTestKey.swift in Sources */,
|
||||||
0D26AF05299E8196005260EE /* ScanView.swift in Sources */,
|
0D26AF05299E8196005260EE /* ScanView.swift in Sources */,
|
||||||
|
@ -2915,6 +2923,7 @@
|
||||||
0D3D04082728B3440032ABC1 /* RecoveryPhraseDisplayView.swift in Sources */,
|
0D3D04082728B3440032ABC1 /* RecoveryPhraseDisplayView.swift in Sources */,
|
||||||
9EB863A2292398A8003D0F8B /* URIParser.swift in Sources */,
|
9EB863A2292398A8003D0F8B /* URIParser.swift in Sources */,
|
||||||
9EB863C12923C779003D0F8B /* URIParserLive.swift in Sources */,
|
9EB863C12923C779003D0F8B /* URIParserLive.swift in Sources */,
|
||||||
|
9E852D6129B098F400CF4AC1 /* RootDebug.swift in Sources */,
|
||||||
34F682EC29A763FD0022C079 /* WalletConfigProvider.swift in Sources */,
|
34F682EC29A763FD0022C079 /* WalletConfigProvider.swift in Sources */,
|
||||||
9EBDF987291F91EF000A1A05 /* LocalAuthenticationTestKey.swift in Sources */,
|
9EBDF987291F91EF000A1A05 /* LocalAuthenticationTestKey.swift in Sources */,
|
||||||
F9971A5F27680DF600A2DB75 /* ScanView.swift in Sources */,
|
F9971A5F27680DF600A2DB75 /* ScanView.swift in Sources */,
|
||||||
|
@ -3053,6 +3062,7 @@
|
||||||
9EAFEB862805A23100199FC9 /* SecItemClientTests.swift in Sources */,
|
9EAFEB862805A23100199FC9 /* SecItemClientTests.swift in Sources */,
|
||||||
3448CB3728E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift in Sources */,
|
3448CB3728E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift in Sources */,
|
||||||
9E9ECC9828589E150099D5A2 /* WelcomeSnapshotTests.swift in Sources */,
|
9E9ECC9828589E150099D5A2 /* WelcomeSnapshotTests.swift in Sources */,
|
||||||
|
9E852D6529B0A86300CF4AC1 /* DebugTests.swift in Sources */,
|
||||||
9E7CB6122869882D00A02233 /* WalletEventsSnapshotTests.swift in Sources */,
|
9E7CB6122869882D00A02233 /* WalletEventsSnapshotTests.swift in Sources */,
|
||||||
9E5BF644281FEC9900BA3F17 /* SendTests.swift in Sources */,
|
9E5BF644281FEC9900BA3F17 /* SendTests.swift in Sources */,
|
||||||
9E852D5C29AF8EB200CF4AC1 /* RecoveryPhraseValidationFlowFeatureFlagTests.swift in Sources */,
|
9E852D5C29AF8EB200CF4AC1 /* RecoveryPhraseValidationFlowFeatureFlagTests.swift in Sources */,
|
||||||
|
|
|
@ -4,9 +4,11 @@
|
||||||
//
|
//
|
||||||
// Created by Francisco Gindre on 2/2/23.
|
// Created by Francisco Gindre on 2/2/23.
|
||||||
//
|
//
|
||||||
|
|
||||||
import ComposableArchitecture
|
import ComposableArchitecture
|
||||||
import FirebaseCore
|
import FirebaseCore
|
||||||
import FirebaseCrashlytics
|
import FirebaseCrashlytics
|
||||||
|
|
||||||
extension CrashReporterClient: DependencyKey {
|
extension CrashReporterClient: DependencyKey {
|
||||||
static let liveValue = CrashReporterClient(
|
static let liveValue = CrashReporterClient(
|
||||||
configure: { canConfigure in
|
configure: { canConfigure in
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
import ComposableArchitecture
|
import ComposableArchitecture
|
||||||
|
|
||||||
extension CrashReporterClient: TestDependencyKey {
|
extension CrashReporterClient: TestDependencyKey {
|
||||||
static let testValue = CrashReporterClient(
|
static let testValue = CrashReporterClient(
|
||||||
configure: { _ in },
|
configure: { _ in },
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
//
|
//
|
||||||
// Created by Francisco Gindre on 2/2/23.
|
// Created by Francisco Gindre on 2/2/23.
|
||||||
//
|
//
|
||||||
|
|
||||||
import ComposableArchitecture
|
import ComposableArchitecture
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
|
|
|
@ -16,8 +16,8 @@ struct HomeReducer: ReducerProtocol {
|
||||||
case balanceBreakdown
|
case balanceBreakdown
|
||||||
case notEnoughFreeDiskSpace
|
case notEnoughFreeDiskSpace
|
||||||
case profile
|
case profile
|
||||||
case request
|
|
||||||
case send
|
case send
|
||||||
|
case settings
|
||||||
case transactionHistory
|
case transactionHistory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,10 +25,10 @@ struct HomeReducer: ReducerProtocol {
|
||||||
var balanceBreakdownState: BalanceBreakdownReducer.State
|
var balanceBreakdownState: BalanceBreakdownReducer.State
|
||||||
var destination: Destination?
|
var destination: Destination?
|
||||||
var profileState: ProfileReducer.State
|
var profileState: ProfileReducer.State
|
||||||
var requestState: RequestReducer.State
|
|
||||||
var requiredTransactionConfirmations = 0
|
var requiredTransactionConfirmations = 0
|
||||||
var scanState: ScanReducer.State
|
var scanState: ScanReducer.State
|
||||||
var sendState: SendFlowReducer.State
|
var sendState: SendFlowReducer.State
|
||||||
|
var settingsState: SettingsReducer.State
|
||||||
var shieldedBalance: Balance
|
var shieldedBalance: Balance
|
||||||
var synchronizerStatusSnapshot: SyncStatusSnapshot
|
var synchronizerStatusSnapshot: SyncStatusSnapshot
|
||||||
var walletEventsState: WalletEventsFlowReducer.State
|
var walletEventsState: WalletEventsFlowReducer.State
|
||||||
|
@ -61,9 +61,8 @@ struct HomeReducer: ReducerProtocol {
|
||||||
case onAppear
|
case onAppear
|
||||||
case onDisappear
|
case onDisappear
|
||||||
case profile(ProfileReducer.Action)
|
case profile(ProfileReducer.Action)
|
||||||
case request(RequestReducer.Action)
|
|
||||||
case rewindDone(String?, SettingsReducer.Action)
|
|
||||||
case send(SendFlowReducer.Action)
|
case send(SendFlowReducer.Action)
|
||||||
|
case settings(SettingsReducer.Action)
|
||||||
case synchronizerStateChanged(SDKSynchronizerState)
|
case synchronizerStateChanged(SDKSynchronizerState)
|
||||||
case walletEvents(WalletEventsFlowReducer.Action)
|
case walletEvents(WalletEventsFlowReducer.Action)
|
||||||
case updateDestination(HomeReducer.State.Destination?)
|
case updateDestination(HomeReducer.State.Destination?)
|
||||||
|
@ -86,6 +85,10 @@ struct HomeReducer: ReducerProtocol {
|
||||||
SendFlowReducer()
|
SendFlowReducer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Scope(state: \.settingsState, action: /Action.settings) {
|
||||||
|
SettingsReducer()
|
||||||
|
}
|
||||||
|
|
||||||
Scope(state: \.profileState, action: /Action.profile) {
|
Scope(state: \.profileState, action: /Action.profile) {
|
||||||
ProfileReducer()
|
ProfileReducer()
|
||||||
}
|
}
|
||||||
|
@ -138,45 +141,12 @@ struct HomeReducer: ReducerProtocol {
|
||||||
state.destination = nil
|
state.destination = nil
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .profile(.settings(.quickRescan)):
|
case .settings:
|
||||||
state.destination = nil
|
return .none
|
||||||
return .run { send in
|
|
||||||
do {
|
|
||||||
try await sdkSynchronizer.rewind(.quick)
|
|
||||||
await send(.rewindDone(nil, .quickRescan))
|
|
||||||
} catch {
|
|
||||||
await send(.rewindDone(error.localizedDescription, .quickRescan))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case .profile(.settings(.fullRescan)):
|
|
||||||
state.destination = nil
|
|
||||||
return .run { send in
|
|
||||||
do {
|
|
||||||
try await sdkSynchronizer.rewind(.birthday)
|
|
||||||
await send(.rewindDone(nil, .fullRescan))
|
|
||||||
} catch {
|
|
||||||
await send(.rewindDone(error.localizedDescription, .fullRescan))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case .profile:
|
case .profile:
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .request:
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case let .rewindDone(errorDescription, _):
|
|
||||||
if let errorDescription {
|
|
||||||
// TODO: [#221] Handle error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
|
|
||||||
state.alert = AlertState(
|
|
||||||
title: TextState("Rewind failed"),
|
|
||||||
message: TextState("Error: \(errorDescription)"),
|
|
||||||
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .walletEvents:
|
case .walletEvents:
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
@ -221,13 +191,6 @@ extension HomeStore {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func requestStore() -> RequestStore {
|
|
||||||
self.scope(
|
|
||||||
state: \.requestState,
|
|
||||||
action: HomeReducer.Action.request
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendStore() -> SendFlowStore {
|
func sendStore() -> SendFlowStore {
|
||||||
self.scope(
|
self.scope(
|
||||||
state: \.sendState,
|
state: \.sendState,
|
||||||
|
@ -235,6 +198,13 @@ extension HomeStore {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func settingsStore() -> SettingsStore {
|
||||||
|
self.scope(
|
||||||
|
state: \.settingsState,
|
||||||
|
action: HomeReducer.Action.settings
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func balanceBreakdownStore() -> BalanceBreakdownStore {
|
func balanceBreakdownStore() -> BalanceBreakdownStore {
|
||||||
self.scope(
|
self.scope(
|
||||||
state: \.balanceBreakdownState,
|
state: \.balanceBreakdownState,
|
||||||
|
@ -263,9 +233,9 @@ extension HomeReducer.State {
|
||||||
.init(
|
.init(
|
||||||
balanceBreakdownState: .placeholder,
|
balanceBreakdownState: .placeholder,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
sendState: .placeholder,
|
sendState: .placeholder,
|
||||||
|
settingsState: .placeholder,
|
||||||
shieldedBalance: Balance.zero,
|
shieldedBalance: Balance.zero,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
walletEventsState: .emptyPlaceHolder
|
walletEventsState: .emptyPlaceHolder
|
||||||
|
|
|
@ -8,9 +8,9 @@ struct HomeView: View {
|
||||||
WithViewStore(store) { viewStore in
|
WithViewStore(store) { viewStore in
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
profileButton(viewStore)
|
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
|
||||||
|
settingsButton(viewStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
balance(viewStore)
|
balance(viewStore)
|
||||||
|
@ -19,6 +19,8 @@ struct HomeView: View {
|
||||||
|
|
||||||
sendButton(viewStore)
|
sendButton(viewStore)
|
||||||
|
|
||||||
|
receiveButton(viewStore)
|
||||||
|
|
||||||
Button {
|
Button {
|
||||||
viewStore.send(.updateDestination(.transactionHistory))
|
viewStore.send(.updateDestination(.transactionHistory))
|
||||||
} label: {
|
} label: {
|
||||||
|
@ -48,21 +50,21 @@ struct HomeView: View {
|
||||||
// MARK: - Buttons
|
// MARK: - Buttons
|
||||||
|
|
||||||
extension HomeView {
|
extension HomeView {
|
||||||
func profileButton(_ viewStore: HomeViewStore) -> some View {
|
func settingsButton(_ viewStore: HomeViewStore) -> some View {
|
||||||
Image(Asset.Assets.Icons.profile.name)
|
Image(Asset.Assets.Icons.profile.name)
|
||||||
.resizable()
|
.resizable()
|
||||||
.frame(width: 60, height: 60)
|
.frame(width: 60, height: 60)
|
||||||
.padding(.trailing, 15)
|
.padding(.trailing, 15)
|
||||||
.navigationLink(
|
.navigationLink(
|
||||||
isActive: viewStore.bindingForDestination(.profile),
|
isActive: viewStore.bindingForDestination(.settings),
|
||||||
destination: {
|
destination: {
|
||||||
ProfileView(store: store.profileStore())
|
SettingsView(store: store.settingsStore())
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendButton(_ viewStore: HomeViewStore) -> some View {
|
func sendButton(_ viewStore: HomeViewStore) -> some View {
|
||||||
Text("Send")
|
Text("Send ZEC")
|
||||||
.shadow(color: Asset.Colors.Buttons.buttonsTitleShadow.color, radius: 2, x: 0, y: 2)
|
.shadow(color: Asset.Colors.Buttons.buttonsTitleShadow.color, radius: 2, x: 0, y: 2)
|
||||||
.frame(
|
.frame(
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
|
@ -85,6 +87,30 @@ extension HomeView {
|
||||||
.padding(.bottom, 30)
|
.padding(.bottom, 30)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func receiveButton(_ viewStore: HomeViewStore) -> some View {
|
||||||
|
Text("Receive ZEC")
|
||||||
|
.shadow(color: Asset.Colors.Buttons.buttonsTitleShadow.color, radius: 2, x: 0, y: 2)
|
||||||
|
.frame(
|
||||||
|
minWidth: 0,
|
||||||
|
maxWidth: .infinity,
|
||||||
|
minHeight: 0,
|
||||||
|
maxHeight: .infinity
|
||||||
|
)
|
||||||
|
.foregroundColor(Asset.Colors.Text.activeButtonText.color)
|
||||||
|
.background(Asset.Colors.Buttons.activeButton.color)
|
||||||
|
.cornerRadius(12)
|
||||||
|
.frame(height: 60)
|
||||||
|
.padding(.horizontal, 50)
|
||||||
|
.neumorphicButton()
|
||||||
|
.navigationLink(
|
||||||
|
isActive: viewStore.bindingForDestination(.profile),
|
||||||
|
destination: {
|
||||||
|
ProfileView(store: store.profileStore())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.padding(.bottom, 30)
|
||||||
|
}
|
||||||
|
|
||||||
func balance(_ viewStore: HomeViewStore) -> some View {
|
func balance(_ viewStore: HomeViewStore) -> some View {
|
||||||
Group {
|
Group {
|
||||||
Button {
|
Button {
|
||||||
|
|
|
@ -9,7 +9,6 @@ struct ProfileReducer: ReducerProtocol {
|
||||||
struct State: Equatable {
|
struct State: Equatable {
|
||||||
enum Destination {
|
enum Destination {
|
||||||
case addressDetails
|
case addressDetails
|
||||||
case settings
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var addressDetailsState: AddressDetailsReducer.State
|
var addressDetailsState: AddressDetailsReducer.State
|
||||||
|
@ -17,7 +16,6 @@ struct ProfileReducer: ReducerProtocol {
|
||||||
var appVersion = ""
|
var appVersion = ""
|
||||||
var destination: Destination?
|
var destination: Destination?
|
||||||
var sdkVersion = ""
|
var sdkVersion = ""
|
||||||
var settingsState: SettingsReducer.State
|
|
||||||
|
|
||||||
var unifiedAddress: String {
|
var unifiedAddress: String {
|
||||||
addressDetailsState.uAddress?.stringEncoded ?? "could not extract UA"
|
addressDetailsState.uAddress?.stringEncoded ?? "could not extract UA"
|
||||||
|
@ -27,12 +25,13 @@ struct ProfileReducer: ReducerProtocol {
|
||||||
enum Action: Equatable {
|
enum Action: Equatable {
|
||||||
case addressDetails(AddressDetailsReducer.Action)
|
case addressDetails(AddressDetailsReducer.Action)
|
||||||
case back
|
case back
|
||||||
|
case copyUnifiedAddressToPastboard
|
||||||
case onAppear
|
case onAppear
|
||||||
case settings(SettingsReducer.Action)
|
|
||||||
case updateDestination(ProfileReducer.State.Destination?)
|
case updateDestination(ProfileReducer.State.Destination?)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Dependency(\.appVersion) var appVersion
|
@Dependency(\.appVersion) var appVersion
|
||||||
|
@Dependency(\.pasteboard) var pasteboard
|
||||||
@Dependency(\.sdkSynchronizer) var sdkSynchronizer
|
@Dependency(\.sdkSynchronizer) var sdkSynchronizer
|
||||||
@Dependency(\.zcashSDKEnvironment) var zcashSDKEnvironment
|
@Dependency(\.zcashSDKEnvironment) var zcashSDKEnvironment
|
||||||
|
|
||||||
|
@ -41,10 +40,6 @@ struct ProfileReducer: ReducerProtocol {
|
||||||
AddressDetailsReducer()
|
AddressDetailsReducer()
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope(state: \.settingsState, action: /Action.settings) {
|
|
||||||
SettingsReducer()
|
|
||||||
}
|
|
||||||
|
|
||||||
Reduce { state, action in
|
Reduce { state, action in
|
||||||
switch action {
|
switch action {
|
||||||
case .onAppear:
|
case .onAppear:
|
||||||
|
@ -57,15 +52,16 @@ struct ProfileReducer: ReducerProtocol {
|
||||||
case .back:
|
case .back:
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
case .copyUnifiedAddressToPastboard:
|
||||||
|
pasteboard.setString(state.unifiedAddress.redacted)
|
||||||
|
return .none
|
||||||
|
|
||||||
case let .updateDestination(destination):
|
case let .updateDestination(destination):
|
||||||
state.destination = destination
|
state.destination = destination
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .addressDetails:
|
case .addressDetails:
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .settings:
|
|
||||||
return .none
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,13 +76,6 @@ extension ProfileStore {
|
||||||
action: ProfileReducer.Action.addressDetails
|
action: ProfileReducer.Action.addressDetails
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func settingsStore() -> SettingsStore {
|
|
||||||
self.scope(
|
|
||||||
state: \.settingsState,
|
|
||||||
action: ProfileReducer.Action.settings
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - ViewStore
|
// MARK: - ViewStore
|
||||||
|
@ -105,13 +94,6 @@ extension ProfileViewStore {
|
||||||
embed: { $0 ? .addressDetails : nil }
|
embed: { $0 ? .addressDetails : nil }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
var bindingForSettings: Binding<Bool> {
|
|
||||||
self.destinationBinding.map(
|
|
||||||
extract: { $0 == .settings },
|
|
||||||
embed: { $0 ? .settings : nil }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Placeholders
|
// MARK: - Placeholders
|
||||||
|
@ -120,8 +102,7 @@ extension ProfileReducer.State {
|
||||||
static var placeholder: Self {
|
static var placeholder: Self {
|
||||||
.init(
|
.init(
|
||||||
addressDetailsState: .placeholder,
|
addressDetailsState: .placeholder,
|
||||||
destination: nil,
|
destination: nil
|
||||||
settingsState: .placeholder
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,62 +6,32 @@ struct ProfileView: View {
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
WithViewStore(store) { viewStore in
|
WithViewStore(store) { viewStore in
|
||||||
ScrollView {
|
VStack {
|
||||||
qrCodeUA(viewStore.unifiedAddress)
|
qrCodeUA(viewStore.unifiedAddress)
|
||||||
.padding(.top, 30)
|
.padding(.vertical, 50)
|
||||||
|
|
||||||
Text("Your UA address \(viewStore.unifiedAddress)")
|
|
||||||
.truncationMode(.middle)
|
|
||||||
.multilineTextAlignment(.center)
|
|
||||||
.lineLimit(2)
|
|
||||||
.padding(30)
|
|
||||||
|
|
||||||
Button(
|
|
||||||
action: { viewStore.send(.updateDestination(.addressDetails)) },
|
|
||||||
label: { Text("See address details") }
|
|
||||||
)
|
|
||||||
.activeButtonStyle
|
|
||||||
.frame(height: 50)
|
|
||||||
.padding(EdgeInsets(top: 0, leading: 30, bottom: 50, trailing: 30))
|
|
||||||
|
|
||||||
Rectangle()
|
|
||||||
.frame(height: 1.5)
|
|
||||||
.padding(EdgeInsets(top: 0, leading: 100, bottom: 20, trailing: 100))
|
|
||||||
.foregroundColor(Asset.Colors.TextField.Underline.purple.color)
|
|
||||||
|
|
||||||
Button(
|
|
||||||
action: { viewStore.send(.updateDestination(.settings)) },
|
|
||||||
label: { Text("Settings") }
|
|
||||||
)
|
|
||||||
.primaryButtonStyle
|
|
||||||
.frame(height: 50)
|
|
||||||
.padding(EdgeInsets(top: 30, leading: 30, bottom: 20, trailing: 30))
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
|
|
||||||
HStack {
|
HStack {
|
||||||
VStack {
|
Text("Your UA")
|
||||||
Text("secant v\(viewStore.appVersion)(\(viewStore.appBuild))")
|
.fontWeight(.bold)
|
||||||
Text("sdk v\(viewStore.sdkVersion)")
|
.onTapGesture {
|
||||||
}
|
viewStore.send(.copyUnifiedAddressToPastboard)
|
||||||
Spacer()
|
|
||||||
Button(
|
|
||||||
action: { },
|
|
||||||
label: {
|
|
||||||
Text("More info")
|
|
||||||
.foregroundColor(Asset.Colors.Text.moreInfoText.color)
|
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
Button {
|
||||||
|
viewStore.send(.updateDestination(.addressDetails))
|
||||||
|
} label: {
|
||||||
|
Image(systemName: "info.circle")
|
||||||
|
.offset(x: -10, y: -10)
|
||||||
|
.tint(.black)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.padding(30)
|
|
||||||
|
Text("\(viewStore.unifiedAddress)")
|
||||||
|
.padding(30)
|
||||||
|
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
.onAppear(perform: { viewStore.send(.onAppear) })
|
.onAppear(perform: { viewStore.send(.onAppear) })
|
||||||
.navigationLinkEmpty(
|
|
||||||
isActive: viewStore.bindingForSettings,
|
|
||||||
destination: {
|
|
||||||
SettingsView(store: store.settingsStore())
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.navigationLinkEmpty(
|
.navigationLinkEmpty(
|
||||||
isActive: viewStore.bindingForAddressDetails,
|
isActive: viewStore.bindingForAddressDetails,
|
||||||
destination: {
|
destination: {
|
||||||
|
@ -104,14 +74,11 @@ struct ProfileView_Previews: PreviewProvider {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
ProfileView(
|
ProfileView(
|
||||||
store: .init(
|
store: .init(
|
||||||
initialState: .init(
|
initialState: .init(addressDetailsState: .placeholder),
|
||||||
addressDetailsState: .placeholder,
|
|
||||||
settingsState: .placeholder
|
|
||||||
),
|
|
||||||
reducer: ProfileReducer()
|
reducer: ProfileReducer()
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.preferredColorScheme(.dark)
|
.preferredColorScheme(.light)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
//
|
||||||
|
// RootDebug.swift
|
||||||
|
// secant
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 02.03.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import ComposableArchitecture
|
||||||
|
import ZcashLightClientKit
|
||||||
|
|
||||||
|
/// In this file is a collection of helpers that control all state and action related operations
|
||||||
|
/// for the `RootReducer` with a connection to the UI navigation.
|
||||||
|
extension RootReducer {
|
||||||
|
struct DebugState: Equatable {
|
||||||
|
var rescanDialog: ConfirmationDialogState<RootReducer.Action>?
|
||||||
|
}
|
||||||
|
|
||||||
|
indirect enum DebugAction: Equatable {
|
||||||
|
case cancelRescan
|
||||||
|
case flagUpdated
|
||||||
|
case fullRescan
|
||||||
|
case quickRescan
|
||||||
|
case rescanBlockchain
|
||||||
|
case rewindDone(String?, RootReducer.Action)
|
||||||
|
case testCrashReporter // this will crash the app if live.
|
||||||
|
case updateFlag(FeatureFlag, Bool)
|
||||||
|
case walletConfigLoaded(WalletConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
// swiftlint:disable:next cyclomatic_complexity
|
||||||
|
func debugReduce() -> Reduce<RootReducer.State, RootReducer.Action> {
|
||||||
|
Reduce { state, action in
|
||||||
|
switch action {
|
||||||
|
case .debug(.testCrashReporter):
|
||||||
|
crashReporter.testCrash()
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case .debug(.rescanBlockchain):
|
||||||
|
state.debugState.rescanDialog = .init(
|
||||||
|
title: TextState("Rescan"),
|
||||||
|
message: TextState("Select the rescan you want"),
|
||||||
|
buttons: [
|
||||||
|
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
|
||||||
|
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
|
||||||
|
.cancel(TextState("Cancel"))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case .debug(.cancelRescan):
|
||||||
|
state.debugState.rescanDialog = nil
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case .debug(.quickRescan):
|
||||||
|
state.destinationState.destination = .home
|
||||||
|
return .run { send in
|
||||||
|
do {
|
||||||
|
try await sdkSynchronizer.rewind(.quick)
|
||||||
|
await send(.debug(.rewindDone(nil, .debug(.quickRescan))))
|
||||||
|
} catch {
|
||||||
|
await send(.debug(.rewindDone(error.localizedDescription, .debug(.quickRescan))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case .debug(.fullRescan):
|
||||||
|
state.destinationState.destination = .home
|
||||||
|
return .run { send in
|
||||||
|
do {
|
||||||
|
try await sdkSynchronizer.rewind(.birthday)
|
||||||
|
await send(.debug(.rewindDone(nil, .debug(.fullRescan))))
|
||||||
|
} catch {
|
||||||
|
await send(.debug(.rewindDone(error.localizedDescription, .debug(.fullRescan))))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case let .debug(.rewindDone(errorDescription, _)):
|
||||||
|
if let errorDescription {
|
||||||
|
// TODO: [#221] Handle error more properly (https://github.com/zcash/secant-ios-wallet/issues/221)
|
||||||
|
state.alert = AlertState(
|
||||||
|
title: TextState("Rewind failed"),
|
||||||
|
message: TextState("Error: \(errorDescription)"),
|
||||||
|
dismissButton: .default(TextState("Ok"), action: .send(.dismissAlert))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return .none
|
||||||
|
|
||||||
|
case let .debug(.updateFlag(flag, isEnabled)):
|
||||||
|
return walletConfigProvider.update(flag, !isEnabled)
|
||||||
|
.receive(on: mainQueue)
|
||||||
|
.map { _ in return Action.debug(.flagUpdated) }
|
||||||
|
.eraseToEffect()
|
||||||
|
.cancellable(id: WalletConfigCancelId.self, cancelInFlight: true)
|
||||||
|
|
||||||
|
case .debug(.flagUpdated):
|
||||||
|
return walletConfigProvider.load()
|
||||||
|
.receive(on: mainQueue)
|
||||||
|
.map { Action.debug(.walletConfigLoaded($0)) }
|
||||||
|
.eraseToEffect()
|
||||||
|
.cancellable(id: WalletConfigCancelId.self, cancelInFlight: true)
|
||||||
|
|
||||||
|
case let .debug(.walletConfigLoaded(walletConfig)):
|
||||||
|
return EffectTask(value: .updateStateAfterConfigUpdate(walletConfig))
|
||||||
|
|
||||||
|
default: return .none
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: Placeholders
|
||||||
|
|
||||||
|
extension RootReducer.DebugState {
|
||||||
|
static var placeholder: Self {
|
||||||
|
.init()
|
||||||
|
}
|
||||||
|
}
|
|
@ -134,8 +134,8 @@ extension RootReducer {
|
||||||
state.destinationState.alert = nil
|
state.destinationState.alert = nil
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .home, .initialization, .onboarding, .phraseDisplay, .phraseValidation,
|
case .home, .initialization, .onboarding, .phraseDisplay, .phraseValidation, .sandbox, .updateStateAfterConfigUpdate,
|
||||||
.sandbox, .welcome, .binding, .nukeWalletFailed, .nukeWalletSucceeded, .debug, .walletConfigLoaded, .dismissAlert:
|
.welcome, .binding, .nukeWalletFailed, .nukeWalletSucceeded, .debug, .walletConfigLoaded, .dismissAlert:
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,6 @@ extension RootReducer {
|
||||||
case walletConfigChanged(WalletConfig)
|
case walletConfigChanged(WalletConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum DebugAction: Equatable {
|
|
||||||
case updateFlag(FeatureFlag, Bool)
|
|
||||||
case flagUpdated
|
|
||||||
case walletConfigLoaded(WalletConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// swiftlint:disable:next cyclomatic_complexity function_body_length
|
// swiftlint:disable:next cyclomatic_complexity function_body_length
|
||||||
func initializationReduce() -> Reduce<RootReducer.State, RootReducer.Action> {
|
func initializationReduce() -> Reduce<RootReducer.State, RootReducer.Action> {
|
||||||
Reduce { state, action in
|
Reduce { state, action in
|
||||||
|
@ -56,8 +50,10 @@ extension RootReducer {
|
||||||
}
|
}
|
||||||
|
|
||||||
case .initialization(.walletConfigChanged(let walletConfig)):
|
case .initialization(.walletConfigChanged(let walletConfig)):
|
||||||
updateStateAfterConfigUpdate(state: &state, config: walletConfig)
|
return .concatenate(
|
||||||
return EffectTask(value: .initialization(.initialSetups))
|
EffectTask(value: .updateStateAfterConfigUpdate(walletConfig)),
|
||||||
|
EffectTask(value: .initialization(.initialSetups))
|
||||||
|
)
|
||||||
|
|
||||||
case .initialization(.initialSetups):
|
case .initialization(.initialSetups):
|
||||||
// TODO: [#524] finish all the wallet events according to definition, https://github.com/zcash/secant-ios-wallet/issues/524
|
// TODO: [#524] finish all the wallet events according to definition, https://github.com/zcash/secant-ios-wallet/issues/524
|
||||||
|
@ -308,42 +304,25 @@ extension RootReducer {
|
||||||
case .onboarding(.createNewWallet):
|
case .onboarding(.createNewWallet):
|
||||||
return EffectTask(value: .initialization(.createNewWallet))
|
return EffectTask(value: .initialization(.createNewWallet))
|
||||||
|
|
||||||
case .home, .destination, .onboarding, .phraseDisplay, .phraseValidation, .sandbox, .welcome, .binding:
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .initialization(.configureCrashReporter):
|
case .initialization(.configureCrashReporter):
|
||||||
crashReporter.configure(
|
crashReporter.configure(
|
||||||
!userStoredPreferences.isUserOptedOutOfCrashReporting()
|
!userStoredPreferences.isUserOptedOutOfCrashReporting()
|
||||||
)
|
)
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
case .updateStateAfterConfigUpdate(let walletConfig):
|
||||||
|
state.walletConfig = walletConfig
|
||||||
|
state.onboardingState.walletConfig = walletConfig
|
||||||
|
return .none
|
||||||
|
|
||||||
case .dismissAlert:
|
case .dismissAlert:
|
||||||
state.alert = nil
|
state.alert = nil
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case let .debug(.updateFlag(flag, isEnabled)):
|
case .home, .destination, .onboarding, .phraseDisplay, .phraseValidation, .sandbox,
|
||||||
return walletConfigProvider.update(flag, !isEnabled)
|
.welcome, .binding, .debug:
|
||||||
.receive(on: mainQueue)
|
|
||||||
.map { _ in return Action.debug(.flagUpdated) }
|
|
||||||
.eraseToEffect()
|
|
||||||
.cancellable(id: WalletConfigCancelId.self, cancelInFlight: true)
|
|
||||||
|
|
||||||
case .debug(.flagUpdated):
|
|
||||||
return walletConfigProvider.load()
|
|
||||||
.receive(on: mainQueue)
|
|
||||||
.map { Action.debug(.walletConfigLoaded($0)) }
|
|
||||||
.eraseToEffect()
|
|
||||||
.cancellable(id: WalletConfigCancelId.self, cancelInFlight: true)
|
|
||||||
|
|
||||||
case let .debug(.walletConfigLoaded(walletConfig)):
|
|
||||||
updateStateAfterConfigUpdate(state: &state, config: walletConfig)
|
|
||||||
return .none
|
return .none
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func updateStateAfterConfigUpdate(state: inout RootReducer.State, config: WalletConfig) {
|
|
||||||
state.walletConfig = config
|
|
||||||
state.onboardingState.walletConfig = config
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ struct RootReducer: ReducerProtocol {
|
||||||
struct State: Equatable {
|
struct State: Equatable {
|
||||||
@BindingState var alert: AlertState<RootReducer.Action>?
|
@BindingState var alert: AlertState<RootReducer.Action>?
|
||||||
var appInitializationState: InitializationState = .uninitialized
|
var appInitializationState: InitializationState = .uninitialized
|
||||||
|
var debugState: DebugState
|
||||||
var destinationState: DestinationState
|
var destinationState: DestinationState
|
||||||
var homeState: HomeReducer.State
|
var homeState: HomeReducer.State
|
||||||
var onboardingState: OnboardingFlowReducer.State
|
var onboardingState: OnboardingFlowReducer.State
|
||||||
|
@ -36,6 +37,7 @@ struct RootReducer: ReducerProtocol {
|
||||||
case phraseDisplay(RecoveryPhraseDisplayReducer.Action)
|
case phraseDisplay(RecoveryPhraseDisplayReducer.Action)
|
||||||
case phraseValidation(RecoveryPhraseValidationFlowReducer.Action)
|
case phraseValidation(RecoveryPhraseValidationFlowReducer.Action)
|
||||||
case sandbox(SandboxReducer.Action)
|
case sandbox(SandboxReducer.Action)
|
||||||
|
case updateStateAfterConfigUpdate(WalletConfig)
|
||||||
case walletConfigLoaded(WalletConfig)
|
case walletConfigLoaded(WalletConfig)
|
||||||
case welcome(WelcomeReducer.Action)
|
case welcome(WelcomeReducer.Action)
|
||||||
}
|
}
|
||||||
|
@ -83,6 +85,8 @@ struct RootReducer: ReducerProtocol {
|
||||||
initializationReduce()
|
initializationReduce()
|
||||||
|
|
||||||
destinationReduce()
|
destinationReduce()
|
||||||
|
|
||||||
|
debugReduce()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +176,7 @@ extension RootReducer {
|
||||||
extension RootReducer.State {
|
extension RootReducer.State {
|
||||||
static var placeholder: Self {
|
static var placeholder: Self {
|
||||||
.init(
|
.init(
|
||||||
|
debugState: .placeholder,
|
||||||
destinationState: .placeholder,
|
destinationState: .placeholder,
|
||||||
homeState: .placeholder,
|
homeState: .placeholder,
|
||||||
onboardingState: .init(
|
onboardingState: .init(
|
||||||
|
|
|
@ -126,6 +126,14 @@ private extension RootView {
|
||||||
viewStore.goToDestination(.welcome)
|
viewStore.goToDestination(.welcome)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Button("Test Crash Reporter") {
|
||||||
|
viewStore.send(.debug(.testCrashReporter))
|
||||||
|
}
|
||||||
|
|
||||||
|
Button("Rescan Blockchain") {
|
||||||
|
viewStore.send(.debug(.rescanBlockchain))
|
||||||
|
}
|
||||||
|
|
||||||
Button("[Be careful] Nuke Wallet") {
|
Button("[Be careful] Nuke Wallet") {
|
||||||
viewStore.send(.initialization(.nukeWalletRequest))
|
viewStore.send(.initialization(.nukeWalletRequest))
|
||||||
}
|
}
|
||||||
|
@ -156,6 +164,10 @@ private extension RootView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.alert(self.store.scope(state: \.destinationState.alert), dismiss: .destination(.dismissAlert))
|
.alert(self.store.scope(state: \.destinationState.alert), dismiss: .destination(.dismissAlert))
|
||||||
|
.confirmationDialog(
|
||||||
|
store.scope(state: \.debugState.rescanDialog),
|
||||||
|
dismiss: .debug(.cancelRescan)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.navigationBarTitle("Startup")
|
.navigationBarTitle("Startup")
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,6 @@ struct SettingsReducer: ReducerProtocol {
|
||||||
@BindingState var isCrashReportingOn: Bool
|
@BindingState var isCrashReportingOn: Bool
|
||||||
var isSharingLogs = false
|
var isSharingLogs = false
|
||||||
var phraseDisplayState: RecoveryPhraseDisplayReducer.State
|
var phraseDisplayState: RecoveryPhraseDisplayReducer.State
|
||||||
var rescanDialog: ConfirmationDialogState<SettingsReducer.Action>?
|
|
||||||
var supportData: SupportData?
|
var supportData: SupportData?
|
||||||
|
|
||||||
var tempSDKDir: URL {
|
var tempSDKDir: URL {
|
||||||
|
@ -43,20 +42,15 @@ struct SettingsReducer: ReducerProtocol {
|
||||||
case backupWallet
|
case backupWallet
|
||||||
case backupWalletAccessRequest
|
case backupWalletAccessRequest
|
||||||
case binding(BindingAction<SettingsReducer.State>)
|
case binding(BindingAction<SettingsReducer.State>)
|
||||||
case cancelRescan
|
|
||||||
case dismissAlert
|
case dismissAlert
|
||||||
case exportLogs
|
case exportLogs
|
||||||
case fullRescan
|
|
||||||
case logsExported
|
case logsExported
|
||||||
case logsExportFailed(String)
|
case logsExportFailed(String)
|
||||||
case logsShareFinished
|
case logsShareFinished
|
||||||
case onAppear
|
case onAppear
|
||||||
case phraseDisplay(RecoveryPhraseDisplayReducer.Action)
|
case phraseDisplay(RecoveryPhraseDisplayReducer.Action)
|
||||||
case quickRescan
|
|
||||||
case rescanBlockchain
|
|
||||||
case sendSupportMail
|
case sendSupportMail
|
||||||
case sendSupportMailFinished
|
case sendSupportMailFinished
|
||||||
case testCrashReporter // this will crash the app if live.
|
|
||||||
case updateDestination(SettingsReducer.State.Destination?)
|
case updateDestination(SettingsReducer.State.Destination?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,10 +103,6 @@ struct SettingsReducer: ReducerProtocol {
|
||||||
await userStoredPreferences.setIsUserOptedOutOfCrashReporting(state.isCrashReportingOn)
|
await userStoredPreferences.setIsUserOptedOutOfCrashReporting(state.isCrashReportingOn)
|
||||||
}
|
}
|
||||||
|
|
||||||
case .cancelRescan, .quickRescan, .fullRescan:
|
|
||||||
state.rescanDialog = nil
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .dismissAlert:
|
case .dismissAlert:
|
||||||
state.alert = nil
|
state.alert = nil
|
||||||
return .none
|
return .none
|
||||||
|
@ -146,18 +136,6 @@ struct SettingsReducer: ReducerProtocol {
|
||||||
state.isSharingLogs = false
|
state.isSharingLogs = false
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .rescanBlockchain:
|
|
||||||
state.rescanDialog = .init(
|
|
||||||
title: TextState("Rescan"),
|
|
||||||
message: TextState("Select the rescan you want"),
|
|
||||||
buttons: [
|
|
||||||
.default(TextState("Quick rescan"), action: .send(.quickRescan)),
|
|
||||||
.default(TextState("Full rescan"), action: .send(.fullRescan)),
|
|
||||||
.cancel(TextState("Cancel"))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .phraseDisplay:
|
case .phraseDisplay:
|
||||||
state.destination = nil
|
state.destination = nil
|
||||||
return .none
|
return .none
|
||||||
|
@ -166,10 +144,6 @@ struct SettingsReducer: ReducerProtocol {
|
||||||
state.destination = destination
|
state.destination = destination
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case .testCrashReporter:
|
|
||||||
crashReporter.testCrash()
|
|
||||||
return .none
|
|
||||||
|
|
||||||
case .binding:
|
case .binding:
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
|
|
@ -18,13 +18,6 @@ struct SettingsView: View {
|
||||||
.activeButtonStyle
|
.activeButtonStyle
|
||||||
.frame(height: 50)
|
.frame(height: 50)
|
||||||
|
|
||||||
Button(
|
|
||||||
action: { viewStore.send(.rescanBlockchain) },
|
|
||||||
label: { Text("Rescan Blockchain") }
|
|
||||||
)
|
|
||||||
.primaryButtonStyle
|
|
||||||
.frame(height: 50)
|
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
action: { viewStore.send(.exportLogs) },
|
action: { viewStore.send(.exportLogs) },
|
||||||
label: {
|
label: {
|
||||||
|
@ -42,13 +35,6 @@ struct SettingsView: View {
|
||||||
.frame(height: 50)
|
.frame(height: 50)
|
||||||
.disabled(viewStore.exportLogsDisabled)
|
.disabled(viewStore.exportLogsDisabled)
|
||||||
|
|
||||||
Button(
|
|
||||||
action: { viewStore.send(.testCrashReporter) },
|
|
||||||
label: { Text("Test Crash Reporter") }
|
|
||||||
)
|
|
||||||
.primaryButtonStyle
|
|
||||||
.frame(height: 50)
|
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
action: { viewStore.send(.sendSupportMail) },
|
action: { viewStore.send(.sendSupportMail) },
|
||||||
label: { Text("Send us feedback!") }
|
label: { Text("Send us feedback!") }
|
||||||
|
@ -61,10 +47,6 @@ struct SettingsView: View {
|
||||||
.padding(.horizontal, 30)
|
.padding(.horizontal, 30)
|
||||||
.navigationTitle("Settings")
|
.navigationTitle("Settings")
|
||||||
.applyScreenBackground()
|
.applyScreenBackground()
|
||||||
.confirmationDialog(
|
|
||||||
store.scope(state: \.rescanDialog),
|
|
||||||
dismiss: .cancelRescan
|
|
||||||
)
|
|
||||||
.navigationLinkEmpty(
|
.navigationLinkEmpty(
|
||||||
isActive: viewStore.bindingForBackupPhrase,
|
isActive: viewStore.bindingForBackupPhrase,
|
||||||
destination: {
|
destination: {
|
||||||
|
|
|
@ -87,54 +87,4 @@ class HomeTests: XCTestCase {
|
||||||
// the .onDisappear action cancles the observer of the synchronizer status change.
|
// the .onDisappear action cancles the observer of the synchronizer status change.
|
||||||
store.send(.onDisappear)
|
store.send(.onDisappear)
|
||||||
}
|
}
|
||||||
|
|
||||||
@MainActor func testQuickRescan_ResetToHomeScreen() async throws {
|
|
||||||
let homeState = HomeReducer.State(
|
|
||||||
balanceBreakdownState: .placeholder,
|
|
||||||
destination: .profile,
|
|
||||||
profileState: .placeholder,
|
|
||||||
requestState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
|
||||||
sendState: .placeholder,
|
|
||||||
shieldedBalance: Balance.zero,
|
|
||||||
synchronizerStatusSnapshot: .default,
|
|
||||||
walletEventsState: .emptyPlaceHolder
|
|
||||||
)
|
|
||||||
|
|
||||||
let store = TestStore(
|
|
||||||
initialState: homeState,
|
|
||||||
reducer: HomeReducer()
|
|
||||||
)
|
|
||||||
|
|
||||||
await store.send(.profile(.settings(.quickRescan))) { state in
|
|
||||||
state.destination = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
await store.receive(.rewindDone(nil, .quickRescan))
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor func testFullRescan_ResetToHomeScreen() async throws {
|
|
||||||
let homeState = HomeReducer.State(
|
|
||||||
balanceBreakdownState: .placeholder,
|
|
||||||
destination: .profile,
|
|
||||||
profileState: .placeholder,
|
|
||||||
requestState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
|
||||||
sendState: .placeholder,
|
|
||||||
shieldedBalance: Balance.zero,
|
|
||||||
synchronizerStatusSnapshot: .default,
|
|
||||||
walletEventsState: .emptyPlaceHolder
|
|
||||||
)
|
|
||||||
|
|
||||||
let store = TestStore(
|
|
||||||
initialState: homeState,
|
|
||||||
reducer: HomeReducer()
|
|
||||||
)
|
|
||||||
|
|
||||||
await store.send(.profile(.settings(.fullRescan))) { state in
|
|
||||||
state.destination = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
await store.receive(.rewindDone(nil, .fullRescan))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,9 @@ import ComposableArchitecture
|
||||||
import ZcashLightClientKit
|
import ZcashLightClientKit
|
||||||
|
|
||||||
class ProfileTests: XCTestCase {
|
class ProfileTests: XCTestCase {
|
||||||
|
// swiftlint:disable line_length
|
||||||
|
let uAddressEncoding = "utest1zkkkjfxkamagznjr6ayemffj2d2gacdwpzcyw669pvg06xevzqslpmm27zjsctlkstl2vsw62xrjktmzqcu4yu9zdhdxqz3kafa4j2q85y6mv74rzjcgjg8c0ytrg7dwyzwtgnuc76h"
|
||||||
|
|
||||||
@MainActor func testSynchronizerStateChanged_AnyButSynced() async throws {
|
@MainActor func testSynchronizerStateChanged_AnyButSynced() async throws {
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: .placeholder,
|
initialState: .placeholder,
|
||||||
|
@ -20,9 +23,8 @@ class ProfileTests: XCTestCase {
|
||||||
dependencies.sdkSynchronizer = SDKSynchronizerDependency.mock
|
dependencies.sdkSynchronizer = SDKSynchronizerDependency.mock
|
||||||
}
|
}
|
||||||
|
|
||||||
// swiftlint:disable line_length
|
|
||||||
let uAddress = try UnifiedAddress(
|
let uAddress = try UnifiedAddress(
|
||||||
encoding: "utest1zkkkjfxkamagznjr6ayemffj2d2gacdwpzcyw669pvg06xevzqslpmm27zjsctlkstl2vsw62xrjktmzqcu4yu9zdhdxqz3kafa4j2q85y6mv74rzjcgjg8c0ytrg7dwyzwtgnuc76h",
|
encoding: uAddressEncoding,
|
||||||
network: .testnet
|
network: .testnet
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,4 +35,26 @@ class ProfileTests: XCTestCase {
|
||||||
state.sdkVersion = "0.18.1-beta"
|
state.sdkVersion = "0.18.1-beta"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testCopyUnifiedAddressToPasteboard() throws {
|
||||||
|
let testPasteboard = PasteboardClient.testPasteboard
|
||||||
|
let uAddress = try UnifiedAddress(encoding: uAddressEncoding, network: .testnet)
|
||||||
|
|
||||||
|
let store = TestStore(
|
||||||
|
initialState: ProfileReducer.State(
|
||||||
|
addressDetailsState: AddressDetailsReducer.State(uAddress: uAddress)
|
||||||
|
),
|
||||||
|
reducer: ProfileReducer()
|
||||||
|
) {
|
||||||
|
$0.pasteboard = testPasteboard
|
||||||
|
}
|
||||||
|
|
||||||
|
store.send(.copyUnifiedAddressToPastboard)
|
||||||
|
|
||||||
|
XCTAssertEqual(
|
||||||
|
testPasteboard.getString()?.data,
|
||||||
|
uAddress.stringEncoded,
|
||||||
|
"AddressDetails: `testCopyUnifiedAddressToPasteboard` is expected to match the input `\(uAddress.stringEncoded)`"
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,7 @@ class RecoveryPhraseValidationFlowFeatureFlagTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let appState = RootReducer.State(
|
let appState = RootReducer.State(
|
||||||
|
debugState: .placeholder,
|
||||||
destinationState: .placeholder,
|
destinationState: .placeholder,
|
||||||
homeState: .placeholder,
|
homeState: .placeholder,
|
||||||
onboardingState: .init(
|
onboardingState: .init(
|
||||||
|
|
|
@ -68,6 +68,7 @@ class AppInitializationTests: XCTestCase {
|
||||||
let walletConfig = WalletConfig(flags: defaultRawFlags)
|
let walletConfig = WalletConfig(flags: defaultRawFlags)
|
||||||
|
|
||||||
let appState = RootReducer.State(
|
let appState = RootReducer.State(
|
||||||
|
debugState: .placeholder,
|
||||||
destinationState: .placeholder,
|
destinationState: .placeholder,
|
||||||
homeState: .placeholder,
|
homeState: .placeholder,
|
||||||
onboardingState: .init(
|
onboardingState: .init(
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
//
|
||||||
|
// DebugTests.swift
|
||||||
|
// secantTests
|
||||||
|
//
|
||||||
|
// Created by Lukáš Korba on 02.03.2023.
|
||||||
|
//
|
||||||
|
|
||||||
|
import XCTest
|
||||||
|
@testable import secant_testnet
|
||||||
|
import ComposableArchitecture
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class DebugTests: XCTestCase {
|
||||||
|
func testRescanBlockchain() async throws {
|
||||||
|
let store = TestStore(
|
||||||
|
initialState: .placeholder,
|
||||||
|
reducer: RootReducer()
|
||||||
|
)
|
||||||
|
|
||||||
|
await store.send(.debug(.rescanBlockchain)) { state in
|
||||||
|
state.debugState.rescanDialog = .init(
|
||||||
|
title: TextState("Rescan"),
|
||||||
|
message: TextState("Select the rescan you want"),
|
||||||
|
buttons: [
|
||||||
|
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
|
||||||
|
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
|
||||||
|
.cancel(TextState("Cancel"))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRescanBlockchain_Cancelling() async throws {
|
||||||
|
var mockState = RootReducer.State.placeholder
|
||||||
|
|
||||||
|
mockState.debugState.rescanDialog = .init(
|
||||||
|
title: TextState("Rescan"),
|
||||||
|
message: TextState("Select the rescan you want"),
|
||||||
|
buttons: [
|
||||||
|
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
|
||||||
|
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
|
||||||
|
.cancel(TextState("Cancel"))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
let store = TestStore(
|
||||||
|
initialState: mockState,
|
||||||
|
reducer: RootReducer()
|
||||||
|
)
|
||||||
|
|
||||||
|
await store.send(.debug(.cancelRescan)) { state in
|
||||||
|
state.debugState.rescanDialog = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRescanBlockchain_QuickRescanClearance() async throws {
|
||||||
|
var mockState = RootReducer.State.placeholder
|
||||||
|
|
||||||
|
mockState.debugState.rescanDialog = .init(
|
||||||
|
title: TextState("Rescan"),
|
||||||
|
message: TextState("Select the rescan you want"),
|
||||||
|
buttons: [
|
||||||
|
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
|
||||||
|
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
|
||||||
|
.cancel(TextState("Cancel"))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
let store = TestStore(
|
||||||
|
initialState: mockState,
|
||||||
|
reducer: RootReducer()
|
||||||
|
)
|
||||||
|
|
||||||
|
await store.send(.debug(.quickRescan)) { state in
|
||||||
|
state.destinationState.internalDestination = .home
|
||||||
|
state.destinationState.previousDestination = .welcome
|
||||||
|
}
|
||||||
|
|
||||||
|
await store.receive(.debug(.rewindDone(nil, .debug(.quickRescan))))
|
||||||
|
}
|
||||||
|
|
||||||
|
func testRescanBlockchain_FullRescanClearance() async throws {
|
||||||
|
var mockState = RootReducer.State.placeholder
|
||||||
|
|
||||||
|
mockState.debugState.rescanDialog = .init(
|
||||||
|
title: TextState("Rescan"),
|
||||||
|
message: TextState("Select the rescan you want"),
|
||||||
|
buttons: [
|
||||||
|
.default(TextState("Quick rescan"), action: .send(.debug(.quickRescan))),
|
||||||
|
.default(TextState("Full rescan"), action: .send(.debug(.fullRescan))),
|
||||||
|
.cancel(TextState("Cancel"))
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
let store = TestStore(
|
||||||
|
initialState: mockState,
|
||||||
|
reducer: RootReducer()
|
||||||
|
)
|
||||||
|
|
||||||
|
await store.send(.debug(.fullRescan)) { state in
|
||||||
|
state.destinationState.internalDestination = .home
|
||||||
|
state.destinationState.previousDestination = .welcome
|
||||||
|
}
|
||||||
|
|
||||||
|
await store.receive(.debug(.rewindDone(nil, .debug(.fullRescan))))
|
||||||
|
}
|
||||||
|
}
|
|
@ -80,112 +80,12 @@ class SettingsTests: XCTestCase {
|
||||||
await store.finish()
|
await store.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRescanBlockchain() async throws {
|
|
||||||
let store = TestStore(
|
|
||||||
initialState: .placeholder,
|
|
||||||
reducer: SettingsReducer()
|
|
||||||
)
|
|
||||||
|
|
||||||
await store.send(.rescanBlockchain) { state in
|
|
||||||
state.rescanDialog = .init(
|
|
||||||
title: TextState("Rescan"),
|
|
||||||
message: TextState("Select the rescan you want"),
|
|
||||||
buttons: [
|
|
||||||
.default(TextState("Quick rescan"), action: .send(.quickRescan)),
|
|
||||||
.default(TextState("Full rescan"), action: .send(.fullRescan)),
|
|
||||||
.cancel(TextState("Cancel"))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testRescanBlockchain_Cancelling() async throws {
|
|
||||||
let store = TestStore(
|
|
||||||
initialState: SettingsReducer.State(
|
|
||||||
destination: nil,
|
|
||||||
isCrashReportingOn: false,
|
|
||||||
phraseDisplayState: .init(),
|
|
||||||
rescanDialog: .init(
|
|
||||||
title: TextState("Rescan"),
|
|
||||||
message: TextState("Select the rescan you want"),
|
|
||||||
buttons: [
|
|
||||||
.default(TextState("Quick rescan"), action: .send(.quickRescan)),
|
|
||||||
.default(TextState("Full rescan"), action: .send(.fullRescan)),
|
|
||||||
.cancel(TextState("Cancel"))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
reducer: SettingsReducer()
|
|
||||||
)
|
|
||||||
|
|
||||||
await store.send(.cancelRescan) { state in
|
|
||||||
state.rescanDialog = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testRescanBlockchain_QuickRescanClearance() async throws {
|
|
||||||
let store = TestStore(
|
|
||||||
initialState: SettingsReducer.State(
|
|
||||||
destination: nil,
|
|
||||||
isCrashReportingOn: false,
|
|
||||||
phraseDisplayState: .init(),
|
|
||||||
rescanDialog: .init(
|
|
||||||
title: TextState("Rescan"),
|
|
||||||
message: TextState("Select the rescan you want"),
|
|
||||||
buttons: [
|
|
||||||
.default(TextState("Quick rescan"), action: .send(.quickRescan)),
|
|
||||||
.default(TextState("Full rescan"), action: .send(.fullRescan)),
|
|
||||||
.cancel(TextState("Cancel"))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
reducer: SettingsReducer()
|
|
||||||
)
|
|
||||||
|
|
||||||
await store.send(.quickRescan) { state in
|
|
||||||
state.rescanDialog = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testRescanBlockchain_FullRescanClearance() async throws {
|
|
||||||
let store = TestStore(
|
|
||||||
initialState: SettingsReducer.State(
|
|
||||||
destination: nil,
|
|
||||||
isCrashReportingOn: false,
|
|
||||||
phraseDisplayState: .init(),
|
|
||||||
rescanDialog: .init(
|
|
||||||
title: TextState("Rescan"),
|
|
||||||
message: TextState("Select the rescan you want"),
|
|
||||||
buttons: [
|
|
||||||
.default(TextState("Quick rescan"), action: .send(.quickRescan)),
|
|
||||||
.default(TextState("Full rescan"), action: .send(.fullRescan)),
|
|
||||||
.cancel(TextState("Cancel"))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
reducer: SettingsReducer()
|
|
||||||
)
|
|
||||||
|
|
||||||
await store.send(.fullRescan) { state in
|
|
||||||
state.rescanDialog = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func testExportLogs_ButtonDisableShareEnable() async throws {
|
func testExportLogs_ButtonDisableShareEnable() async throws {
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: SettingsReducer.State(
|
initialState: SettingsReducer.State(
|
||||||
destination: nil,
|
destination: nil,
|
||||||
isCrashReportingOn: false,
|
isCrashReportingOn: false,
|
||||||
phraseDisplayState: .init(),
|
phraseDisplayState: .init()
|
||||||
rescanDialog: .init(
|
|
||||||
title: TextState("Rescan"),
|
|
||||||
message: TextState("Select the rescan you want"),
|
|
||||||
buttons: [
|
|
||||||
.default(TextState("Quick rescan"), action: .send(.quickRescan)),
|
|
||||||
.default(TextState("Full rescan"), action: .send(.fullRescan)),
|
|
||||||
.cancel(TextState("Cancel"))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
reducer: SettingsReducer()
|
reducer: SettingsReducer()
|
||||||
)
|
)
|
||||||
|
@ -208,16 +108,7 @@ class SettingsTests: XCTestCase {
|
||||||
destination: nil,
|
destination: nil,
|
||||||
isCrashReportingOn: false,
|
isCrashReportingOn: false,
|
||||||
isSharingLogs: true,
|
isSharingLogs: true,
|
||||||
phraseDisplayState: .init(),
|
phraseDisplayState: .init()
|
||||||
rescanDialog: .init(
|
|
||||||
title: TextState("Rescan"),
|
|
||||||
message: TextState("Select the rescan you want"),
|
|
||||||
buttons: [
|
|
||||||
.default(TextState("Quick rescan"), action: .send(.quickRescan)),
|
|
||||||
.default(TextState("Full rescan"), action: .send(.fullRescan)),
|
|
||||||
.cancel(TextState("Cancel"))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
reducer: SettingsReducer()
|
reducer: SettingsReducer()
|
||||||
)
|
)
|
||||||
|
|
|
@ -39,9 +39,9 @@ class HomeSnapshotTests: XCTestCase {
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
balanceBreakdownState: .placeholder,
|
balanceBreakdownState: .placeholder,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
sendState: .placeholder,
|
sendState: .placeholder,
|
||||||
|
settingsState: .placeholder,
|
||||||
shieldedBalance: balance.redacted,
|
shieldedBalance: balance.redacted,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: walletEvents))
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: walletEvents))
|
||||||
|
|
|
@ -54,9 +54,9 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
balanceBreakdownState: .placeholder,
|
balanceBreakdownState: .placeholder,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
sendState: .placeholder,
|
sendState: .placeholder,
|
||||||
|
settingsState: .placeholder,
|
||||||
shieldedBalance: balance.redacted,
|
shieldedBalance: balance.redacted,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
||||||
|
@ -106,9 +106,9 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
balanceBreakdownState: .placeholder,
|
balanceBreakdownState: .placeholder,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
sendState: .placeholder,
|
sendState: .placeholder,
|
||||||
|
settingsState: .placeholder,
|
||||||
shieldedBalance: balance.redacted,
|
shieldedBalance: balance.redacted,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
||||||
|
@ -158,9 +158,9 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
balanceBreakdownState: .placeholder,
|
balanceBreakdownState: .placeholder,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
sendState: .placeholder,
|
sendState: .placeholder,
|
||||||
|
settingsState: .placeholder,
|
||||||
shieldedBalance: balance.redacted,
|
shieldedBalance: balance.redacted,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
||||||
|
@ -216,9 +216,9 @@ class WalletEventsSnapshotTests: XCTestCase {
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
balanceBreakdownState: .placeholder,
|
balanceBreakdownState: .placeholder,
|
||||||
profileState: .placeholder,
|
profileState: .placeholder,
|
||||||
requestState: .placeholder,
|
|
||||||
scanState: .placeholder,
|
scanState: .placeholder,
|
||||||
sendState: .placeholder,
|
sendState: .placeholder,
|
||||||
|
settingsState: .placeholder,
|
||||||
shieldedBalance: balance.redacted,
|
shieldedBalance: balance.redacted,
|
||||||
synchronizerStatusSnapshot: .default,
|
synchronizerStatusSnapshot: .default,
|
||||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent]))
|
||||||
|
|
|
@ -127,8 +127,10 @@ class WalletConfigProviderTests: XCTestCase {
|
||||||
defaultRawFlags[.onboardingFlow] = true
|
defaultRawFlags[.onboardingFlow] = true
|
||||||
let flags = WalletConfig(flags: defaultRawFlags)
|
let flags = WalletConfig(flags: defaultRawFlags)
|
||||||
|
|
||||||
|
store.send(.debug(.walletConfigLoaded(flags)))
|
||||||
|
|
||||||
// The new flag's value has to be propagated to all `walletConfig` instances
|
// The new flag's value has to be propagated to all `walletConfig` instances
|
||||||
store.send(.debug(.walletConfigLoaded(flags))) { state in
|
store.receive(.updateStateAfterConfigUpdate(flags)) { state in
|
||||||
state.walletConfig = flags
|
state.walletConfig = flags
|
||||||
state.onboardingState.walletConfig = flags
|
state.onboardingState.walletConfig = flags
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue