Mid Hack Demo

This commit is contained in:
Francisco Gindre 2020-06-26 12:45:19 -03:00
parent 3abd221b82
commit 2b49d85683
25 changed files with 695 additions and 133 deletions

View File

@ -14,16 +14,17 @@
0D11D3D4249D05D800223146 /* Wedge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11D3D3249D05D800223146 /* Wedge.swift */; };
0D11D3D7249D2F0B00223146 /* ZircleProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11D3D6249D2F0B00223146 /* ZircleProgress.swift */; };
0D11D3D9249D51FC00223146 /* ZircleTextField_Preview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11D3D8249D51FC00223146 /* ZircleTextField_Preview.swift */; };
0D11D3DB249D5F1600223146 /* ProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11D3DA249D5F1600223146 /* ProgressBar.swift */; };
0D11D3DB249D5F1600223146 /* NeumorphicProgressBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11D3DA249D5F1600223146 /* NeumorphicProgressBar.swift */; };
0D11D3DD249D81B900223146 /* Pie.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D11D3DC249D81B900223146 /* Pie.swift */; };
0D1366AC24991A6000F0EB54 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1366AB24991A6000F0EB54 /* AppDelegate.swift */; };
0D1366AE24991A6000F0EB54 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1366AD24991A6000F0EB54 /* SceneDelegate.swift */; };
0D1366B024991A6000F0EB54 /* SplashScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1366AF24991A6000F0EB54 /* SplashScreen.swift */; };
0D1366B024991A6000F0EB54 /* HomeScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1366AF24991A6000F0EB54 /* HomeScreen.swift */; };
0D1366B224991A6100F0EB54 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0D1366B124991A6100F0EB54 /* Assets.xcassets */; };
0D1366B524991A6100F0EB54 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0D1366B424991A6100F0EB54 /* Preview Assets.xcassets */; };
0D1366B824991A6100F0EB54 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0D1366B624991A6100F0EB54 /* LaunchScreen.storyboard */; };
0D1366C324991A6200F0EB54 /* ZirclesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1366C224991A6200F0EB54 /* ZirclesTests.swift */; };
0D1366CE24991A6200F0EB54 /* ZirclesUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D1366CD24991A6200F0EB54 /* ZirclesUITests.swift */; };
0D3FB6FE24A4CD4E0034A52A /* MockEnvironment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D3FB6FD24A4CD4E0034A52A /* MockEnvironment.swift */; };
0D5142C324A0F0B800F9AE2E /* Zboto.otf in Resources */ = {isa = PBXBuildFile; fileRef = 0D5142C224A0F0B800F9AE2E /* Zboto.otf */; };
0D5142C624A14D0F00F9AE2E /* CreateNewZircleNameView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D5142C524A14D0F00F9AE2E /* CreateNewZircleNameView.swift */; };
0D5142C824A16F9600F9AE2E /* CreateNewTypeOfZircle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D5142C724A16F9600F9AE2E /* CreateNewTypeOfZircle.swift */; };
@ -48,6 +49,11 @@
0D6A22C7249AB36100B4E946 /* ZcashButtonBackground.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D6A22C6249AB36100B4E946 /* ZcashButtonBackground.swift */; };
0D6A22C9249AB3CA00B4E946 /* ZcashButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D6A22C8249AB3CA00B4E946 /* ZcashButton.swift */; };
0D6A22CB249AB61200B4E946 /* Glow_Preview.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0D6A22CA249AB61200B4E946 /* Glow_Preview.swift */; };
0DB5330F24A623AF0090D722 /* sapling-spend.params in Resources */ = {isa = PBXBuildFile; fileRef = 0DB5330D24A623AF0090D722 /* sapling-spend.params */; };
0DB5331024A623AF0090D722 /* sapling-output.params in Resources */ = {isa = PBXBuildFile; fileRef = 0DB5330E24A623AF0090D722 /* sapling-output.params */; };
0DB5331224A6413D0090D722 /* LazyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DB5331124A6413D0090D722 /* LazyView.swift */; };
0DD7278924A5532300C36D27 /* AllZirclesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DD7278824A5532300C36D27 /* AllZirclesView.swift */; };
0DD7278B24A564AF00C36D27 /* ZircleListCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DD7278A24A564AF00C36D27 /* ZircleListCard.swift */; };
0DEE59A824A24B7300447C15 /* WelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEE59A724A24B7300447C15 /* WelcomeView.swift */; };
0DEE59AA24A2B90F00447C15 /* CreateNewZircleDescription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0DEE59A924A2B90F00447C15 /* CreateNewZircleDescription.swift */; };
450B0C2B71526C48C265CB70 /* Pods_Zircles.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 897CFDF9BD39874744EF71AB /* Pods_Zircles.framework */; };
@ -78,12 +84,12 @@
0D11D3D3249D05D800223146 /* Wedge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wedge.swift; sourceTree = "<group>"; };
0D11D3D6249D2F0B00223146 /* ZircleProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZircleProgress.swift; sourceTree = "<group>"; };
0D11D3D8249D51FC00223146 /* ZircleTextField_Preview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZircleTextField_Preview.swift; sourceTree = "<group>"; };
0D11D3DA249D5F1600223146 /* ProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressBar.swift; sourceTree = "<group>"; };
0D11D3DA249D5F1600223146 /* NeumorphicProgressBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NeumorphicProgressBar.swift; sourceTree = "<group>"; };
0D11D3DC249D81B900223146 /* Pie.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Pie.swift; sourceTree = "<group>"; };
0D1366A824991A6000F0EB54 /* Zircles.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Zircles.app; sourceTree = BUILT_PRODUCTS_DIR; };
0D1366AB24991A6000F0EB54 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
0D1366AD24991A6000F0EB54 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
0D1366AF24991A6000F0EB54 /* SplashScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SplashScreen.swift; sourceTree = "<group>"; };
0D1366AF24991A6000F0EB54 /* HomeScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeScreen.swift; sourceTree = "<group>"; };
0D1366B124991A6100F0EB54 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
0D1366B424991A6100F0EB54 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
0D1366B724991A6100F0EB54 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
@ -94,6 +100,7 @@
0D1366C924991A6200F0EB54 /* ZirclesUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ZirclesUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
0D1366CD24991A6200F0EB54 /* ZirclesUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZirclesUITests.swift; sourceTree = "<group>"; };
0D1366CF24991A6200F0EB54 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
0D3FB6FD24A4CD4E0034A52A /* MockEnvironment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockEnvironment.swift; sourceTree = "<group>"; };
0D5142C224A0F0B800F9AE2E /* Zboto.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = Zboto.otf; sourceTree = "<group>"; };
0D5142C524A14D0F00F9AE2E /* CreateNewZircleNameView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateNewZircleNameView.swift; sourceTree = "<group>"; };
0D5142C724A16F9600F9AE2E /* CreateNewTypeOfZircle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateNewTypeOfZircle.swift; sourceTree = "<group>"; };
@ -118,6 +125,11 @@
0D6A22C6249AB36100B4E946 /* ZcashButtonBackground.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZcashButtonBackground.swift; sourceTree = "<group>"; };
0D6A22C8249AB3CA00B4E946 /* ZcashButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZcashButton.swift; sourceTree = "<group>"; };
0D6A22CA249AB61200B4E946 /* Glow_Preview.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Glow_Preview.swift; sourceTree = "<group>"; };
0DB5330D24A623AF0090D722 /* sapling-spend.params */ = {isa = PBXFileReference; lastKnownFileType = file; path = "sapling-spend.params"; sourceTree = "<group>"; };
0DB5330E24A623AF0090D722 /* sapling-output.params */ = {isa = PBXFileReference; lastKnownFileType = file; path = "sapling-output.params"; sourceTree = "<group>"; };
0DB5331124A6413D0090D722 /* LazyView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LazyView.swift; sourceTree = "<group>"; };
0DD7278824A5532300C36D27 /* AllZirclesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AllZirclesView.swift; sourceTree = "<group>"; };
0DD7278A24A564AF00C36D27 /* ZircleListCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZircleListCard.swift; sourceTree = "<group>"; };
0DEE59A724A24B7300447C15 /* WelcomeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeView.swift; sourceTree = "<group>"; };
0DEE59A924A2B90F00447C15 /* CreateNewZircleDescription.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateNewZircleDescription.swift; sourceTree = "<group>"; };
5A3D0DB1D10FF551A7DE4766 /* Pods-Zircles-ZirclesUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Zircles-ZirclesUITests.release.xcconfig"; path = "Target Support Files/Pods-Zircles-ZirclesUITests/Pods-Zircles-ZirclesUITests.release.xcconfig"; sourceTree = "<group>"; };
@ -172,6 +184,7 @@
0D11D3D5249D2E0400223146 /* Utils */ = {
isa = PBXGroup;
children = (
0DB5331124A6413D0090D722 /* LazyView.swift */,
0D64CEB224A3CDA90080AA4F /* BalanceUtils.swift */,
0D64CEB124A3CDA90080AA4F /* CameraAccessHelper.swift */,
0D64CEAE24A3CDA80080AA4F /* MnemonicSeedPhraseHandling.swift */,
@ -186,6 +199,7 @@
0D6A22CA249AB61200B4E946 /* Glow_Preview.swift */,
0D64CEC024A3F2580080AA4F /* FirstScreen.swift */,
0D64CEC224A4137D0080AA4F /* ZircleData.swift */,
0D3FB6FD24A4CD4E0034A52A /* MockEnvironment.swift */,
);
path = Utils;
sourceTree = "<group>";
@ -215,6 +229,8 @@
0D1366AA24991A6000F0EB54 /* Zircles */ = {
isa = PBXGroup;
children = (
0DB5330E24A623AF0090D722 /* sapling-output.params */,
0DB5330D24A623AF0090D722 /* sapling-spend.params */,
0D64CEBE24A3D3A30080AA4F /* CombineSynchronizer.swift */,
0D64CEA724A3CD040080AA4F /* Environment */,
0D5142C424A1323900F9AE2E /* Views */,
@ -262,12 +278,13 @@
0D5142C424A1323900F9AE2E /* Views */ = {
isa = PBXGroup;
children = (
0D1366AF24991A6000F0EB54 /* SplashScreen.swift */,
0D1366AF24991A6000F0EB54 /* HomeScreen.swift */,
0D5142C524A14D0F00F9AE2E /* CreateNewZircleNameView.swift */,
0D5142C724A16F9600F9AE2E /* CreateNewTypeOfZircle.swift */,
0DEE59A724A24B7300447C15 /* WelcomeView.swift */,
0DEE59A924A2B90F00447C15 /* CreateNewZircleDescription.swift */,
0D64CEC424A41AF30080AA4F /* AppDetails.swift */,
0DD7278824A5532300C36D27 /* AllZirclesView.swift */,
);
path = Views;
sourceTree = "<group>";
@ -288,6 +305,7 @@
0D6A22C6249AB36100B4E946 /* ZcashButtonBackground.swift */,
0D6A22C4249AB1FC00B4E946 /* ZcashSymbol.swift */,
0D64CEA524A3854C0080AA4F /* ZircleOptionSelector.swift */,
0DD7278A24A564AF00C36D27 /* ZircleListCard.swift */,
);
path = Components;
sourceTree = "<group>";
@ -295,7 +313,7 @@
0D6A22CC249ACD6C00B4E946 /* Neumorphic */ = {
isa = PBXGroup;
children = (
0D11D3DA249D5F1600223146 /* ProgressBar.swift */,
0D11D3DA249D5F1600223146 /* NeumorphicProgressBar.swift */,
0D11D3CD249C294E00223146 /* NeumorphicButtons.swift */,
0D11D3CF249C3AE300223146 /* Card.swift */,
0D11D3D1249CE6C800223146 /* GlowEffect.swift */,
@ -430,7 +448,9 @@
0D1366B824991A6100F0EB54 /* LaunchScreen.storyboard in Resources */,
0D1366B524991A6100F0EB54 /* Preview Assets.xcassets in Resources */,
0D5142C324A0F0B800F9AE2E /* Zboto.otf in Resources */,
0DB5331024A623AF0090D722 /* sapling-output.params in Resources */,
0D1366B224991A6100F0EB54 /* Assets.xcassets in Resources */,
0DB5330F24A623AF0090D722 /* sapling-spend.params in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -574,16 +594,20 @@
0D11D3D0249C3AE400223146 /* Card.swift in Sources */,
0D64CEB724A3CDA90080AA4F /* QRCodeGenerator.swift in Sources */,
0D64CEBF24A3D3A30080AA4F /* CombineSynchronizer.swift in Sources */,
0DD7278B24A564AF00C36D27 /* ZircleListCard.swift in Sources */,
0D6A22CB249AB61200B4E946 /* Glow_Preview.swift in Sources */,
0D5142C624A14D0F00F9AE2E /* CreateNewZircleNameView.swift in Sources */,
0DEE59AA24A2B90F00447C15 /* CreateNewZircleDescription.swift in Sources */,
0DD7278924A5532300C36D27 /* AllZirclesView.swift in Sources */,
0D3FB6FE24A4CD4E0034A52A /* MockEnvironment.swift in Sources */,
0D11D3D7249D2F0B00223146 /* ZircleProgress.swift in Sources */,
0D11D3D9249D51FC00223146 /* ZircleTextField_Preview.swift in Sources */,
0D64CEC124A3F2580080AA4F /* FirstScreen.swift in Sources */,
0D64CEBA24A3CDA90080AA4F /* zECC+SwiftUI.swift in Sources */,
0D11D3D2249CE6C800223146 /* GlowEffect.swift in Sources */,
0D64CEB524A3CDA90080AA4F /* String+Zcash.swift in Sources */,
0D11D3DB249D5F1600223146 /* ProgressBar.swift in Sources */,
0DB5331224A6413D0090D722 /* LazyView.swift in Sources */,
0D11D3DB249D5F1600223146 /* NeumorphicProgressBar.swift in Sources */,
0D64CEBD24A3CDA90080AA4F /* SimpleLogger.swift in Sources */,
0D64CEBC24A3CDA90080AA4F /* BalanceUtils.swift in Sources */,
0D5142C824A16F9600F9AE2E /* CreateNewTypeOfZircle.swift in Sources */,
@ -591,7 +615,7 @@
0D64CEB424A3CDA90080AA4F /* SeedManagement.swift in Sources */,
0D64CEC324A4137D0080AA4F /* ZircleData.swift in Sources */,
0D64CEA924A3CD1B0080AA4F /* ZirclesEnvironment.swift in Sources */,
0D1366B024991A6000F0EB54 /* SplashScreen.swift in Sources */,
0D1366B024991A6000F0EB54 /* HomeScreen.swift in Sources */,
0DEE59A824A24B7300447C15 /* WelcomeView.swift in Sources */,
0D64CEA624A3854C0080AA4F /* ZircleOptionSelector.swift in Sources */,
);

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "Invite.jpg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "downchart.pdf",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "join.jpg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

View File

@ -0,0 +1,21 @@
{
"images" : [
{
"filename" : "upchart.pdf",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

View File

@ -10,7 +10,7 @@ import Foundation
import SwiftUI
extension Color {
static let background = Color(#colorLiteral(red: 0.8931570649, green: 0.9219855666, blue: 0.9563117623, alpha: 1))
static let background = Color(#colorLiteral(red: 0.8941176471, green: 0.9411764706, blue: 0.9568627451, alpha: 1))
static let shadowBackground = Color(#colorLiteral(red: 0.8572473526, green: 0.8862729073, blue: 0.9295067191, alpha: 1))
static let buttonBlue = Color(#colorLiteral(red: 0.2486506402, green: 0.3574069142, blue: 0.5763935447, alpha: 1))
static let buttonGray = Color(#colorLiteral(red: 0.5530887246, green: 0.622399509, blue: 0.7596352696, alpha: 1))

View File

@ -0,0 +1,56 @@
//
// ZircleListCard.swift
// Zircles
//
// Created by Francisco Gindre on 6/25/20.
// Copyright © 2020 Electric Coin Company. All rights reserved.
//
import SwiftUI
struct ZircleListCard: View {
var name: String
var progress: Double
@State var isPressed = false
var body: some View {
Toggle(isOn: $isPressed) {
HStack(spacing: 16) {
Toggle(isOn: $isPressed) {
if progress < 0.5 {
Image("downchart")
.renderingMode(.original)
} else {
Image("upchart")
.renderingMode(.original)
}
}.toggleStyle(SimpleToggleStyle(shape: RoundedRectangle(cornerRadius: 10, style: .continuous), padding: 16))
VStack {
HStack {
Text(name)
.foregroundColor(.zGray)
.shadow(radius: 1)
Text("\(Int(progress))%")
.foregroundColor(.zGray)
.shadow(radius: 1)
}
NeumorphicProgressBar(progress: .constant(CGFloat(progress)), fillStyle: progress < 0.5 ? Color.red : Color.green )
.frame(minWidth: 100, idealWidth: 100, maxWidth: .infinity, minHeight: 5, idealHeight: 5, maxHeight: 5, alignment: .center)
}
}
}
.toggleStyle(SimpleToggleStyle(shape: RoundedRectangle(cornerRadius: 10, style: .continuous),padding:16))
}
}
struct ZircleListCard_Previews: PreviewProvider {
static var previews: some View {
ZStack {
Color.background
Group {
ZircleListCard(name: "Hackathon Drinks", progress: 0.5)
ZircleListCard(name: "Long-term Circle", progress: 0.02)
}
}
}
}

View File

@ -18,7 +18,12 @@ enum WalletState {
}
protocol AppEnvironment {
func createNewWallet() throws
func nuke(abortApplication: Bool)
func getMainAddress() -> String
func getUsername() -> String
func getMainSeedPhrase() -> String
func getLatestHeight() -> Int64
}
final class ZirclesEnvironment: ObservableObject {
@ -33,7 +38,7 @@ final class ZirclesEnvironment: ObservableObject {
static var shared: ZirclesEnvironment = try! ZirclesEnvironment() // app can't live without this existing.
@Published var state: WalletState
var errorPublisher = PassthroughSubject<Error,Never>()
let endpoint = LightWalletEndpoint(address: ZcashSDK.isMainnet ? "lightwalletd.z.cash" : "lightwalletd.testnet.z.cash", port: 9067, secure: true)
var dataDbURL: URL
var cacheDbURL: URL
@ -123,6 +128,27 @@ final class ZirclesEnvironment: ObservableObject {
self.synchronizer.start()
}
static var appBuild: String? {
Bundle.main.infoDictionary?["CFBundleVersion"] as? String
}
static var appVersion: String? {
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
}
func isValidAddress(_ address: String) -> Bool {
self.initializer.isValidShieldedAddress(address) || self.initializer.isValidTransparentAddress(address)
}
func sufficientFundsToSend(amount: Double) -> Bool {
return sufficientFunds(availableBalance: self.initializer.getVerifiedBalance(), zatoshiToSend: amount.toZatoshi())
}
private func sufficientFunds(availableBalance: Int64, zatoshiToSend: Int64) -> Bool {
availableBalance - zatoshiToSend - Int64(ZcashSDK.MINERS_FEE_ZATOSHI) >= 0
}
static var minerFee: Double {
Int64(ZcashSDK.MINERS_FEE_ZATOSHI).asHumanReadableZecBalance()
}
/**
only for internal use
*/
@ -152,6 +178,16 @@ final class ZirclesEnvironment: ObservableObject {
}
}
deinit {
cancellables.forEach {
c in
c.cancel()
}
}
}
extension Error {
static func mapError(error: Error) -> ZirclesEnvironment.WalletError {
if let rustError = error as? RustWeldingError {
@ -167,55 +203,50 @@ final class ZirclesEnvironment: ObservableObject {
case .malformedStringInput:
return ZirclesEnvironment.WalletError.genericError(message: "Malformed address or key detected")
default:
return WalletError.genericError(message: "\(rustError)")
return ZirclesEnvironment.WalletError.genericError(message: "\(rustError)")
}
} else if let synchronizerError = error as? SynchronizerError {
switch synchronizerError {
case .generalError(let message):
return ZirclesEnvironment.WalletError.genericError(message: message)
case .initFailed(let message):
return WalletError.initializationFailed(message: "Synchronizer failed to initialize: \(message)")
return ZirclesEnvironment.WalletError.initializationFailed(message: "Synchronizer failed to initialize: \(message)")
case .syncFailed:
return WalletError.genericError(message: "Synchronizing failed")
return ZirclesEnvironment.WalletError.genericError(message: "Synchronizing failed")
case .connectionFailed(let message):
return WalletError.connectionFailed(message: message)
return ZirclesEnvironment.WalletError.connectionFailed(message: message)
case .maxRetryAttemptsReached(attempts: let attempts):
return WalletError.maxRetriesReached(attempts: attempts)
return ZirclesEnvironment.WalletError.maxRetriesReached(attempts: attempts)
case .connectionError(_, let message):
return WalletError.connectionFailed(message: message)
return ZirclesEnvironment.WalletError.connectionFailed(message: message)
}
}
return ZirclesEnvironment.WalletError.genericError(message: Self.genericErrorMessage)
return ZirclesEnvironment.WalletError.genericError(message: ZirclesEnvironment.genericErrorMessage)
}
deinit {
cancellables.forEach {
c in
c.cancel()
}
extension ZirclesEnvironment: AppEnvironment {
func getMainAddress() -> String {
self.initializer.getAddress(index: 0) ?? "No address!!"
}
func getUsername() -> String {
ZircleDataStorage.default.username
}
func getMainSeedPhrase() -> String {
guard let phrase = try? SeedManager.default.exportPhrase() else {
return "no phrase"
}
return phrase
}
func getLatestHeight() -> Int64 {
Int64(synchronizer.syncBlockHeight.value)
}
}
extension ZirclesEnvironment {
static var appBuild: String? {
Bundle.main.infoDictionary?["CFBundleVersion"] as? String
}
static var appVersion: String? {
Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
}
func isValidAddress(_ address: String) -> Bool {
self.initializer.isValidShieldedAddress(address) || self.initializer.isValidTransparentAddress(address)
}
func sufficientFundsToSend(amount: Double) -> Bool {
return sufficientFunds(availableBalance: self.initializer.getVerifiedBalance(), zatoshiToSend: amount.toZatoshi())
}
private func sufficientFunds(availableBalance: Int64, zatoshiToSend: Int64) -> Bool {
availableBalance - zatoshiToSend - Int64(ZcashSDK.MINERS_FEE_ZATOSHI) >= 0
}
static var minerFee: Double {
Int64(ZcashSDK.MINERS_FEE_ZATOSHI).asHumanReadableZecBalance()
}
}

View File

@ -1,7 +1,7 @@
import SwiftUI
extension Color {
static let offWhite = Color(red: 225 / 255, green: 225 / 255, blue: 235 / 255)
static let offWhite = Color(red: 228 / 255, green: 240 / 255, blue: 250 / 255)
static let darkStart = Color(red: 50 / 255, green: 60 / 255, blue: 65 / 255)
static let darkEnd = Color(red: 25 / 255, green: 25 / 255, blue: 30 / 255)

View File

@ -8,8 +8,9 @@
import SwiftUI
struct ProgressBar: View {
struct NeumorphicProgressBar<S: ShapeStyle>: View {
@Binding var progress: CGFloat
var fillStyle: S
var body: some View {
GeometryReader { geometry in
@ -29,7 +30,7 @@ struct ProgressBar: View {
}
.stroke(style: .init(lineWidth: geometry.size.height, lineCap: .round))
.fill(LinearGradient.zButtonGradient)
.fill(self.fillStyle)
}
}
@ -45,7 +46,7 @@ struct ProgressBar_Previews: PreviewProvider {
cornerRadius: 15,
padding: 5
) {
ProgressBar(progress: .constant(0.6))
NeumorphicProgressBar(progress: .constant(0.6), fillStyle: LinearGradient.zButtonGradient)
.animation(.easeInOut)
.frame(height: 30)
.padding(.horizontal)

View File

@ -18,22 +18,33 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
_ZirclesNavigationBarLookTweaks()
// Create the SwiftUI view that provides the window contents.
let isInitialized = ZirclesEnvironment.isInitialized()
let contentView = FirstScreen() {
if isInitialized {
SplashScreen()
HomeScreen()
// AllZirclesView(
// zircles: [
// ZircleSummary(progress: 0.5, name: "Hackathon Drinks", paymentDue: false),
// ZircleSummary(progress: 0.02, name: "Long-term Circle", paymentDue: true)
//
// ]
// )
} else {
WelcomeView()
}
}
if isInitialized {
try? ZirclesEnvironment.shared.initialize()
ZirclesEnvironment.shared.synchronizer.start()
}
// Use a UIHostingController as window root view controller.
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
@ -69,3 +80,33 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
}
extension UIApplication {
func endEditing() {
sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
func _ZirclesNavigationBarLookTweaks() {
//// let appearance = UINavigationBarAppearance()
//// appearance.configureWithTransparentBackground()
//// appearance.largeTitleTextAttributes = [
//// .font : UIFont.systemFont(ofSize: 20),
//// NSAttributedString.Key.foregroundColor : UIColor.white
//// ]
////
//// appearance.titleTextAttributes = [
//// .font : UIFont.systemFont(ofSize: 20),
//// NSAttributedString.Key.foregroundColor : UIColor.white
//// ]
////
// UINavigationBar.appearance().scrollEdgeAppearance = appearance
// UINavigationBar.appearance().standardAppearance = appearance
//
let clearView = UIView()
clearView.backgroundColor = UIColor.clear
UITableViewCell.appearance().selectedBackgroundView = clearView
UITableView.appearance().backgroundColor = UIColor.clear
}

View File

@ -0,0 +1,19 @@
//
// LazyView.swift
// wallet
//
// Created by Francisco Gindre on 3/19/20.
// Copyright © 2020 Francisco Gindre. All rights reserved.
//
import SwiftUI
struct LazyView<Content: View>: View {
let build: () -> Content
init(_ build: @autoclosure @escaping () -> Content) {
self.build = build
}
var body: Content {
build()
}
}

View File

@ -0,0 +1,27 @@
//
// MockEnvironment.swift
// Zircles
//
// Created by Francisco Gindre on 6/25/20.
// Copyright © 2020 Electric Coin Company. All rights reserved.
//
import Foundation
class MockAppEnvironment: AppEnvironment, ObservableObject {
func createNewWallet() throws {}
func nuke(abortApplication: Bool) {}
func getMainAddress() -> String {
"zsFakefejaefnq2rrneferjgbrauiebnfiosjebfeyetqoq3"
}
func getUsername() -> String {
"pacu"
}
func getMainSeedPhrase() -> String {
"kitchen renew wide common vague fold vacuum tilt amazing pear square gossip jewel month tree shock scan alpha just spot fluid toilet view dinner"
}
func getLatestHeight() -> Int64 {
999999
}
}

View File

@ -0,0 +1,111 @@
//
// AllZirclesView.swift
// Zircles
//
// Created by Francisco Gindre on 6/25/20.
// Copyright © 2020 Electric Coin Company. All rights reserved.
//
import SwiftUI
import UIKit
struct ZircleSummary {
var progress: Double
var name: String
var paymentDue: Bool
}
struct AllZirclesView: View {
@State var detailsActive = false
var zircles: [ZircleSummary]
var paymentsDueLegend: String {
let paymentsDue = zircles.filter({ $0.paymentDue}).count
return "You Have \(zircles.count) \( zircles.count > 1 ? "Zircles" : "Zircle"). \(paymentsDue > 0 ? String(paymentsDue) : "No") \(paymentsDue == 1 ? "payment" : "payments") due"
}
var body: some View {
ZStack {
Color.background.edgesIgnoringSafeArea(.all)
VStack(alignment: .leading, spacing: 24) {
HStack {
FancyLogo(progress: .constant(0.75))
.scaleEffect(0.3)
.disabled(true)
.background(EmptyView())
Text(paymentsDueLegend)
.lineLimit(2)
.foregroundColor(.black)
.font(.title)
}
.frame(height: 50)
List {
ForEach(0 ..< zircles.count) { index in
VStack {
ZircleListCard(summary: zircles[index])
}
.padding(.vertical, 30)
.listRowBackground(Color.clear)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
}
}
}
}
.onAppear() {
UITableView.appearance().separatorStyle = .none
UITableView.appearance().backgroundColor = UIColor.clear
}
.onDisappear() {
UITableView.appearance().separatorStyle = .singleLine
UITableView.appearance().backgroundColor = UIColor.white
}
.navigationBarTitle("", displayMode: .inline)
.sheet(isPresented: $detailsActive) {
AppDetails(isActive: $detailsActive,appEnvironment: MockAppEnvironment())
}
.navigationBarBackButtonHidden(true)
.navigationBarItems(trailing: Button(action: {
self.detailsActive = true
}){
Image(systemName: "z.circle")
.frame(width: 30, height: 30, alignment: .center)
}
.contentShape(Circle())
)
.sheet(isPresented: $detailsActive) {
AppDetails(isActive: $detailsActive,appEnvironment: MockAppEnvironment())
}
}
}
extension ZircleListCard {
init(summary: ZircleSummary) {
self.name = summary.name
self.progress = summary.progress
}
}
struct AllZirclesView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
ZStack{
AllZirclesView(
zircles: [
ZircleSummary(progress: 0.5, name: "Hackathon Drinks", paymentDue: false),
ZircleSummary(progress: 0.02, name: "Long-term Circle", paymentDue: true)
]
)
}
}
}
}

View File

@ -10,75 +10,126 @@ import SwiftUI
struct AppDetails: View {
@State var showNukeAlert = false
@Binding var isActive: Bool
var appEnvironment: AppEnvironment
var body: some View {
ZStack {
Color.background.edgesIgnoringSafeArea(.all)
VStack {
VStack(alignment: .leading, spacing: 3) {
Text("Username")
.foregroundColor(.textLightGray)
.fontWeight(.heavy)
.font(.footnote)
.frame(alignment: .leading)
Card(isOn: .constant(true),cornerRadius: 5,padding: 8) {
Text(ZircleDataStorage.default.username)
.foregroundColor(Color.textDarkGray)
.font(.system(size: 14, weight: .heavy, design: .default))
}
}.padding(.all, 0)
VStack(alignment: .leading, spacing: 3) {
Text("App Version")
.foregroundColor(.textLightGray)
.fontWeight(.heavy)
.font(.footnote)
.frame(alignment: .leading)
Card(isOn: .constant(true),cornerRadius: 5,padding: 8) {
Text("Zircles v\(ZirclesEnvironment.appVersion ?? "Unknown") - Build: \(ZirclesEnvironment.appBuild ?? "Unknown")")
.foregroundColor(Color.textDarkGray)
.font(.system(size: 14, weight: .heavy, design: .default))
}
}.padding(.all, 0)
NavigationView {
ZStack {
Color.background.edgesIgnoringSafeArea(.all)
Button(action: {
self.showNukeAlert = true
}) {
Text("NUKE WALLET")
.foregroundColor(.red)
.zcashButtonBackground(shape: .roundedCorners(fillStyle: .outline(color: .red, lineWidth: 2)))
.frame(height: 48)
}.alert(isPresented: $showNukeAlert) {
Alert(title: Text("Delete Wallet?"),
message: Text("You are about to")+Text(" nuke your wallet. ").foregroundColor(.red) + Text("Are you sure you want to proceed?"),
primaryButton: .default(
Text("I'm not sure")
,action: { self.showNukeAlert = false}
),
secondaryButton: .destructive(
Text("NUKE WALLET!"),
action: {
ZirclesEnvironment.shared.nuke(abortApplication: true)
}
)
)
VStack(alignment: .leading, spacing: 12) {
VStack(alignment: .leading, spacing: 3) {
Text("Username")
.foregroundColor(.textLightGray)
.fontWeight(.heavy)
.font(.footnote)
.frame(alignment: .leading)
Card(isOn: .constant(true),cornerRadius: 5,padding: 8) {
Text(appEnvironment.getUsername())
.foregroundColor(Color.textDarkGray)
.font(.system(size: 14, weight: .heavy, design: .default))
}
}.padding(.all, 0)
VStack(alignment: .leading, spacing: 3) {
Text("Main Account zAddress")
.foregroundColor(.textLightGray)
.fontWeight(.heavy)
.font(.footnote)
.frame(alignment: .leading)
Card(isOn: .constant(true),cornerRadius: 5,padding: 8) {
Text(appEnvironment.getMainAddress())
.foregroundColor(Color.textDarkGray)
.font(.system(size: 14, weight: .heavy, design: .default))
}
}.padding(.all, 0)
VStack(alignment: .leading, spacing: 3) {
Text("Latest Downloaded Height")
.foregroundColor(.textLightGray)
.fontWeight(.heavy)
.font(.footnote)
.frame(alignment: .leading)
Card(isOn: .constant(true),cornerRadius: 5,padding: 8) {
Text("999999")
.foregroundColor(Color.textDarkGray)
.font(.system(size: 14, weight: .heavy, design: .default))
}
}.padding(.all, 0)
VStack(alignment: .leading, spacing: 3) {
Text("Main Account Seed Phrase")
.foregroundColor(.textLightGray)
.fontWeight(.heavy)
.font(.footnote)
.frame(alignment: .leading)
Card(isOn: .constant(true),cornerRadius: 5,padding: 8) {
Text(appEnvironment.getMainSeedPhrase())
.foregroundColor(Color.textDarkGray)
.font(.system(size: 14, weight: .heavy, design: .default))
}
}.padding(.all, 0)
VStack(alignment: .leading, spacing: 3) {
Text("App Version")
.foregroundColor(.textLightGray)
.fontWeight(.heavy)
.font(.footnote)
.frame(alignment: .leading)
Card(isOn: .constant(true),cornerRadius: 5,padding: 8) {
Text("Zircles v\(ZirclesEnvironment.appVersion ?? "Unknown") - Build: \(ZirclesEnvironment.appBuild ?? "Unknown")")
.foregroundColor(Color.textDarkGray)
.font(.system(size: 14, weight: .heavy, design: .default))
}
}.padding(.all, 0)
Spacer()
Button(action: {
self.showNukeAlert = true
}) {
Text("NUKE WALLET")
.foregroundColor(.red)
.zcashButtonBackground(shape: .roundedCorners(fillStyle: .outline(color: .red, lineWidth: 2)))
.frame(height: 48)
}.alert(isPresented: $showNukeAlert) {
Alert(title: Text("Delete Wallet?"),
message: Text("You are about to")+Text(" nuke your wallet. ").foregroundColor(.red) + Text("Are you sure you want to proceed?"),
primaryButton: .default(
Text("I'm not sure")
,action: { self.showNukeAlert = false}
),
secondaryButton: .destructive(
Text("NUKE WALLET!"),
action: {
ZirclesEnvironment.shared.nuke(abortApplication: true)
}
)
)
}
}
.padding([.horizontal,.bottom], 30)
}
}.navigationBarTitle(Text("Backstage"))
.navigationBarItems(trailing: Button(action:{
}){
Text("close")
})
.navigationBarTitle(Text("Backstage"))
.navigationBarItems(trailing: Button(action:{
}){
Text("close")
})
}
}
}
struct AppDetails_Previews: PreviewProvider {
static var previews: some View {
AppDetails()
NavigationView{
AppDetails(isActive: .constant(true), appEnvironment: MockAppEnvironment())
}
}
}

View File

@ -11,7 +11,7 @@ import SwiftUI
struct CreateNewTypeOfZircle: View {
var body: some View {
ZStack {
Color.background
Color.background.edgesIgnoringSafeArea(.all)
VStack(spacing: 32 ) {
Spacer()
Text("Savings Circle")
@ -33,7 +33,9 @@ struct CreateNewTypeOfZircle: View {
.shadow(color: Color(red: 0.2, green: 0.2, blue: 0.2).opacity(0.5), radius: 25, x: 10, y: 10)
.frame(height: 50)
NavigationLink(
destination: CreateNewZircleDescription())
{
Text("Group Budget Goal")
.font(.system(size: 20, weight: .bold, design: .default))
.shadow(color:Color(.sRGBLinear, red: 0.2, green: 0.2, blue: 0.2, opacity: 0.5), radius: 1, x: 0, y: 2)
@ -42,6 +44,7 @@ struct CreateNewTypeOfZircle: View {
.shadow(color: Color(red: 0.2, green: 0.2, blue: 0.2).opacity(0.5), radius: 25, x: 10, y: 10)
.frame(height: 50)
}
Card(isOn: .constant(false),cornerRadius: 10, padding: 16) {
ZircleProgress(progress: 0.7, stroke: .init(lineWidth: 5, lineCap: .round))
.glow(vibe: .heavy, soul: .split(left: Color.gradientPink, right: Color.gradientOrange))
@ -59,7 +62,7 @@ struct CreateNewTypeOfZircle: View {
}
.padding(.horizontal, 30)
.padding(.bottom, 30)
}
}.navigationBarTitle(Text("What Type of Savings Project?"))
}
}

View File

@ -55,7 +55,7 @@ struct CreateNewZircleDescription: View {
var body: some View {
ZStack {
Color.background
Color.background.edgesIgnoringSafeArea(.all)
VStack(spacing: 30) {
VStack(alignment: .leading, spacing: 3) {
Text("Name of project")

View File

@ -8,7 +8,16 @@
import SwiftUI
struct SplashScreen: View {
/*
Zircles:ztestsapling16rzlnxq7wyxjctymxcnhjh2tru4hk48t2v3a32aacuyldsj3q0wgkny9w4re7n22yuemgmw8fqg
Wallet Birthday:950000
come exhibit fatal kid consider useless pigeon glove crawl stumble crunch left click labor curtain debris park hour raise wonder guilt upset eager order
*/
struct HomeScreen: View {
@State var detailsActive = false
@State var progress: Double = 0
var body: some View {
ZStack {
@ -26,11 +35,15 @@ struct SplashScreen: View {
.contentShape(RoundedRectangle(cornerRadius: 5))
.toggleStyle(SimpleToggleStyle(shape: RoundedRectangle(cornerRadius: 5), padding: 8))
Spacer()
FancyLogo()
FancyLogo(progress: $progress)
.frame(width: 200, height: 200)
.animation(.easeInOut)
.onReceive(ZirclesEnvironment.shared.synchronizer.progress) { p in
self.progress = Double(p)
}
Spacer()
VStack(spacing: 16) {
Text("Join a Zircle")
if progress < 1 {
Text("Syncing...")
.font(.system(size: 20, weight: .bold, design: .default))
.shadow(color:Color(red: 0.2, green: 0.2, blue: 0.2).opacity(0.2), radius: 1, x: 0, y: 2)
.foregroundColor(Color.buttonBlue)
@ -39,8 +52,25 @@ struct SplashScreen: View {
.shadow(color: Color(red: 0.2, green: 0.2, blue: 0.2).opacity(0.3), radius: 15, x: 10, y: 15)
.shadow(color: Color.white.opacity(0.5), radius: 25, x:-10, y: -10)
.frame(height: 50)
} else {
VStack(spacing: 16) {
Button(action: {
}, label: {
Text("Join a Zircle")
.font(.system(size: 20, weight: .bold, design: .default))
.shadow(color:Color(red: 0.2, green: 0.2, blue: 0.2).opacity(0.2), radius: 1, x: 0, y: 2)
.foregroundColor(Color.buttonBlue)
.modifier(ZcashButtonBackground(buttonShape: .roundedCorners(fillStyle: .solid(color: Color.background))))
.shadow(color: Color(red: 0.2, green: 0.2, blue: 0.2).opacity(0.3), radius: 15, x: 10, y: 15)
.shadow(color: Color.white.opacity(0.5), radius: 25, x:-10, y: -10)
.frame(height: 50)
})
Button(action: {}) {
NavigationLink(
destination: CreateNewTypeOfZircle()) {
Text("Create New")
.font(.system(size: 20, weight: .bold, design: .default))
.shadow(color:Color(red: 0.2, green: 0.2, blue: 0.2).opacity(0.2), radius: 1, x: 0, y: 2)
@ -51,14 +81,31 @@ struct SplashScreen: View {
.frame(height: 50)
}
}.padding(.all, 0)
}
}.padding(30)
}.navigationBarTitle(Text("Welcome to Zircles"))
}
.navigationBarBackButtonHidden(true)
.navigationBarTitle(Text("Welcome to Zircles"))
.navigationBarItems(trailing: Button(action: {
self.detailsActive = true
}){
Image(systemName: "z.circle")
.frame(width: 30, height: 30, alignment: .center)
}
.contentShape(Circle())
)
.sheet(isPresented: $detailsActive) {
AppDetails(isActive: $detailsActive,appEnvironment: ZirclesEnvironment.shared)
}
}
}
struct FancyLogo: View {
@Binding var progress: Double
var body: some View {
ZStack {
@ -73,8 +120,9 @@ struct FancyLogo: View {
}
.overlay(
ZircleProgress(progress: 0.75, stroke: .init(lineWidth: 40, lineCap: .round))
ZircleProgress(progress: progress, stroke: .init(lineWidth: 40, lineCap: .round))
.padding(23)
.animation(.easeIn)
)
@ -93,6 +141,6 @@ struct FancyLogo: View {
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
SplashScreen()
HomeScreen()
}
}

View File

@ -8,15 +8,20 @@
import SwiftUI
import MnemonicSwift
import ZcashLightClientKit
struct WelcomeView: View {
@State var username: String = ""
@State var seedPhrase: String = ""
@State var birthdayHeight: String = ""
@State var isWelcome = false
@State var showError = false
@State var error: Error? = nil
var body: some View {
ZStack {
Color.background.edgesIgnoringSafeArea(.all)
VStack(alignment: .leading, spacing: 16) {
Spacer()
Text("It looks like you are a new user, let's get to know you! What is your name?")
.fontWeight(.heavy)
.foregroundColor(Color.textDarkGray)
@ -52,6 +57,18 @@ struct WelcomeView: View {
.font(.system(size: 14, weight: .heavy, design: .default))
}
}.padding(.all, 0)
VStack(alignment: .leading, spacing: 4) {
Text("Birthday height")
.foregroundColor(.textLightGray)
.fontWeight(.heavy)
.font(.footnote)
.frame(alignment: .leading)
Card(isOn: .constant(true),cornerRadius: 5,padding: 8) {
TextField("Birthday height", text: $birthdayHeight)
.foregroundColor(Color.textDarkGray)
.font(.system(size: 14, weight: .heavy, design: .default))
}
}.padding(.all, 0)
Spacer()
Text("The Zircles app will only send ZEC to other Zircles app.")
.foregroundColor(.textLightGray)
@ -60,8 +77,11 @@ struct WelcomeView: View {
.frame(alignment: .center)
Spacer()
Button(action: {
self.isWelcome = true
do {
try initialize()
} catch {
ZirclesEnvironment.shared.errorPublisher.send(error)
}
}) {
Text("Add Wallet to Zircles")
.font(.system(size: 20, weight: .bold, design: .default))
@ -72,8 +92,9 @@ struct WelcomeView: View {
.shadow(color: Color(red: 0.2, green: 0.2, blue: 0.2).opacity(0.5), radius: 25, x: 10, y: 10)
.frame(height: 50)
}.disabled(!validInput())
.opacity(validInput() ? 1.0 : 0.6)
NavigationLink(
destination: SplashScreen(),
destination: HomeScreen(),
isActive: $isWelcome,
label: {
EmptyView()
@ -81,14 +102,34 @@ struct WelcomeView: View {
}
.padding([.horizontal,.bottom], 30)
}.navigationBarTitle(Text("Welcome"))
}
.navigationBarTitle(Text("Welcome"))
.alert(isPresented: $showError) {
Alert(
title: Text("Error"),
message: Text( error == nil ? "It would be embarrasing if it wasn't a hackathon" : "Error: \( ZirclesEnvironment.WalletError.mapError(error: error!).localizedDescription)"),
dismissButton: .default(Text("dismiss"), action: {
self.error = nil
}))
}.onReceive(ZirclesEnvironment.shared.errorPublisher) { e in
self.error = e
self.showError = true
if let _ = e as? SeedManager.SeedManagerError {
ZirclesEnvironment.shared.nuke()
}
}
}
func initialize() throws {
ZircleDataStorage.default.saveUsername(self.username)
try self.importSeed()
try self.importBirthday()
try ZirclesEnvironment.shared.initialize()
self.isWelcome = true
}
func validInput() -> Bool {
validSeedPhrase() && validName()
validSeedPhrase() && validName() && validBirthday()
}
func validSeedPhrase() -> Bool {
@ -98,10 +139,35 @@ struct WelcomeView: View {
func validName() -> Bool {
!username.isEmpty
}
func validBirthday() -> Bool {
birthdayHeight.isEmpty || Int64(birthdayHeight) != nil
}
func validateSeed(_ seed: String) -> Bool {
MnemonicSeedProvider.default.isValid(mnemonic: seed)
}
func importBirthday() throws {
let b = BlockHeight(self.birthdayHeight.trimmingCharacters(in: .whitespacesAndNewlines)) ?? ZcashSDK.SAPLING_ACTIVATION_HEIGHT
try SeedManager.default.importBirthday(b)
}
func importSeed() throws {
let trimmedSeedPhrase = seedPhrase.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmedSeedPhrase.isEmpty, let seedBytes =
MnemonicSeedProvider.default.toSeed(mnemonic: trimmedSeedPhrase) else { throw ZirclesEnvironment.WalletError.createFailed
}
try SeedManager.default.importSeed(seedBytes)
try SeedManager.default.importPhrase(bip39: trimmedSeedPhrase)
}
}
struct WelcomeView_Previews: PreviewProvider {
static var previews: some View {
NavigationView {
WelcomeView()
}
}
}

Binary file not shown.

Binary file not shown.