Step 6: sell and request screen scaffold

This commit is contained in:
Francisco Gindre 2021-02-24 22:44:38 -03:00
parent 614d3ea5e8
commit c4bea8c3f1
10 changed files with 354 additions and 103 deletions

View File

@ -260,3 +260,88 @@ struct HomeScreen: View {
} }
```` ````
## Tag: `step-6-Sell-Screen`
We are going to create a sell screen where we will generate a QR code with our address and some instructions for our customer to send us the requested ZEC along some memo.
We are going to move some other elements to the SettingsView, and Create a form in the `SellScreen` view where we will request some amount and enter an order code, that will be shown on the request screen so that the user types that code in the transaction memo.
````
/// SellScreen.swift
var body: some View {
NavigationView {
ZStack {
ZcashBackground()
VStack(alignment: .center, spacing: 20) {
ZcashLogo(width: 50)
Spacer()
ZcashTextField(title: "Zec Amount To Request",
subtitleView: amountSubtitle,
contentType: nil,
keyboardType: .numberPad,
binding: $numberString,
action: nil,
accessoryIcon: nil,
onEditingChanged: { _ in }, onCommit: {})
ZcashTextField(title: "Order Code",
subtitleView: codeSubtitle,
binding: $orderCode) { _ in } onCommit: {}
````
We are going to create the Request Screen. It will allow the user to see the information needed to create the transaction
````
struct RequestZec: View {
@EnvironmentObject var model: ZcashPoSModel
@State var zAddress: String? = nil
@State var alertType: AlertType? = nil
var body: some View {
ZStack {
ZcashBackground()
VStack(alignment: .center, spacing: 40){
Text("To This address:")
.foregroundColor(.white)
Text(zAddress ?? "Error Deriving Address")
.foregroundColor(.white)
Text("$\(model.request.amount.toZecAmount())")
.lineLimit(1)
.minimumScaleFactor(0.5)
.foregroundColor(.white)
.font(
.custom("Zboto", size: 72)
)
Text("Append Memo With this Code")
.foregroundColor(.white)
Text(model.request.code)
.foregroundColor(.white)
.font(.title)
}
}.navigationTitle("Pay with ZEC")
````
The interesting part is this: We can derive a Z-Address from viewing key!
We can do this and many more things with the `DerivationTool` class of the Zcash SDK.
````
.onAppear() {
do {
guard let ivk = model.viewingKey else {
self.alertType = .errorAlert(ZcashPoSModel.PoSError.unableToRetrieveCredentials)
return
}
self.zAddress = try DerivationTool.default.deriveShieldedAddress(viewingKey: ivk)
} catch {
self.alertType = .errorAlert(error)
}
}
````
Unfortunately this screen is really helpful. we need to get some QR code so that the user can scan the address! We will see that on the next step

View File

@ -13,6 +13,8 @@
0D08DE7325E6FE4B00E08533 /* SellScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DE7225E6FE4B00E08533 /* SellScreen.swift */; }; 0D08DE7325E6FE4B00E08533 /* SellScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DE7225E6FE4B00E08533 /* SellScreen.swift */; };
0D08DE7625E7077F00E08533 /* ReceivedTransactions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DE7525E7077F00E08533 /* ReceivedTransactions.swift */; }; 0D08DE7625E7077F00E08533 /* ReceivedTransactions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DE7525E7077F00E08533 /* ReceivedTransactions.swift */; };
0D08DEAA25E70D8400E08533 /* SettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DEA925E70D8400E08533 /* SettingsScreen.swift */; }; 0D08DEAA25E70D8400E08533 /* SettingsScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DEA925E70D8400E08533 /* SettingsScreen.swift */; };
0D08DEAD25E71D4500E08533 /* RequestZec.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D08DEAC25E71D4500E08533 /* RequestZec.swift */; };
0D08DEB025E732C900E08533 /* Zboto.otf in Resources */ = {isa = PBXBuildFile; fileRef = 0D08DEAF25E732C900E08533 /* Zboto.otf */; };
0D475B2125E3ED600067978E /* CombineSynchronizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D475B2025E3ED600067978E /* CombineSynchronizer.swift */; }; 0D475B2125E3ED600067978E /* CombineSynchronizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D475B2025E3ED600067978E /* CombineSynchronizer.swift */; };
0D475B2725E3EEE10067978E /* DetailModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D475B2625E3EEE10067978E /* DetailModel.swift */; }; 0D475B2725E3EEE10067978E /* DetailModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D475B2625E3EEE10067978E /* DetailModel.swift */; };
0D475B2A25E3F04C0067978E /* String+Zcash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D475B2925E3F04C0067978E /* String+Zcash.swift */; }; 0D475B2A25E3F04C0067978E /* String+Zcash.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D475B2925E3F04C0067978E /* String+Zcash.swift */; };
@ -47,6 +49,8 @@
0D08DE7225E6FE4B00E08533 /* SellScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SellScreen.swift; sourceTree = "<group>"; }; 0D08DE7225E6FE4B00E08533 /* SellScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SellScreen.swift; sourceTree = "<group>"; };
0D08DE7525E7077F00E08533 /* ReceivedTransactions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceivedTransactions.swift; sourceTree = "<group>"; }; 0D08DE7525E7077F00E08533 /* ReceivedTransactions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReceivedTransactions.swift; sourceTree = "<group>"; };
0D08DEA925E70D8400E08533 /* SettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreen.swift; sourceTree = "<group>"; }; 0D08DEA925E70D8400E08533 /* SettingsScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsScreen.swift; sourceTree = "<group>"; };
0D08DEAC25E71D4500E08533 /* RequestZec.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestZec.swift; sourceTree = "<group>"; };
0D08DEAF25E732C900E08533 /* Zboto.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Zboto.otf; sourceTree = "<group>"; };
0D475B2025E3ED600067978E /* CombineSynchronizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombineSynchronizer.swift; sourceTree = "<group>"; }; 0D475B2025E3ED600067978E /* CombineSynchronizer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CombineSynchronizer.swift; sourceTree = "<group>"; };
0D475B2625E3EEE10067978E /* DetailModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailModel.swift; sourceTree = "<group>"; }; 0D475B2625E3EEE10067978E /* DetailModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailModel.swift; sourceTree = "<group>"; };
0D475B2925E3F04C0067978E /* String+Zcash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Zcash.swift"; sourceTree = "<group>"; }; 0D475B2925E3F04C0067978E /* String+Zcash.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "String+Zcash.swift"; sourceTree = "<group>"; };
@ -116,6 +120,7 @@
0D08DE7225E6FE4B00E08533 /* SellScreen.swift */, 0D08DE7225E6FE4B00E08533 /* SellScreen.swift */,
0D08DE7525E7077F00E08533 /* ReceivedTransactions.swift */, 0D08DE7525E7077F00E08533 /* ReceivedTransactions.swift */,
0D08DEA925E70D8400E08533 /* SettingsScreen.swift */, 0D08DEA925E70D8400E08533 /* SettingsScreen.swift */,
0D08DEAC25E71D4500E08533 /* RequestZec.swift */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@ -141,6 +146,7 @@
0D5050A625DFEFAC00E7A697 /* accept-zcash-poc */ = { 0D5050A625DFEFAC00E7A697 /* accept-zcash-poc */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
0D08DEAF25E732C900E08533 /* Zboto.otf */,
0D08DE6825E6C29600E08533 /* sapling-output.params */, 0D08DE6825E6C29600E08533 /* sapling-output.params */,
0D08DE6925E6C29700E08533 /* sapling-spend.params */, 0D08DE6925E6C29700E08533 /* sapling-spend.params */,
0D475B2525E3EEBE0067978E /* Model */, 0D475B2525E3EEBE0067978E /* Model */,
@ -273,6 +279,7 @@
0D08DE6A25E6C29700E08533 /* sapling-output.params in Resources */, 0D08DE6A25E6C29700E08533 /* sapling-output.params in Resources */,
0D5050AF25DFEFAD00E7A697 /* Preview Assets.xcassets in Resources */, 0D5050AF25DFEFAD00E7A697 /* Preview Assets.xcassets in Resources */,
0D5050AC25DFEFAD00E7A697 /* Assets.xcassets in Resources */, 0D5050AC25DFEFAD00E7A697 /* Assets.xcassets in Resources */,
0D08DEB025E732C900E08533 /* Zboto.otf in Resources */,
0D08DE6B25E6C29700E08533 /* sapling-spend.params in Resources */, 0D08DE6B25E6C29700E08533 /* sapling-spend.params in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -332,6 +339,7 @@
0D5051C125E0797C00E7A697 /* ZcashButtonBackground.swift in Sources */, 0D5051C125E0797C00E7A697 /* ZcashButtonBackground.swift in Sources */,
0DC0819725E53E690028532F /* HomeScreen.swift in Sources */, 0DC0819725E53E690028532F /* HomeScreen.swift in Sources */,
0D475B3325E3F4910067978E /* ZcashEnvironment.swift in Sources */, 0D475B3325E3F4910067978E /* ZcashEnvironment.swift in Sources */,
0D08DEAD25E71D4500E08533 /* RequestZec.swift in Sources */,
0D50519A25E0591B00E7A697 /* ZcashBackground.swift in Sources */, 0D50519A25E0591B00E7A697 /* ZcashBackground.swift in Sources */,
0D5051B625E076BA00E7A697 /* KeyboardResponder.swift in Sources */, 0D5051B625E076BA00E7A697 /* KeyboardResponder.swift in Sources */,
0D08DE7625E7077F00E08533 /* ReceivedTransactions.swift in Sources */, 0D08DE7625E7077F00E08533 /* ReceivedTransactions.swift in Sources */,

View File

@ -46,5 +46,9 @@
<string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string> <string>UIInterfaceOrientationLandscapeRight</string>
</array> </array>
<key>UIAppFonts</key>
<array>
<string>Zboto.otf</string>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -10,9 +10,6 @@ import SwiftUI
struct ZcashLogo: View { struct ZcashLogo: View {
var fillGradient: LinearGradient { var fillGradient: LinearGradient {
LinearGradient(gradient: Gradient( LinearGradient(gradient: Gradient(
colors: [Color.zAmberGradient1, colors: [Color.zAmberGradient1,
@ -22,25 +19,18 @@ struct ZcashLogo: View {
endPoint: UnitPoint(x: 0.5, y: 1.0)) endPoint: UnitPoint(x: 0.5, y: 1.0))
} }
var width: CGFloat = 100
var body: some View { var body: some View {
ZStack { ZcashSymbol()
.fill(fillGradient)
.frame(width: width, height: width * 1.05, alignment: .center)
.padding(width * 0.3)
.overlay( Ring()
.stroke(lineWidth: width * 0.14)
.fill(fillGradient)
Ring() )
.stroke(lineWidth: 14)
.fill(fillGradient)
.frame(width: 167, height: 167, alignment: .center)
.padding(20)
VStack (alignment: .center) {
ZcashSymbol()
.fill(fillGradient)
.frame(width: 100, height: 105, alignment: .center)
}
}
} }
} }

View File

@ -15,20 +15,23 @@ struct HomeScreen: View {
var body: some View { var body: some View {
TabView { TabView(selection: $model.tabSelection) {
SellScreen() SellScreen()
.tabItem { .tabItem {
Label("Sell", systemImage: "shield") Label("Sell", systemImage: "shield")
} }
.tag(AppNavigation.Tab.sell)
ReceivedTransactions() ReceivedTransactions()
.tabItem { .tabItem {
Label("History", systemImage: "square.and.pencil") Label("History", systemImage: "square.and.pencil")
} }
.tag(AppNavigation.Tab.received)
SettingsScreen() SettingsScreen()
.tabItem { .tabItem {
Label("Settings", systemImage: "list.dash") Label("Settings", systemImage: "list.dash")
} }
.tag(AppNavigation.Tab.settings)
} }

View File

@ -0,0 +1,71 @@
//
// RequestZec.swift
// accept-zcash-poc
//
// Created by Francisco Gindre on 2/24/21.
//
import SwiftUI
import ZcashLightClientKit
struct RequestZec: View {
@EnvironmentObject var model: ZcashPoSModel
@State var zAddress: String? = nil
@State var alertType: AlertType? = nil
var body: some View {
ZStack {
ZcashBackground()
VStack(alignment: .center, spacing: 40){
Text("To This address:")
.foregroundColor(.white)
Text(zAddress ?? "Error Deriving Address")
.foregroundColor(.white)
Text("$\(model.request.amount.toZecAmount())")
.lineLimit(1)
.minimumScaleFactor(0.5)
.foregroundColor(.white)
.font(
.custom("Zboto", size: 72)
)
Text("Append Memo With this Code")
.foregroundColor(.white)
Text(model.request.code)
.foregroundColor(.white)
.font(.title)
}
}.navigationTitle("Pay with ZEC")
.onAppear() {
do {
guard let ivk = model.viewingKey else {
self.alertType = .errorAlert(ZcashPoSModel.PoSError.unableToRetrieveCredentials)
return
}
self.zAddress = try DerivationTool.default.deriveShieldedAddress(viewingKey: ivk)
} catch {
self.alertType = .errorAlert(error)
}
}
.alert(item: $alertType) { t in
t.buildAlert()
}
}
}
struct RequestZec_Previews: PreviewProvider {
static var previews: some View {
RequestZec()
}
}
extension ZcashPoSModel {
var request: ZECRequest {
self.currentPayment ?? ZECRequest.nullRequest
}
}
extension ZcashPoSModel.ZECRequest {
static var nullRequest: Self {
Self(amount: 0, code: "NO CODE")
}
}

View File

@ -9,75 +9,106 @@ import SwiftUI
import ZcashLightClientKit import ZcashLightClientKit
struct SellScreen: View { struct SellScreen: View {
enum Status {
case ready
case syncing
case offline
}
@EnvironmentObject var model: ZcashPoSModel @EnvironmentObject var model: ZcashPoSModel
@Environment(\.zcashEnvironment) var zcash: ZcashEnvironment @Environment(\.zcashEnvironment) var zcash: ZcashEnvironment
@State var alertType: AlertType? = nil @State var alertType: AlertType? = nil
@State var status: Status = .offline @State var numberString: String = ""
@State var progress: Int = 0 @State var orderCode: String = ""
@State var height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT @State var navigation: AppNavigation.Screen? = nil
var body: some View { var body: some View {
ZStack { NavigationView {
ZcashBackground() ZStack {
VStack(alignment: .center, spacing: 20) { ZcashBackground()
ZcashLogo() VStack(alignment: .center, spacing: 20) {
switch status { ZcashLogo(width: 50)
case .offline:
Button(action: { Spacer()
start() ZcashTextField(title: "Zec Amount To Request",
}) { subtitleView: amountSubtitle,
Text("Offline - Tap to Start").foregroundColor(.white) contentType: nil,
keyboardType: .numberPad,
binding: $numberString,
action: nil,
accessoryIcon: nil,
onEditingChanged: { _ in }, onCommit: {})
ZcashTextField(title: "Order Code",
subtitleView: codeSubtitle,
binding: $orderCode) { _ in } onCommit: {}
NavigationLink(destination: AppNavigation.Screen.request.buildScreen().environmentObject(model), tag: AppNavigation.Screen.request, selection: $model.navigation) {
Button(action: {
guard let amount = NumberFormatter.zecAmountFormatter.number(from: numberString)?.doubleValue,
validOrderCode else {
self.alertType = AlertType.message("Invalid values!")
return
}
model.currentPayment = ZcashPoSModel.ZECRequest(amount: amount, code: orderCode)
model.navigation = .request
}) {
Text("Request ZEC")
.foregroundColor(.black)
.zcashButtonBackground(shape: .rounded(fillStyle: .gradient(gradient: .zButtonGradient)))
.frame(height: 48)
}
.disabled(!validForm)
.opacity(validForm ? 1.0 : 0.6)
} }
case .ready:
Text("Ready! Yay!").foregroundColor(.white)
case .syncing:
Text("Syncing \(progress)% Block: \(height)").foregroundColor(.white)
} }
.padding(20)
} }
.onReceive(zcash.synchronizer.progress) { (p) in .keyboardAdaptive()
self.progress = Int(p * 100) .navigationBarTitle(Text("Zcash PoS"), displayMode: .inline)
.navigationBarHidden(false)
.onAppear() {
_zECCWalletNavigationBarLookTweaks()
} }
.onReceive(zcash.synchronizer.syncBlockHeight) { (h) in .alert(item: $alertType) { (type) -> Alert in
self.height = h type.buildAlert()
}
}.onReceive(zcash.synchronizer.status) { (s) in
switch s {
case .disconnected, .stopped:
self.status = .offline
case .synced:
self.status = .ready
case .syncing:
self.status = .syncing
} }
} }
.navigationBarTitle(Text("Zcash PoS"), displayMode: .inline)
.navigationBarHidden(false)
.onAppear() {
_zECCWalletNavigationBarLookTweaks()
start()
}
.alert(item: $alertType) { (type) -> Alert in
type.buildAlert()
}
} }
func start() { var amountSubtitle: AnyView {
do { AnyView(
guard let ivk = model.viewingKey, let bday = model.birthday else { Text(validAmount ? "This is a valid amount" : "Invalid Zec amount")
throw ZcashPoSModel.PoSError.unableToRetrieveCredentials .foregroundColor(.white)
} .font(.caption)
try self.zcash.synchronizer.initializer.initialize(viewingKeys: [ivk], walletBirthday: bday) )
try self.zcash.synchronizer.start()
} catch {
self.alertType = AlertType.errorAlert(error)
}
} }
var codeSubtitle: AnyView {
AnyView(
Text(validOrderCode ? "Valid Order code" : "Please enter an order code")
.foregroundColor(.white)
.font(.caption)
)
}
var validAmount: Bool {
guard let amount = NumberFormatter.zecAmountFormatter.number(from: numberString)?.doubleValue else {
return false
}
return amount > 0
}
var validOrderCode: Bool {
!orderCode.isEmpty && orderCode.count < 6
}
var validForm: Bool {
guard validAmount,
validOrderCode else {
return false
}
return true
}
} }
struct SellScreen_Previews: PreviewProvider { struct SellScreen_Previews: PreviewProvider {

View File

@ -6,18 +6,36 @@
// //
import SwiftUI import SwiftUI
import ZcashLightClientKit
struct SettingsScreen: View { struct SettingsScreen: View {
enum Status {
case ready
case syncing
case offline
}
@EnvironmentObject var model: ZcashPoSModel @EnvironmentObject var model: ZcashPoSModel
@Environment(\.zcashEnvironment) var zcash: ZcashEnvironment @Environment(\.zcashEnvironment) var zcash: ZcashEnvironment
@State var status: Status = .offline
@State var progress: Int = 0
@State var height: BlockHeight = ZcashSDK.SAPLING_ACTIVATION_HEIGHT
@State var alertType: AlertType? = nil
var body: some View { var body: some View {
ZStack { ZStack {
ZcashBackground() ZcashBackground()
VStack { VStack {
ZcashLogo() ZcashLogo()
Text("This is where the settings would be") switch status {
.foregroundColor(.white) case .offline:
Button(action: {
start()
}) {
Text("Offline - Tap to Start").foregroundColor(.white)
}
case .ready:
Text("Ready! Yay!").foregroundColor(.white)
case .syncing:
Text("Syncing \(progress)% Block: \(height)").foregroundColor(.white)
}
Button(action: { Button(action: {
zcash.synchronizer.stop() zcash.synchronizer.stop()
model.nuke() model.nuke()
@ -30,8 +48,34 @@ struct SettingsScreen: View {
} }
} }
} }
.onReceive(zcash.synchronizer.progress) { (p) in
self.progress = Int(p * 100)
}
.onReceive(zcash.synchronizer.syncBlockHeight) { (h) in
self.height = h
}.onReceive(zcash.synchronizer.status) { (s) in
switch s {
case .disconnected, .stopped:
self.status = .offline
case .synced:
self.status = .ready
case .syncing:
self.status = .syncing
}
}
} }
func start() {
do {
guard let ivk = model.viewingKey, let bday = model.birthday else {
throw ZcashPoSModel.PoSError.unableToRetrieveCredentials
}
try self.zcash.synchronizer.initializer.initialize(viewingKeys: [ivk], walletBirthday: bday)
try self.zcash.synchronizer.start()
} catch {
self.alertType = AlertType.errorAlert(error)
}
}
} }
struct SettingsScreen_Previews: PreviewProvider { struct SettingsScreen_Previews: PreviewProvider {

BIN
accept-zcash-poc/Zboto.otf Normal file

Binary file not shown.

View File

@ -16,14 +16,12 @@ struct accept_zcash_pocApp: App {
var body: some Scene { var body: some Scene {
WindowGroup { WindowGroup {
// we can navigate now!
NavigationView {
// and we need to check what our main screen will be. Is it an empty or an already initialized app?
model.initialScreen()
.environmentObject(model)
.zcashEnvironment(ZcashEnvironment.default)
} //we need to check what our main screen will be. Is it an empty or an already initialized app?
model.initialScreen()
.environmentObject(model)
.zcashEnvironment(ZcashEnvironment.default)
} }
} }
} }
@ -36,9 +34,16 @@ class ZcashPoSModel: ObservableObject {
case failedToStart(error: Error) case failedToStart(error: Error)
case unableToRetrieveCredentials case unableToRetrieveCredentials
} }
@Published var tabSelection: AppNavigation.Tab = .history
@Published var status = AppNavigation.AppStatus.current struct ZECRequest {
var amount: Double
var code: String
}
@Published var tabSelection: AppNavigation.Tab = .sell
@Published var status = AppNavigation.AppStatus.empty
@Published var navigation: AppNavigation.Screen? = nil @Published var navigation: AppNavigation.Screen? = nil
@Published var currentPayment: ZECRequest? = nil
@AppStorage("viewingKey") var viewingKey: String? @AppStorage("viewingKey") var viewingKey: String?
@AppStorage("walletBirthday") var birthday: BlockHeight? @AppStorage("walletBirthday") var birthday: BlockHeight?
@ -50,11 +55,13 @@ class ZcashPoSModel: ObservableObject {
return .initialized return .initialized
} }
@ViewBuilder func initialScreen() -> some View{ @ViewBuilder func initialScreen() -> some View{
switch appStatus { switch appStatus {
case .empty: case .empty:
ImportViewingKey() NavigationView {
ImportViewingKey()
}
case .initialized: case .initialized:
HomeScreen() HomeScreen()
} }
@ -71,27 +78,35 @@ struct AppNavigation {
enum AppStatus { enum AppStatus {
case empty case empty
case initialized case initialized
static var current: AppStatus {
.empty
}
} }
enum Tab { enum Tab {
case receive case sell
case history case received
case settings
} }
enum Screen { enum Screen {
case importViewingKey case importViewingKey
case home case home
case receivedTransaction
case settings
case sell
case request
@ViewBuilder func buildScreen() -> some View { @ViewBuilder func buildScreen() -> some View {
switch self { switch self {
case .importViewingKey: case .importViewingKey:
ImportViewingKey() ImportViewingKey()
case .home: case .home:
HomeScreen() HomeScreen()
case .receivedTransaction:
ReceivedTransactions()
case .settings:
SettingsScreen()
case .request:
RequestZec()
case .sell:
SellScreen()
} }
} }
} }