Add Profile placeholder feature

This feature is a very basic example of combining two existing features
that can be navigated to. Aside from this it currently has no other functionality, and is
intended to exist as yet another feature that can be navigated to.
This commit is contained in:
Daniel Haight 2021-12-14 00:50:52 +00:00
parent 4166439ffa
commit c0dd6f8015
5 changed files with 185 additions and 0 deletions

View File

@ -107,6 +107,8 @@
F96B41E8273B501F0021B49A /* TransactionDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E5273B501F0021B49A /* TransactionDetailView.swift */; };
F96B41E9273B501F0021B49A /* TransactionHistoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41E6273B501F0021B49A /* TransactionHistoryView.swift */; };
F96B41EB273B50520021B49A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41EA273B50520021B49A /* Strings.swift */; };
F9971A5327680DD000A2DB75 /* Profile.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5027680DD000A2DB75 /* Profile.swift */; };
F9971A5427680DD000A2DB75 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5227680DD000A2DB75 /* ProfileView.swift */; };
F9971A5927680DDE00A2DB75 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5627680DDE00A2DB75 /* Request.swift */; };
F9971A5A27680DDE00A2DB75 /* RequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5827680DDE00A2DB75 /* RequestView.swift */; };
F9971A5F27680DF600A2DB75 /* ScanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5D27680DF600A2DB75 /* ScanView.swift */; };
@ -248,6 +250,8 @@
F96B41E5273B501F0021B49A /* TransactionDetailView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionDetailView.swift; sourceTree = "<group>"; };
F96B41E6273B501F0021B49A /* TransactionHistoryView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionHistoryView.swift; sourceTree = "<group>"; };
F96B41EA273B50520021B49A /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
F9971A5027680DD000A2DB75 /* Profile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Profile.swift; sourceTree = "<group>"; };
F9971A5227680DD000A2DB75 /* ProfileView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileView.swift; sourceTree = "<group>"; };
F9971A5627680DDE00A2DB75 /* Request.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = "<group>"; };
F9971A5827680DDE00A2DB75 /* RequestView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestView.swift; sourceTree = "<group>"; };
F9971A5D27680DF600A2DB75 /* ScanView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanView.swift; sourceTree = "<group>"; };
@ -712,6 +716,7 @@
isa = PBXGroup;
children = (
F93874EC273C4DE200F0E875 /* Home */,
F9971A4F27680DD000A2DB75 /* Profile */,
F9971A5527680DDE00A2DB75 /* Request */,
F9971A5B27680DF600A2DB75 /* Scan */,
F9C165B62740403600592F76 /* Send */,
@ -810,6 +815,23 @@
path = Views;
sourceTree = "<group>";
};
F9971A4F27680DD000A2DB75 /* Profile */ = {
isa = PBXGroup;
children = (
F9971A5027680DD000A2DB75 /* Profile.swift */,
F9971A5127680DD000A2DB75 /* Views */,
);
path = Profile;
sourceTree = "<group>";
};
F9971A5127680DD000A2DB75 /* Views */ = {
isa = PBXGroup;
children = (
F9971A5227680DD000A2DB75 /* ProfileView.swift */,
);
path = Views;
sourceTree = "<group>";
};
F9971A5527680DDE00A2DB75 /* Request */ = {
isa = PBXGroup;
children = (
@ -1113,6 +1135,7 @@
0D535FE2271F9476009A9E3E /* EnumeratedChip.swift in Sources */,
6654C73E2715A41300901167 /* OnboardingStore.swift in Sources */,
0D32281E26C5867D00262533 /* ScanQrScreen.swift in Sources */,
F9971A5327680DD000A2DB75 /* Profile.swift in Sources */,
F93874F0273C4DE200F0E875 /* HomeStore.swift in Sources */,
669FDAEB272C23C2007B9422 /* CircularFrameBadge.swift in Sources */,
0D864A0E26E1583000A61879 /* LoadingScreen.swift in Sources */,
@ -1175,6 +1198,7 @@
F96B41EB273B50520021B49A /* Strings.swift in Sources */,
0D32283226C5877A00262533 /* BalanceScreen.swift in Sources */,
0D354A0A26D5A9D000315F45 /* KeyStoring.swift in Sources */,
F9971A5427680DD000A2DB75 /* ProfileView.swift in Sources */,
0DA13CA226C1955600E3B610 /* HomeScreenViewModel.swift in Sources */,
0D32282926C586E000262533 /* RequestZcashScreenViewModel.swift in Sources */,
0D32281926C5864B00262533 /* ProfileScreen.swift in Sources */,

View File

@ -6,16 +6,19 @@ struct HomeState: Equatable {
case history
case send
case recoveryPhraseDisplay
case profile
case scan
case request
}
var transactionHistoryState: TransactionHistoryState
var profileState: ProfileState
var route: Route?
}
enum HomeAction: Equatable {
case updateRoute(HomeState.Route?)
case transactionHistory(TransactionHistoryAction)
case profile(ProfileAction)
}
// MARK: - HomeReducer
@ -33,6 +36,16 @@ extension HomeReducer {
.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, ())
}
}
}
@ -48,6 +61,14 @@ extension HomeStore {
action: HomeAction.transactionHistory
)
}
func profileStore() -> ProfileStore {
self.scope(
state: \.profileState,
action: HomeAction.profile
)
}
}
// MARK: - HomeViewStore
@ -119,6 +140,15 @@ extension HomeViewStore {
}
)
}
var showProfileBinding: Binding<Bool> {
self.binding(
get: { $0.route == .profile },
send: { isActive in
return .updateRoute(isActive ? .profile : nil)
}
)
}
}
// MARK: PlaceHolders
@ -127,6 +157,7 @@ extension HomeState {
static var placeholder: Self {
.init(
transactionHistoryState: .placeHolder,
profileState: .placeholder,
route: nil
)
}

View File

@ -32,6 +32,8 @@ struct HomeView: View {
RecoveryPhraseDisplayView(store: .demo)
case .scan:
ScanView()
case .profile:
ProfileView(store: store.profileStore())
case .request:
RequestView()
}
@ -91,6 +93,7 @@ extension HomeStore {
HomeStore(
initialState: HomeState(
transactionHistoryState: .placeHolder,
profileState: .placeholder,
route: nil
),
reducer: .default.debug(),

View File

@ -0,0 +1,81 @@
import ComposableArchitecture
import SwiftUI
struct ProfileState: Equatable {
enum Route {
case settings
case walletInfo
}
var walletInfoState: WalletInfoState
var settingsState: SettingsState
var route: Route?
}
enum ProfileAction: Equatable {
case updateRoute(ProfileState.Route?)
}
struct ProfileEnvironment {
}
// MARK: - ProfileReducer
typealias ProfileReducer = Reducer<ProfileState, ProfileAction, ProfileEnvironment>
extension ProfileReducer {
static let `default` = ProfileReducer { state, action, environment in
switch action {
case let .updateRoute(route):
state.route = route
return .none
}
}
}
// MARK: - ProfileStore
typealias ProfileStore = Store<ProfileState, ProfileAction>
extension ProfileStore {
}
// MARK: - ProfileViewStore
typealias ProfileViewStore = ViewStore<ProfileState, ProfileAction>
extension ProfileViewStore {
var routeBinding: Binding<ProfileState.Route?> {
self.binding(
get: \.route,
send: ProfileAction.updateRoute
)
}
var bindingForWalletInfo: Binding<Bool> {
self.routeBinding.map(
extract: { $0 == .walletInfo },
embed: { $0 ? .walletInfo : nil }
)
}
var bindingForSettings: Binding<Bool> {
self.routeBinding.map(
extract: { $0 == .settings },
embed: { $0 ? .settings : nil }
)
}
}
// MARK: PlaceHolders
extension ProfileState {
static var placeholder: Self {
.init(
walletInfoState: .init(),
settingsState: .init(),
route: nil
)
}
}

View File

@ -0,0 +1,46 @@
import ComposableArchitecture
import SwiftUI
struct ProfileView: View {
let store: ProfileStore
var body: some View {
WithViewStore(store) { viewStore in
List {
Text("Go To Wallet Info")
.navigationLink(
isActive: viewStore.bindingForWalletInfo,
destination: {
Text("Wallet")
}
)
Text("Go To Settings")
.navigationLink(
isActive: viewStore.bindingForSettings,
destination: {
Text("Settings")
}
)
}
.navigationTitle(Text("\(String(describing: Self.self))"))
}
}
}
struct ProfileView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ProfileView(
store: .init(
initialState: .init(
walletInfoState: .init(),
settingsState: .init()
),
reducer: .default,
environment: .init()
)
)
}
}
}