Issue #276 - [Scaffold] Drawer for the Home Screen (#275)

Drawer + transactions history

clean up

Profile button on home screen

QR, Send and Request buttons

cleanup

conflicts resolved + cleanup
This commit is contained in:
Lukas Korba 2022-04-20 18:41:32 +02:00 committed by GitHub
parent 1a16282899
commit bab53181aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 266 additions and 31 deletions

View File

@ -127,12 +127,12 @@
F96B41EB273B50520021B49A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F96B41EA273B50520021B49A /* Strings.swift */; };
F9971A4D27680DC400A2DB75 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A4A27680DC400A2DB75 /* App.swift */; };
F9971A4E27680DC400A2DB75 /* AppView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A4C27680DC400A2DB75 /* AppView.swift */; };
F9971A5327680DD000A2DB75 /* Profile.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5027680DD000A2DB75 /* Profile.swift */; };
F9971A5327680DD000A2DB75 /* ProfileStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5027680DD000A2DB75 /* ProfileStore.swift */; };
F9971A5427680DD000A2DB75 /* ProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5227680DD000A2DB75 /* ProfileView.swift */; };
F9971A5927680DDE00A2DB75 /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5627680DDE00A2DB75 /* Request.swift */; };
F9971A5927680DDE00A2DB75 /* RequestStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5627680DDE00A2DB75 /* RequestStore.swift */; };
F9971A5A27680DDE00A2DB75 /* RequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5827680DDE00A2DB75 /* RequestView.swift */; };
F9971A5F27680DF600A2DB75 /* ScanView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5D27680DF600A2DB75 /* ScanView.swift */; };
F9971A6027680DF600A2DB75 /* Scan.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5E27680DF600A2DB75 /* Scan.swift */; };
F9971A6027680DF600A2DB75 /* ScanStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A5E27680DF600A2DB75 /* ScanStore.swift */; };
F9971A6527680DFE00A2DB75 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A6227680DFE00A2DB75 /* Settings.swift */; };
F9971A6627680DFE00A2DB75 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A6427680DFE00A2DB75 /* SettingsView.swift */; };
F9971A6B27680E1000A2DB75 /* WalletInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = F9971A6827680E1000A2DB75 /* WalletInfo.swift */; };
@ -288,12 +288,12 @@
F96B41EA273B50520021B49A /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
F9971A4A27680DC400A2DB75 /* App.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
F9971A4C27680DC400A2DB75 /* AppView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppView.swift; sourceTree = "<group>"; };
F9971A5027680DD000A2DB75 /* Profile.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Profile.swift; sourceTree = "<group>"; };
F9971A5027680DD000A2DB75 /* ProfileStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProfileStore.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>"; };
F9971A5627680DDE00A2DB75 /* RequestStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RequestStore.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>"; };
F9971A5E27680DF600A2DB75 /* Scan.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scan.swift; sourceTree = "<group>"; };
F9971A5E27680DF600A2DB75 /* ScanStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ScanStore.swift; sourceTree = "<group>"; };
F9971A6227680DFE00A2DB75 /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
F9971A6427680DFE00A2DB75 /* SettingsView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
F9971A6827680E1000A2DB75 /* WalletInfo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletInfo.swift; sourceTree = "<group>"; };
@ -876,7 +876,7 @@
F9971A4F27680DD000A2DB75 /* Profile */ = {
isa = PBXGroup;
children = (
F9971A5027680DD000A2DB75 /* Profile.swift */,
F9971A5027680DD000A2DB75 /* ProfileStore.swift */,
F9971A5127680DD000A2DB75 /* Views */,
);
path = Profile;
@ -893,7 +893,7 @@
F9971A5527680DDE00A2DB75 /* Request */ = {
isa = PBXGroup;
children = (
F9971A5627680DDE00A2DB75 /* Request.swift */,
F9971A5627680DDE00A2DB75 /* RequestStore.swift */,
F9971A5727680DDE00A2DB75 /* Views */,
);
path = Request;
@ -910,8 +910,8 @@
F9971A5B27680DF600A2DB75 /* Scan */ = {
isa = PBXGroup;
children = (
F9971A5E27680DF600A2DB75 /* ScanStore.swift */,
F9971A5C27680DF600A2DB75 /* Views */,
F9971A5E27680DF600A2DB75 /* Scan.swift */,
);
path = Scan;
sourceTree = "<group>";
@ -1210,7 +1210,7 @@
0DDB6A5127737D4A0012A410 /* ValidationFailedView.swift in Sources */,
0D6D628B276A528E002FB4CC /* DropDelegate.swift in Sources */,
9E2DF99D27CF704D00649636 /* ImportSeedEditor.swift in Sources */,
F9971A5327680DD000A2DB75 /* Profile.swift in Sources */,
F9971A5327680DD000A2DB75 /* ProfileStore.swift in Sources */,
669FDAEB272C23C2007B9422 /* CircularFrameBadge.swift in Sources */,
2E8719CD27FB0D3B0082C926 /* TransactionCurrencySelector.swift in Sources */,
F9971A6C27680E1000A2DB75 /* WalletInfoView.swift in Sources */,
@ -1271,7 +1271,7 @@
F96B41EB273B50520021B49A /* Strings.swift in Sources */,
2EDA07A227EDE1AE00D6F09B /* TextFieldFooter.swift in Sources */,
F9971A5427680DD000A2DB75 /* ProfileView.swift in Sources */,
F9971A6027680DF600A2DB75 /* Scan.swift in Sources */,
F9971A6027680DF600A2DB75 /* ScanStore.swift in Sources */,
9EF8139127F191BF0075AF48 /* WalletStorageInteractor.swift in Sources */,
0DFE93E1272C9ECB000FCCA5 /* RecoveryPhraseBackupValidationView.swift in Sources */,
9E69A24D27FB002800A55317 /* Welcome.swift in Sources */,
@ -1283,7 +1283,7 @@
2E8719CB27FB09990082C926 /* TransactionTextField.swift in Sources */,
6654C7412715A47300901167 /* Onboarding.swift in Sources */,
F9C165C42740403600592F76 /* SentView.swift in Sources */,
F9971A5927680DDE00A2DB75 /* Request.swift in Sources */,
F9971A5927680DDE00A2DB75 /* RequestStore.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -2,9 +2,21 @@ import ComposableArchitecture
import SwiftUI
struct HomeState: Equatable {
enum Route: Equatable {
case profile
case request
case send
case scan
}
var arePublishersPrepared = false
var route: Route?
var drawerOverlay: DrawerOverlay
var profileState: ProfileState
var requestState: RequestState
var sendState: SendState
var scanState: ScanState
var totalBalance: Double
var transactionHistoryState: TransactionHistoryState
var verifiedBalance: Double
@ -13,9 +25,14 @@ struct HomeState: Equatable {
enum HomeAction: Equatable {
case debugMenuStartup
case preparePublishers
case profile(ProfileAction)
case request(RequestAction)
case send(SendAction)
case scan(ScanAction)
case transactionHistory(TransactionHistoryAction)
case updateBalance(Balance)
case updateDrawer(DrawerOverlay)
case updateRoute(HomeState.Route?)
}
struct HomeEnvironment {
@ -58,10 +75,48 @@ extension HomeReducer {
.default
.run(&state.transactionHistoryState, historyAction, ())
.map(HomeAction.transactionHistory)
case .updateRoute(let route):
state.route = route
return .none
case .profile(let action):
return .none
case .request(let action):
return .none
case .send(let action):
return .none
case .scan(let action):
return .none
}
}
}
// MARK: - HomeViewStore
typealias HomeViewStore = ViewStore<HomeState, HomeAction>
extension HomeViewStore {
func bindingForRoute(_ route: HomeState.Route) -> Binding<Bool> {
self.binding(
get: { $0.route == route },
send: { isActive in
return .updateRoute(isActive ? route : nil)
}
)
}
func bindingForDrawer() -> Binding<DrawerOverlay> {
self.binding(
get: { $0.drawerOverlay },
send: { .updateDrawer($0) }
)
}
}
// MARK: - HomeStore
typealias HomeStore = Store<HomeState, HomeAction>
@ -73,17 +128,32 @@ extension HomeStore {
action: HomeAction.transactionHistory
)
}
}
func profileStore() -> ProfileStore {
self.scope(
state: \.profileState,
action: HomeAction.profile
)
}
// MARK: - HomeViewStore
func requestStore() -> RequestStore {
self.scope(
state: \.requestState,
action: HomeAction.request
)
}
typealias HomeViewStore = ViewStore<HomeState, HomeAction>
func sendStore() -> SendStore {
self.scope(
state: \.sendState,
action: HomeAction.send
)
}
extension HomeViewStore {
func bindingForDrawer() -> Binding<DrawerOverlay> {
self.binding(
get: { $0.drawerOverlay },
send: { .updateDrawer($0) }
func scanStore() -> ScanStore {
self.scope(
state: \.scanState,
action: HomeAction.scan
)
}
}
@ -94,6 +164,10 @@ extension HomeState {
static var placeholder: Self {
.init(
drawerOverlay: .partial,
profileState: .placeholder,
requestState: .placeholder,
sendState: .placeholder,
scanState: .placeholder,
totalBalance: 0.0,
transactionHistoryState: .placeHolder,
verifiedBalance: 0.0

View File

@ -8,12 +8,21 @@ struct HomeView: View {
WithViewStore(store) { viewStore in
GeometryReader { proxy in
ZStack {
scanButton(viewStore)
profileButton(viewStore)
sendButton(viewStore)
requestButton(viewStore)
.padding(.top, 140)
VStack {
Text("totalBalance \(viewStore.totalBalance)")
Text("verifiedBalance \(viewStore.verifiedBalance)")
Text("balance: \(viewStore.totalBalance)")
.accessDebugMenuWithHiddenGesture {
viewStore.send(.debugMenuStartup)
}
.padding(.top, 180)
Spacer()
}
@ -29,8 +38,115 @@ struct HomeView: View {
}
}
.applyScreenBackground()
.navigationBarHidden(true)
.applyScreenBackground()
.onAppear(perform: { viewStore.send(.preparePublishers) })
}
.onAppear(perform: { viewStore.send(.preparePublishers) })
}
}
}
// MARK: - Buttons
extension HomeView {
func profileButton(_ viewStore: HomeViewStore) -> some View {
VStack {
HStack {
Spacer()
Image(Asset.Assets.Icons.profile.name)
.resizable()
.frame(width: 60, height: 60)
.padding(.trailing, 15)
.navigationLink(
isActive: viewStore.bindingForRoute(.profile),
destination: {
ProfileView(store: store.profileStore())
}
)
}
Spacer()
}
}
func requestButton(_ viewStore: HomeViewStore) -> some View {
VStack {
Spacer()
Text("home.request")
.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.secondaryButtonText.color)
.background(Asset.Colors.Buttons.secondaryButton.color)
.cornerRadius(12)
.frame(height: 60)
.padding(.horizontal, 50)
.neumorphicButton()
.navigationLink(
isActive: viewStore.bindingForRoute(.request),
destination: {
RequestView(store: store.requestStore())
}
)
Spacer()
}
}
func sendButton(_ viewStore: HomeViewStore) -> some View {
VStack {
Spacer()
Text("Send")
.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.bindingForRoute(.send),
destination: {
SendView(store: store.sendStore())
}
)
Spacer()
}
}
func scanButton(_ viewStore: HomeViewStore) -> some View {
VStack {
HStack {
Image(Asset.Assets.Icons.qrCode.name)
.resizable()
.frame(width: 40, height: 40)
.padding(.top, 7)
.padding(.leading, 22)
.navigationLink(
isActive: viewStore.bindingForRoute(.scan),
destination: {
ScanView(store: store.scanStore())
}
)
Spacer()
}
Spacer()
}
}
}
@ -54,5 +170,10 @@ struct HomeView_Previews: PreviewProvider {
NavigationView {
HomeView(store: .placeholder)
}
NavigationView {
HomeView(store: .placeholder)
.preferredColorScheme(.dark)
}
}
}

View File

@ -7,7 +7,7 @@ enum RequestAction: Equatable {
case noOp
}
struct RequestEnvironment: Equatable {
struct RequestEnvironment {
}
// MARK: - RequestReducer
@ -28,6 +28,11 @@ extension RequestReducer {
typealias RequestStore = Store<RequestState, RequestAction>
extension RequestStore {
static let placeholder = RequestStore(
initialState: .placeholder,
reducer: .default,
environment: RequestEnvironment()
)
}
// MARK: - RequestViewStore
@ -36,3 +41,11 @@ typealias RequestViewStore = ViewStore<RequestState, RequestAction>
extension RequestViewStore {
}
// MARK: PlaceHolders
extension RequestState {
static var placeholder: Self {
.init()
}
}

View File

@ -1,13 +1,18 @@
import SwiftUI
import ComposableArchitecture
struct RequestView: View {
let store: RequestStore
var body: some View {
Text("\(String(describing: Self.self)) PlaceHolder")
WithViewStore(store) { _ in
Text("\(String(describing: Self.self)) PlaceHolder")
}
}
}
struct RequestView_Previews: PreviewProvider {
static var previews: some View {
RequestView()
RequestView(store: .placeholder)
}
}

View File

@ -32,11 +32,11 @@ struct SandboxView: View {
case .recoveryPhraseDisplay:
RecoveryPhraseDisplayView(store: .demo)
case .scan:
ScanView()
ScanView(store: .placeholder)
case .profile:
ProfileView(store: store.profileStore())
case .request:
RequestView()
RequestView(store: .placeholder)
}
}

View File

@ -7,7 +7,7 @@ enum ScanAction: Equatable {
case noOp
}
struct ScanEnvironment: Equatable {
struct ScanEnvironment {
}
// MARK: - ScanReducer
@ -28,6 +28,11 @@ extension ScanReducer {
typealias ScanStore = Store<ScanState, ScanAction>
extension ScanStore {
static let placeholder = ScanStore(
initialState: .placeholder,
reducer: .default,
environment: ScanEnvironment()
)
}
// MARK: - ScanViewStore
@ -36,3 +41,11 @@ typealias ScanViewStore = ViewStore<ScanState, ScanAction>
extension ScanViewStore {
}
// MARK: PlaceHolders
extension ScanState {
static var placeholder: Self {
.init()
}
}

View File

@ -1,13 +1,18 @@
import SwiftUI
import ComposableArchitecture
struct ScanView: View {
let store: ScanStore
var body: some View {
Text("\(String(describing: Self.self)) PlaceHolder")
WithViewStore(store) { _ in
Text("\(String(describing: Self.self)) PlaceHolder")
}
}
}
struct ScanView_Previews: PreviewProvider {
static var previews: some View {
ScanView()
ScanView(store: .placeholder)
}
}

View File

@ -55,7 +55,11 @@
"importWallet.button.importPhrase" = "Import Recovery Phrase";
"importWallet.button.importPrivateKey" = "Import a private or viewing key";
// MARK: - Home Screen
"home.request" = "Request ZEC";
// MARK: - Common & Shared
"Back" = "Back";
"Skip" = "Skip";
"Next" = "Next";
"Send" = "Send";