Merge pull request #267 from LukasKorba/266_refactor_and_simplify_homeDebug_views
Old home->sandbox, new home for #255
This commit is contained in:
commit
7b33b632b9
|
@ -101,9 +101,13 @@
|
|||
9E4DC6E227C4C6B700E657F4 /* SecantButtonStyles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E4DC6E127C4C6B700E657F4 /* SecantButtonStyles.swift */; };
|
||||
9E69A24D27FB002800A55317 /* Welcome.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E69A24C27FB002800A55317 /* Welcome.swift */; };
|
||||
9E80B47227E4B34B008FF493 /* UserPreferencesStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E80B47127E4B34B008FF493 /* UserPreferencesStorage.swift */; };
|
||||
9EAFEB822805793200199FC9 /* AppReducerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB812805793200199FC9 /* AppReducerTests.swift */; };
|
||||
9EAFEB84280597B700199FC9 /* WrappedSecItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */; };
|
||||
9EAFEB862805A23100199FC9 /* WrappedSecItemTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB852805A23100199FC9 /* WrappedSecItemTests.swift */; };
|
||||
9EAFEB822805793200199FC9 /* AppReducerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB812805793200199FC9 /* AppReducerTests.swift */; };
|
||||
9EAFEB8F2808183D00199FC9 /* SandboxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB8D2808183D00199FC9 /* SandboxView.swift */; };
|
||||
9EAFEB902808183D00199FC9 /* SandboxStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EAFEB8E2808183D00199FC9 /* SandboxStore.swift */; };
|
||||
9EAFEB9128081E9400199FC9 /* HomeStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93874ED273C4DE200F0E875 /* HomeStore.swift */; };
|
||||
9EAFEB9228081E9400199FC9 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93874EF273C4DE200F0E875 /* HomeView.swift */; };
|
||||
9EBEF87A27CE369800B4F343 /* RecoveryPhraseTestPreambleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EBEF87927CE369800B4F343 /* RecoveryPhraseTestPreambleView.swift */; };
|
||||
9ECAE56827FC713C0089A0EF /* DatabaseFiles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9ECAE56727FC713C0089A0EF /* DatabaseFiles.swift */; };
|
||||
9EF8135C27ECC25E0075AF48 /* WalletStorageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8135A27ECC25E0075AF48 /* WalletStorageTests.swift */; };
|
||||
|
@ -114,8 +118,6 @@
|
|||
9EF8139C27F47AED0075AF48 /* InitializationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EF8139B27F47AED0075AF48 /* InitializationState.swift */; };
|
||||
F9322DC0273B555C00C105B5 /* NavigationLinks.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9322DBF273B555C00C105B5 /* NavigationLinks.swift */; };
|
||||
F93673D62742CB840099C6AF /* Previews.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93673D52742CB840099C6AF /* Previews.swift */; };
|
||||
F93874F0273C4DE200F0E875 /* HomeStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93874ED273C4DE200F0E875 /* HomeStore.swift */; };
|
||||
F93874F1273C4DE200F0E875 /* HomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F93874EF273C4DE200F0E875 /* HomeView.swift */; };
|
||||
F96B41E7273B501F0021B49A /* TransactionHistoryStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E3273B501F0021B49A /* TransactionHistoryStore.swift */; };
|
||||
F96B41E8273B501F0021B49A /* TransactionDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E5273B501F0021B49A /* TransactionDetailView.swift */; };
|
||||
F96B41E9273B501F0021B49A /* TransactionHistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E6273B501F0021B49A /* TransactionHistoryView.swift */; };
|
||||
|
@ -257,9 +259,11 @@
|
|||
9E4DC6E127C4C6B700E657F4 /* SecantButtonStyles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecantButtonStyles.swift; sourceTree = "<group>"; };
|
||||
9E69A24C27FB002800A55317 /* Welcome.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Welcome.swift; sourceTree = "<group>"; };
|
||||
9E80B47127E4B34B008FF493 /* UserPreferencesStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserPreferencesStorage.swift; sourceTree = "<group>"; };
|
||||
9EAFEB812805793200199FC9 /* AppReducerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppReducerTests.swift; sourceTree = "<group>"; };
|
||||
9EAFEB83280597B700199FC9 /* WrappedSecItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItem.swift; sourceTree = "<group>"; };
|
||||
9EAFEB852805A23100199FC9 /* WrappedSecItemTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedSecItemTests.swift; sourceTree = "<group>"; };
|
||||
9EAFEB812805793200199FC9 /* AppReducerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppReducerTests.swift; sourceTree = "<group>"; };
|
||||
9EAFEB8D2808183D00199FC9 /* SandboxView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SandboxView.swift; sourceTree = "<group>"; };
|
||||
9EAFEB8E2808183D00199FC9 /* SandboxStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SandboxStore.swift; sourceTree = "<group>"; };
|
||||
9EBEF87927CE369800B4F343 /* RecoveryPhraseTestPreambleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RecoveryPhraseTestPreambleView.swift; sourceTree = "<group>"; };
|
||||
9ECAE56727FC713C0089A0EF /* DatabaseFiles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseFiles.swift; sourceTree = "<group>"; };
|
||||
9EF8135A27ECC25E0075AF48 /* WalletStorageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletStorageTests.swift; sourceTree = "<group>"; };
|
||||
|
@ -664,6 +668,7 @@
|
|||
6654C73B2715A3F000901167 /* Features */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9EAFEB8B2808174900199FC9 /* Sandbox */,
|
||||
0D0781C2278750C00083ACD7 /* Welcome */,
|
||||
F9971A4927680DC400A2DB75 /* App */,
|
||||
F93874EC273C4DE200F0E875 /* Home */,
|
||||
|
@ -768,6 +773,23 @@
|
|||
path = AppReducer;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9EAFEB8B2808174900199FC9 /* Sandbox */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9EAFEB8E2808183D00199FC9 /* SandboxStore.swift */,
|
||||
9EAFEB8C2808183D00199FC9 /* Views */,
|
||||
);
|
||||
path = Sandbox;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9EAFEB8C2808183D00199FC9 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9EAFEB8D2808183D00199FC9 /* SandboxView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9EBEF87827CE365D00B4F343 /* Preamble */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1149,6 +1171,7 @@
|
|||
files = (
|
||||
2EB660E02747EAB900A06A07 /* OnboardingScreen.swift in Sources */,
|
||||
660558F8270C862F009D6954 /* XCAssets+Generated.swift in Sources */,
|
||||
9EAFEB902808183D00199FC9 /* SandboxStore.swift in Sources */,
|
||||
0D35CC46277A36E00074316A /* ScrollableWhenScaled.swift in Sources */,
|
||||
F96B41E9273B501F0021B49A /* TransactionHistoryView.swift in Sources */,
|
||||
2EDA07A027EDE18C00D6F09B /* TextFieldInput.swift in Sources */,
|
||||
|
@ -1176,7 +1199,6 @@
|
|||
0D6D628B276A528E002FB4CC /* DropDelegate.swift in Sources */,
|
||||
9E2DF99D27CF704D00649636 /* ImportSeedEditor.swift in Sources */,
|
||||
F9971A5327680DD000A2DB75 /* Profile.swift in Sources */,
|
||||
F93874F0273C4DE200F0E875 /* HomeStore.swift in Sources */,
|
||||
669FDAEB272C23C2007B9422 /* CircularFrameBadge.swift in Sources */,
|
||||
2E8719CD27FB0D3B0082C926 /* TransactionCurrencySelector.swift in Sources */,
|
||||
F9971A6C27680E1000A2DB75 /* WalletInfoView.swift in Sources */,
|
||||
|
@ -1188,8 +1210,9 @@
|
|||
665C963F272C26E600BC04FB /* CircularFrameBackground.swift in Sources */,
|
||||
0DB8AA81271DC7520035BC9D /* DesignGuide.swift in Sources */,
|
||||
F9971A4D27680DC400A2DB75 /* App.swift in Sources */,
|
||||
9EAFEB9228081E9400199FC9 /* HomeView.swift in Sources */,
|
||||
F9322DC0273B555C00C105B5 /* NavigationLinks.swift in Sources */,
|
||||
F93874F1273C4DE200F0E875 /* HomeView.swift in Sources */,
|
||||
9EAFEB8F2808183D00199FC9 /* SandboxView.swift in Sources */,
|
||||
0D7CE63427349B5D0020E050 /* View+WhenDraggable.swift in Sources */,
|
||||
0D3D04082728B3440032ABC1 /* RecoveryPhraseDisplayView.swift in Sources */,
|
||||
F9971A5F27680DF600A2DB75 /* ScanView.swift in Sources */,
|
||||
|
@ -1203,6 +1226,7 @@
|
|||
0D354A0926D5A9D000315F45 /* Services.swift in Sources */,
|
||||
660558F7270C862F009D6954 /* Fonts+Generated.swift in Sources */,
|
||||
F96B41E7273B501F0021B49A /* TransactionHistoryStore.swift in Sources */,
|
||||
9EAFEB9128081E9400199FC9 /* HomeStore.swift in Sources */,
|
||||
F9971A5A27680DDE00A2DB75 /* RequestView.swift in Sources */,
|
||||
0DACFA8127208D940039EEA5 /* UInt+SuperscriptText.swift in Sources */,
|
||||
0DF2DC51272344E400FA31E2 /* EmptyChip.swift in Sources */,
|
||||
|
|
|
@ -6,19 +6,21 @@ struct AppState: Equatable {
|
|||
case welcome
|
||||
case startup
|
||||
case onboarding
|
||||
case sandbox
|
||||
case home
|
||||
case phraseValidation
|
||||
case phraseDisplay
|
||||
}
|
||||
|
||||
var appInitializationState: InitializationState = .uninitialized
|
||||
var homeState: HomeState
|
||||
var onboardingState: OnboardingState
|
||||
var phraseValidationState: RecoveryPhraseValidationState
|
||||
var phraseDisplayState: RecoveryPhraseDisplayState
|
||||
var welcomeState: WelcomeState
|
||||
var route: Route = .welcome
|
||||
var sandboxState: SandboxState
|
||||
var storedWallet: StoredWallet?
|
||||
var appInitializationState: InitializationState = .uninitialized
|
||||
var welcomeState: WelcomeState
|
||||
}
|
||||
|
||||
enum AppAction: Equatable {
|
||||
|
@ -32,6 +34,7 @@ enum AppAction: Equatable {
|
|||
case phraseDisplay(RecoveryPhraseDisplayAction)
|
||||
case phraseValidation(RecoveryPhraseValidationAction)
|
||||
case respondToWalletInitializationState(InitializationState)
|
||||
case sandbox(SandboxAction)
|
||||
case updateRoute(AppState.Route)
|
||||
case welcome(WelcomeAction)
|
||||
}
|
||||
|
@ -72,11 +75,12 @@ extension AppReducer {
|
|||
static let `default` = AppReducer.combine(
|
||||
[
|
||||
appReducer,
|
||||
routeReducer,
|
||||
homeReducer,
|
||||
onboardingReducer,
|
||||
phraseValidationReducer,
|
||||
phraseDisplayReducer
|
||||
phraseDisplayReducer,
|
||||
routeReducer,
|
||||
sandboxReducer
|
||||
]
|
||||
)
|
||||
.debug()
|
||||
|
@ -136,7 +140,7 @@ extension AppReducer {
|
|||
.cancellable(id: ListenerId(), cancelInFlight: true)
|
||||
}
|
||||
|
||||
var landingRoute: AppState.Route = .startup
|
||||
var landingRoute: AppState.Route = .home
|
||||
|
||||
if !storedWallet.hasUserPassedPhraseBackupTest {
|
||||
let phraseWords: [String]
|
||||
|
@ -195,12 +199,6 @@ extension AppReducer {
|
|||
// TODO: - when DatabaseFiles dependency is merged, nukeFiles as well, issue #220 (https://github.com/zcash/secant-ios-wallet/issues/220)
|
||||
return .none
|
||||
|
||||
case .welcome(.debugMenuHome):
|
||||
return .concatenate(
|
||||
Effect.cancel(id: ListenerId()),
|
||||
Effect(value: .updateRoute(.home))
|
||||
)
|
||||
|
||||
case .welcome(.debugMenuStartup):
|
||||
return .concatenate(
|
||||
Effect.cancel(id: ListenerId()),
|
||||
|
@ -208,7 +206,7 @@ extension AppReducer {
|
|||
)
|
||||
|
||||
case .onboarding(.importWallet(.successfullyRecovered)):
|
||||
return Effect(value: .updateRoute(.home))
|
||||
return Effect(value: .updateRoute(.sandbox))
|
||||
|
||||
/// Default is meaningful here because there's `routeReducer` handling routes and this reducer is handling only actions. We don't here plenty of unused cases.
|
||||
default:
|
||||
|
@ -221,7 +219,7 @@ extension AppReducer {
|
|||
case let .updateRoute(route):
|
||||
state.route = route
|
||||
|
||||
case .home(.reset):
|
||||
case .sandbox(.reset):
|
||||
state.route = .startup
|
||||
|
||||
case .onboarding(.createNewWallet):
|
||||
|
@ -274,6 +272,12 @@ extension AppReducer {
|
|||
environment: { _ in BackupPhraseEnvironment.demo }
|
||||
)
|
||||
|
||||
private static let sandboxReducer: AppReducer = SandboxReducer.default.pullback(
|
||||
state: \AppState.sandboxState,
|
||||
action: /AppAction.sandbox,
|
||||
environment: { _ in }
|
||||
)
|
||||
|
||||
private static let welcomeReducer: AppReducer = WelcomeReducer.default.pullback(
|
||||
state: \AppState.welcomeState,
|
||||
action: /AppAction.welcome,
|
||||
|
@ -356,6 +360,7 @@ extension AppState {
|
|||
phraseDisplayState: RecoveryPhraseDisplayState(
|
||||
phrase: .placeholder
|
||||
),
|
||||
sandboxState: .placeholder,
|
||||
welcomeState: .placeholder
|
||||
)
|
||||
}
|
||||
|
|
|
@ -9,11 +9,19 @@ struct AppView: View {
|
|||
WithViewStore(store) { viewStore in
|
||||
switch viewStore.route {
|
||||
case .home:
|
||||
HomeView(
|
||||
store: store.scope(
|
||||
state: \.homeState,
|
||||
action: AppAction.home
|
||||
)
|
||||
)
|
||||
|
||||
case .sandbox:
|
||||
NavigationView {
|
||||
HomeView(
|
||||
SandboxView(
|
||||
store: store.scope(
|
||||
state: \.homeState,
|
||||
action: AppAction.home
|
||||
state: \.sandboxState,
|
||||
action: AppAction.sandbox
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -75,8 +83,8 @@ private struct StartupView: View {
|
|||
var body: some View {
|
||||
List {
|
||||
Section(header: Text("Navigation Stack Routes")) {
|
||||
Button("Go To Home") {
|
||||
sendAction(.updateRoute(.home))
|
||||
Button("Go To Sandbox (navigation proof)") {
|
||||
sendAction(.updateRoute(.sandbox))
|
||||
}
|
||||
|
||||
Button("Go To Onboarding") {
|
||||
|
|
|
@ -2,24 +2,10 @@ import ComposableArchitecture
|
|||
import SwiftUI
|
||||
|
||||
struct HomeState: Equatable {
|
||||
enum Route: Equatable, CaseIterable {
|
||||
case history
|
||||
case send
|
||||
case recoveryPhraseDisplay
|
||||
case profile
|
||||
case scan
|
||||
case request
|
||||
}
|
||||
var transactionHistoryState: TransactionHistoryState
|
||||
var profileState: ProfileState
|
||||
var route: Route?
|
||||
var balance: Double
|
||||
}
|
||||
|
||||
enum HomeAction: Equatable {
|
||||
case updateRoute(HomeState.Route?)
|
||||
case transactionHistory(TransactionHistoryAction)
|
||||
case profile(ProfileAction)
|
||||
case reset
|
||||
}
|
||||
|
||||
// MARK: - HomeReducer
|
||||
|
@ -27,30 +13,8 @@ enum HomeAction: Equatable {
|
|||
typealias HomeReducer = Reducer<HomeState, HomeAction, Void>
|
||||
|
||||
extension HomeReducer {
|
||||
static let `default` = HomeReducer { state, action, _ in
|
||||
switch action {
|
||||
case let .updateRoute(route):
|
||||
state.route = route
|
||||
return .none
|
||||
case let .transactionHistory(transactionHistoryAction):
|
||||
return TransactionHistoryReducer
|
||||
.default
|
||||
.run(&state.transactionHistoryState, transactionHistoryAction, ())
|
||||
.map(HomeAction.transactionHistory)
|
||||
case let .profile(profileAction):
|
||||
return ProfileReducer
|
||||
.default
|
||||
.pullback(
|
||||
state: \.profileState,
|
||||
action: /HomeAction.profile,
|
||||
environment: { _ in
|
||||
return ProfileEnvironment()
|
||||
}
|
||||
)
|
||||
.run(&state, action, ())
|
||||
case .reset:
|
||||
return .none
|
||||
}
|
||||
static let `default` = HomeReducer { _, _, _ in
|
||||
return .none
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,58 +22,11 @@ extension HomeReducer {
|
|||
|
||||
typealias HomeStore = Store<HomeState, HomeAction>
|
||||
|
||||
extension HomeStore {
|
||||
func historyStore() -> TransactionHistoryStore {
|
||||
self.scope(
|
||||
state: \.transactionHistoryState,
|
||||
action: HomeAction.transactionHistory
|
||||
)
|
||||
}
|
||||
|
||||
func profileStore() -> ProfileStore {
|
||||
self.scope(
|
||||
state: \.profileState,
|
||||
action: HomeAction.profile
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - HomeViewStore
|
||||
|
||||
typealias HomeViewStore = ViewStore<HomeState, HomeAction>
|
||||
|
||||
extension HomeViewStore {
|
||||
func toggleSelectedTransaction() {
|
||||
let isAlreadySelected = (self.selectedTranactionID != nil)
|
||||
let transcation = self.transactionHistoryState.transactions[5]
|
||||
let newRoute = isAlreadySelected ? nil : TransactionHistoryState.Route.showTransaction(transcation)
|
||||
send(.transactionHistory(.setRoute(newRoute)))
|
||||
}
|
||||
|
||||
var selectedTranactionID: Int? {
|
||||
self.transactionHistoryState
|
||||
.route
|
||||
.flatMap(/TransactionHistoryState.Route.showTransaction)
|
||||
.map(\.id)
|
||||
}
|
||||
|
||||
func bindingForRoute(_ route: HomeState.Route) -> Binding<Bool> {
|
||||
self.binding(
|
||||
get: { $0.route == route },
|
||||
send: { isActive in
|
||||
return .updateRoute(isActive ? route : nil)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: PlaceHolders
|
||||
extension HomeState {
|
||||
static var placeholder: Self {
|
||||
.init(
|
||||
transactionHistoryState: .placeHolder,
|
||||
profileState: .placeholder,
|
||||
route: nil
|
||||
balance: 1.2
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,113 +4,21 @@ import ComposableArchitecture
|
|||
struct HomeView: View {
|
||||
let store: Store<HomeState, HomeAction>
|
||||
|
||||
var navigationRouteValues: [RouteValue] = HomeState.Route.allCases
|
||||
.enumerated()
|
||||
.filter { $0.1 != .history }
|
||||
.map { RouteValue(id: $0.0, route: $0.1) }
|
||||
|
||||
var modalRoutes: [RouteValue] = HomeState.Route.allCases
|
||||
.enumerated()
|
||||
.filter { $0.1 == .history }
|
||||
.map { RouteValue(id: $0.0, route: $0.1) }
|
||||
|
||||
@ViewBuilder func view(for route: HomeState.Route) -> some View {
|
||||
switch route {
|
||||
case .history:
|
||||
TransactionHistoryView(store: store.historyStore())
|
||||
case .send:
|
||||
SendView(
|
||||
store: .init(
|
||||
initialState: .placeholder,
|
||||
reducer: SendReducer.default(
|
||||
whenDone: { HomeViewStore(store).send(.updateRoute(nil)) }
|
||||
)
|
||||
.debug(),
|
||||
environment: ()
|
||||
)
|
||||
)
|
||||
case .recoveryPhraseDisplay:
|
||||
RecoveryPhraseDisplayView(store: .demo)
|
||||
case .scan:
|
||||
ScanView()
|
||||
case .profile:
|
||||
ProfileView(store: store.profileStore())
|
||||
case .request:
|
||||
RequestView()
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
WithViewStore(store) { viewStore in
|
||||
VStack {
|
||||
List {
|
||||
Section(header: Text("Navigation Stack Routes")) {
|
||||
ForEach(navigationRouteValues) { routeValue in
|
||||
Text("\(String(describing: routeValue.route))")
|
||||
.navigationLink(
|
||||
isActive: viewStore.bindingForRoute(routeValue.route),
|
||||
destination: {
|
||||
view(for: routeValue.route)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Modal Routes")) {
|
||||
ForEach(modalRoutes) { routeValue in
|
||||
Button(
|
||||
action: { viewStore.send(.updateRoute(routeValue.route)) },
|
||||
label: { Text("\(String(describing: routeValue.route))") }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Other Actions")) {
|
||||
Button(
|
||||
action: { viewStore.toggleSelectedTransaction() },
|
||||
label: { Text("Toggle Selected Transaction") }
|
||||
)
|
||||
|
||||
Button(
|
||||
action: { viewStore.send(.reset) },
|
||||
label: { Text("Reset (to startup)") }
|
||||
)
|
||||
}
|
||||
}
|
||||
Text("balance \(viewStore.balance)")
|
||||
}
|
||||
.fullScreenCover(
|
||||
isPresented: viewStore.bindingForRoute(.history),
|
||||
content: {
|
||||
NavigationView {
|
||||
TransactionHistoryView(store: store.historyStore())
|
||||
.toolbar {
|
||||
ToolbarItem {
|
||||
Button("Done") { viewStore.send(.updateRoute(nil)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
.navigationBarTitle("Home")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RouteValue: Identifiable {
|
||||
let id: Int
|
||||
let route: HomeState.Route
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
extension HomeStore {
|
||||
static var placeholder: HomeStore {
|
||||
HomeStore(
|
||||
initialState: HomeState(
|
||||
transactionHistoryState: .placeHolder,
|
||||
profileState: .placeholder,
|
||||
route: nil
|
||||
),
|
||||
initialState: .placeholder,
|
||||
reducer: .default.debug(),
|
||||
environment: ()
|
||||
)
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
import ComposableArchitecture
|
||||
import SwiftUI
|
||||
|
||||
struct SandboxState: Equatable {
|
||||
enum Route: Equatable, CaseIterable {
|
||||
case history
|
||||
case send
|
||||
case recoveryPhraseDisplay
|
||||
case profile
|
||||
case scan
|
||||
case request
|
||||
}
|
||||
var transactionHistoryState: TransactionHistoryState
|
||||
var profileState: ProfileState
|
||||
var route: Route?
|
||||
}
|
||||
|
||||
enum SandboxAction: Equatable {
|
||||
case updateRoute(SandboxState.Route?)
|
||||
case transactionHistory(TransactionHistoryAction)
|
||||
case profile(ProfileAction)
|
||||
case reset
|
||||
}
|
||||
|
||||
// MARK: - SandboxReducer
|
||||
|
||||
typealias SandboxReducer = Reducer<SandboxState, SandboxAction, Void>
|
||||
|
||||
extension SandboxReducer {
|
||||
static let `default` = SandboxReducer { state, action, _ in
|
||||
switch action {
|
||||
case let .updateRoute(route):
|
||||
state.route = route
|
||||
return .none
|
||||
case let .transactionHistory(transactionHistoryAction):
|
||||
return TransactionHistoryReducer
|
||||
.default
|
||||
.run(&state.transactionHistoryState, transactionHistoryAction, ())
|
||||
.map(SandboxAction.transactionHistory)
|
||||
case let .profile(profileAction):
|
||||
return ProfileReducer
|
||||
.default
|
||||
.pullback(
|
||||
state: \.profileState,
|
||||
action: /SandboxAction.profile,
|
||||
environment: { _ in
|
||||
return ProfileEnvironment()
|
||||
}
|
||||
)
|
||||
.run(&state, action, ())
|
||||
case .reset:
|
||||
return .none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SandboxStore
|
||||
|
||||
typealias SandboxStore = Store<SandboxState, SandboxAction>
|
||||
|
||||
extension SandboxStore {
|
||||
func historyStore() -> TransactionHistoryStore {
|
||||
self.scope(
|
||||
state: \.transactionHistoryState,
|
||||
action: SandboxAction.transactionHistory
|
||||
)
|
||||
}
|
||||
|
||||
func profileStore() -> ProfileStore {
|
||||
self.scope(
|
||||
state: \.profileState,
|
||||
action: SandboxAction.profile
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - SandboxViewStore
|
||||
|
||||
typealias SandboxViewStore = ViewStore<SandboxState, SandboxAction>
|
||||
|
||||
extension SandboxViewStore {
|
||||
func toggleSelectedTransaction() {
|
||||
let isAlreadySelected = (self.selectedTranactionID != nil)
|
||||
let transcation = self.transactionHistoryState.transactions[5]
|
||||
let newRoute = isAlreadySelected ? nil : TransactionHistoryState.Route.showTransaction(transcation)
|
||||
send(.transactionHistory(.setRoute(newRoute)))
|
||||
}
|
||||
|
||||
var selectedTranactionID: Int? {
|
||||
self.transactionHistoryState
|
||||
.route
|
||||
.flatMap(/TransactionHistoryState.Route.showTransaction)
|
||||
.map(\.id)
|
||||
}
|
||||
|
||||
func bindingForRoute(_ route: SandboxState.Route) -> Binding<Bool> {
|
||||
self.binding(
|
||||
get: { $0.route == route },
|
||||
send: { isActive in
|
||||
return .updateRoute(isActive ? route : nil)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: PlaceHolders
|
||||
extension SandboxState {
|
||||
static var placeholder: Self {
|
||||
.init(
|
||||
transactionHistoryState: .placeHolder,
|
||||
profileState: .placeholder,
|
||||
route: nil
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
import SwiftUI
|
||||
import ComposableArchitecture
|
||||
|
||||
struct SandboxView: View {
|
||||
let store: Store<SandboxState, SandboxAction>
|
||||
|
||||
var navigationRouteValues: [SandboxRouteValue] = SandboxState.Route.allCases
|
||||
.enumerated()
|
||||
.filter { $0.1 != .history }
|
||||
.map { SandboxRouteValue(id: $0.0, route: $0.1) }
|
||||
|
||||
var modalRoutes: [SandboxRouteValue] = SandboxState.Route.allCases
|
||||
.enumerated()
|
||||
.filter { $0.1 == .history }
|
||||
.map { SandboxRouteValue(id: $0.0, route: $0.1) }
|
||||
|
||||
@ViewBuilder func view(for route: SandboxState.Route) -> some View {
|
||||
switch route {
|
||||
case .history:
|
||||
TransactionHistoryView(store: store.historyStore())
|
||||
case .send:
|
||||
SendView(
|
||||
store: .init(
|
||||
initialState: .placeholder,
|
||||
reducer: SendReducer.default(
|
||||
whenDone: { SandboxViewStore(store).send(.updateRoute(nil)) }
|
||||
)
|
||||
.debug(),
|
||||
environment: ()
|
||||
)
|
||||
)
|
||||
case .recoveryPhraseDisplay:
|
||||
RecoveryPhraseDisplayView(store: .demo)
|
||||
case .scan:
|
||||
ScanView()
|
||||
case .profile:
|
||||
ProfileView(store: store.profileStore())
|
||||
case .request:
|
||||
RequestView()
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
WithViewStore(store) { viewStore in
|
||||
VStack {
|
||||
List {
|
||||
Section(header: Text("Navigation Stack Routes")) {
|
||||
ForEach(navigationRouteValues) { routeValue in
|
||||
Text("\(String(describing: routeValue.route))")
|
||||
.navigationLink(
|
||||
isActive: viewStore.bindingForRoute(routeValue.route),
|
||||
destination: {
|
||||
view(for: routeValue.route)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Modal Routes")) {
|
||||
ForEach(modalRoutes) { routeValue in
|
||||
Button(
|
||||
action: { viewStore.send(.updateRoute(routeValue.route)) },
|
||||
label: { Text("\(String(describing: routeValue.route))") }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Section(header: Text("Other Actions")) {
|
||||
Button(
|
||||
action: { viewStore.toggleSelectedTransaction() },
|
||||
label: { Text("Toggle Selected Transaction") }
|
||||
)
|
||||
|
||||
Button(
|
||||
action: { viewStore.send(.reset) },
|
||||
label: { Text("Reset (to startup)") }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.fullScreenCover(
|
||||
isPresented: viewStore.bindingForRoute(.history),
|
||||
content: {
|
||||
NavigationView {
|
||||
TransactionHistoryView(store: store.historyStore())
|
||||
.toolbar {
|
||||
ToolbarItem {
|
||||
Button("Done") { viewStore.send(.updateRoute(nil)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
.navigationBarTitle("Sandbox")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SandboxRouteValue: Identifiable {
|
||||
let id: Int
|
||||
let route: SandboxState.Route
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
||||
extension SandboxStore {
|
||||
static var placeholder: SandboxStore {
|
||||
SandboxStore(
|
||||
initialState: SandboxState(
|
||||
transactionHistoryState: .placeHolder,
|
||||
profileState: .placeholder,
|
||||
route: nil
|
||||
),
|
||||
reducer: .default.debug(),
|
||||
environment: ()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct SandboxView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NavigationView {
|
||||
SandboxView(store: .placeholder)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,7 +16,6 @@ extension WelcomeState {
|
|||
|
||||
enum WelcomeAction: Equatable {
|
||||
case debugMenuStartup
|
||||
case debugMenuHome
|
||||
}
|
||||
|
||||
typealias WelcomeReducer = Reducer<WelcomeState, WelcomeAction, Void>
|
||||
|
|
|
@ -41,9 +41,7 @@ struct WelcomeView: View {
|
|||
.onEnded { value in
|
||||
guard case .second(true, let drag?) = value else { return }
|
||||
|
||||
if drag.translation.height < 0 {
|
||||
ViewStore(store).send(.debugMenuHome)
|
||||
} else {
|
||||
if drag.translation.height > 0 {
|
||||
ViewStore(store).send(.debugMenuStartup)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue