diff --git a/co.electriccoin.swiftlint.yml b/.swiftlint.yml similarity index 88% rename from co.electriccoin.swiftlint.yml rename to .swiftlint.yml index 3ea9fb6..7bd9828 100644 --- a/co.electriccoin.swiftlint.yml +++ b/.swiftlint.yml @@ -2,8 +2,8 @@ # https://github.com/raywenderlich/swift-style-guide excluded: - - ${PWD}/Pods - - ${PWD}/xctemplates + - Pods + - xctemplates disabled_rules: - notification_center_detachment @@ -37,7 +37,7 @@ opt_in_rules: - legacy_random - literal_expression_end_indentation - multiline_arguments - - multiline_argument_brackets + - multiline_arguments_brackets - multiline_function_chains - multiline_literal_brackets - multiline_parameters @@ -70,26 +70,26 @@ custom_rules: severity: warning string_concatenation: - included: ".*\.swift" - excluded: ".*Test\.swift" + included: ".*\\.swift" + excluded: ".*Test\\.swift" name: "String Concatenation" - regex: '' \+ "|" \+ |\+= "' + regex: " \\+ \"|\" \\+ |\\+= \"" message: "Please use string interpolation instead of concatenation" severity: error print_function_usage: - included: ".*\.swift" - excluded: ".*Test\.swift" + included: ".*\\.swift" + excluded: ".*Test\\.swift" name: "Swift print() or debugPrint() should not be used in App Code" - regex: "print\(|debugPrint\(" + regex: "print\\(|debugPrint\\(" message: "The Swift print() or debugPrint() functions should not be used." severity: warning nslog_function_usage: - included: ".*\.swift" - excluded: ".*Test\.swift" + included: ".*\\.swift" + excluded: ".*Test\\.swift" name: "Swift NSLog() should not be used in App Code" - regex: "NSLog\(" + regex: "NSLog\\(" message: "The swift NSLog function should not be used." severity: error @@ -117,7 +117,7 @@ identifier_name: - z indentation_width: - indentation_width: 2 + indentation_width: 4 line_length: warning: 150 @@ -127,7 +127,7 @@ line_length: file_length: warning: 600 - ignore_comment_only_lines: false: true + ignore_comment_only_lines: true multiline_arguments: first_argument_location: next_line @@ -141,4 +141,4 @@ trailing_whitespace: ignores_comments: true vertical_whitespace: - max_empty_lines: 2 + max_empty_lines: 1 diff --git a/secant.xcodeproj/project.pbxproj b/secant.xcodeproj/project.pbxproj index a0748e8..4e59e42 100644 --- a/secant.xcodeproj/project.pbxproj +++ b/secant.xcodeproj/project.pbxproj @@ -385,6 +385,7 @@ isa = PBXNativeTarget; buildConfigurationList = 0D4E7A2A26B364180058B01E /* Build configuration list for PBXNativeTarget "secant-testnet" */; buildPhases = ( + 6696BA8726F0B1D200D5C875 /* SwiftLint */, 0D4E7A0126B364170058B01E /* Sources */, 0D4E7A0226B364170058B01E /* Frameworks */, 0D4E7A0326B364170058B01E /* Resources */, @@ -503,6 +504,27 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 6696BA8726F0B1D200D5C875 /* SwiftLint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = SwiftLint; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "swiftlint_version=0.44.0\n\nif which swiftlint >/dev/null; then\n if [ $(swiftlint version) = $swiftlint_version ]; then\n swiftlint\n else\n echo \"warning: Compatible SwiftLint version not installed, download version $swiftlint_version from https://github.com/realm/SwiftLint. Currently installed version is $(swiftlint version)\"\n fi \nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 0D4E7A0126B364170058B01E /* Sources */ = { isa = PBXSourcesBuildPhase; diff --git a/secant/Base/Router.swift b/secant/Base/Router.swift index 68ecf2b..a4aee11 100644 --- a/secant/Base/Router.swift +++ b/secant/Base/Router.swift @@ -10,6 +10,6 @@ import SwiftUI public protocol Router: ObservableObject { associatedtype ViewOutput: View - + func rootView() -> ViewOutput } diff --git a/secant/Base/ViewModel.swift b/secant/Base/ViewModel.swift index 3c32d8d..c467180 100644 --- a/secant/Base/ViewModel.swift +++ b/secant/Base/ViewModel.swift @@ -8,11 +8,9 @@ import Foundation open class BaseViewModel { - public var services: S public init(services: S) { self.services = services } - } diff --git a/secant/Mocked Dependencies/KeyStoring.swift b/secant/Mocked Dependencies/KeyStoring.swift index a8e575f..0a59b68 100644 --- a/secant/Mocked Dependencies/KeyStoring.swift +++ b/secant/Mocked Dependencies/KeyStoring.swift @@ -7,30 +7,31 @@ import Foundation - protocol KeyStoring { func importBirthday(_ height: BlockHeight) throws func exportBirthday() throws -> BlockHeight func importPhrase(bip39 phrase: String) throws func exportPhrase() throws -> String - var keysPresent: Bool { get } + /** - Use carefully: Deletes the seed phrase from the keychain - */ + Use carefully: Deletes the seed phrase from the keychain + */ func nukePhrase() /** - Use carefully: deletes the wallet birthday from the keychain - */ + Use carefully: deletes the wallet birthday from the keychain + */ func nukeBirthday() /** There's no fate but what we make for ourselves - Sarah Connor */ func nukeWallet() + + var keysPresent: Bool { get } } -enum KeyStoringError : Error { +enum KeyStoringError: Error { case alreadyImported case uninitializedWallet } diff --git a/secant/Mocked Dependencies/MnemonicSeedPhraseHandling.swift b/secant/Mocked Dependencies/MnemonicSeedPhraseHandling.swift index 2026a2f..0c4e670 100644 --- a/secant/Mocked Dependencies/MnemonicSeedPhraseHandling.swift +++ b/secant/Mocked Dependencies/MnemonicSeedPhraseHandling.swift @@ -7,6 +7,7 @@ // import Foundation + enum MnemonicError: Error { case invalidSeed case checksumFailed @@ -14,26 +15,27 @@ enum MnemonicError: Error { protocol MnemonicSeedPhraseHandling { /** - random 24 words mnemonic phrase - */ + Random 24 words mnemonic phrase + */ func randomMnemonic() throws -> String + /** - random 24 words mnemonic phrase as array of words + Random 24 words mnemonic phrase as array of words */ func randomMnemonicWords() throws -> [String] - + /** - generate deterministic seed from mnemonic phrase - */ + Generate deterministic seed from mnemonic phrase + */ func toSeed(mnemonic: String) throws -> [UInt8] - + /** - get this mnemonic + Get this mnemonic */ func asWords(mnemonic: String) throws -> [String] - + /** - validates whether the given mnemonic is correct - */ + Validates whether the given mnemonic is correct + */ func isValid(mnemonic: String) throws } diff --git a/secant/Mocked Dependencies/Services.swift b/secant/Mocked Dependencies/Services.swift index 02c700f..dfe6afe 100644 --- a/secant/Mocked Dependencies/Services.swift +++ b/secant/Mocked Dependencies/Services.swift @@ -13,7 +13,6 @@ protocol Services { var keyStorage: KeyStoring { get } } - protocol ZcashNetworkProvider { func currentNetwork() -> ZcashNetwork } diff --git a/secant/Models/Balance.swift b/secant/Models/Balance.swift index 62b65b8..00c3db2 100644 --- a/secant/Models/Balance.swift +++ b/secant/Models/Balance.swift @@ -6,67 +6,92 @@ // import Foundation + /** - Funds Expressed in Zatoshis - */ +Funds Expressed in Zatoshis +*/ protocol Funds { /** - Confirmed, spendable funds - */ + Confirmed, spendable funds + */ var confirmed: Int64 { get } + /** - Unconfirmed, not yet spendable funds. - */ + Unconfirmed, not yet spendable funds. + */ var unconfirmed: Int64 { get } - + /** - Represents a null value of Funds with Zero confirmed and Zero unconfirmed funds. - */ - static var noFunds: Funds { get} + Represents a null value of Funds with Zero confirmed and Zero unconfirmed funds. + */ + static var noFunds: Funds { get } } /** - Wallet Balance that condenses transpant, Sapling and Orchard funds - */ +Wallet Balance that condenses transpant, Sapling and Orchard funds +*/ protocol WalletBalance { /** - Transparent funds. This is the sum of the UTXOs of the user found at a given time - */ + Transparent funds. This is the sum of the UTXOs of the user found at a given time + */ var transaparent: Funds { get } + /** - Funds on the Sapling shielded pool for a given user. - */ + Funds on the Sapling shielded pool for a given user. + */ var sapling: Funds { get } + /** - Funds on the Orchard shielded pool for a given user. - */ + Funds on the Orchard shielded pool for a given user. + */ var orchard: Funds { get } + /** - The sum of all confirmed funds, transparent, sapling and orchard funds (calculated) - */ + The sum of all confirmed funds, transparent, sapling and orchard funds (calculated) + */ var totalAvailableBalance: Int64 { get } - + /** - the sum of all unconfirmed funds: transparent, sapling, and orchard funds (calculated - */ + The sum of all unconfirmed funds: transparent, sapling, and orchard funds (calculated + */ var totalUnconfirmedBalance: Int64 { get } - - + /** - the sum of all funds confirmed and unconfirmed of all pools (transparent, sapling and orchard). - */ + The sum of all funds confirmed and unconfirmed of all pools (transparent, sapling and orchard). + */ var totalBalance: Int64 { get } - + /** - represents a the value of Zero funds. - */ + Represents a the value of Zero funds. + */ static var nullBalance: WalletBalance { get } } +extension WalletBalance { + static var nullBalance: WalletBalance { + Balance( + transaparent: ZcashFunds.noFunds, + sapling: ZcashFunds.noFunds, + orchard: ZcashFunds.noFunds + ) + } + + var totalAvailableBalance: Int64 { + transaparent.confirmed + sapling.confirmed + orchard.confirmed + } + + var totalUnconfirmedBalance: Int64 { + transaparent.unconfirmed + sapling.unconfirmed + orchard.unconfirmed + } + + var totalBalance: Int64 { + totalAvailableBalance + totalUnconfirmedBalance + } +} /** - Concrete Wallet Balance. - */ +Concrete Wallet Balance. +*/ struct Balance: WalletBalance { var transaparent: Funds var sapling: Funds @@ -77,25 +102,7 @@ struct ZcashFunds: Funds { static var noFunds: Funds { ZcashFunds(confirmed: 0, unconfirmed: 0) } + var confirmed: Int64 var unconfirmed: Int64 - -} - -extension WalletBalance { - static var nullBalance: WalletBalance { - Balance(transaparent: ZcashFunds.noFunds, sapling: ZcashFunds.noFunds, orchard: ZcashFunds.noFunds) - } - - var totalAvailableBalance: Int64 { - transaparent.confirmed + sapling.confirmed + orchard.confirmed - } - - var totalUnconfirmedBalance: Int64 { - transaparent.unconfirmed + sapling.unconfirmed + orchard.unconfirmed - } - - var totalBalance: Int64 { - totalAvailableBalance + totalUnconfirmedBalance - } } diff --git a/secant/Routers/AppRouter.swift b/secant/Routers/AppRouter.swift index 4bf96c7..c52b9f1 100644 --- a/secant/Routers/AppRouter.swift +++ b/secant/Routers/AppRouter.swift @@ -15,60 +15,40 @@ enum AppRouterScreen { } class AppRouter: Router { - - // MARK: - Published vars @Published var screen: AppRouterScreen = .appLoading - - // MARK: - Private vars - - // MARK: - Internal vars + var services: Services - - // MARK: - Initialization init(services: Services) { self.services = services } - - // MARK: - Methods - + @ViewBuilder func rootView() -> some View { // Add your content here NavigationView { AppRouterView(router: self) } } - + @ViewBuilder func createNew() -> some View { Text("Create New") } - + @ViewBuilder func home() -> some View { Text("Home Screen") } - + @ViewBuilder func loadingScreen() -> some View { Text("Loading") } } - struct AppRouterView: View { @StateObject var router: AppRouter - - @ViewBuilder func viewForScreen(_ screen: AppRouterScreen) -> some View { - switch self.router.screen { - case .appLoading: - self.router.loadingScreen() - case .createRestoreWallet: - self.router.createNew() - case .home: - self.router.home() - } - } + var body: some View { viewForScreen(router.screen) - .onAppear() { + .onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + 1) { if router.services.keyStorage.keysPresent { router.screen = .home @@ -78,4 +58,12 @@ struct AppRouterView: View { } } } + + @ViewBuilder func viewForScreen(_ screen: AppRouterScreen) -> some View { + switch router.screen { + case .appLoading: router.loadingScreen() + case .createRestoreWallet: router.createNew() + case .home: router.home() + } + } } diff --git a/secant/Screens/Backup Wallet/BackupWalletScreen.swift b/secant/Screens/Backup Wallet/BackupWalletScreen.swift index ce9c172..d67ab5c 100644 --- a/secant/Screens/Backup Wallet/BackupWalletScreen.swift +++ b/secant/Screens/Backup Wallet/BackupWalletScreen.swift @@ -7,16 +7,15 @@ import SwiftUI -protocol BackupWalletScreenRouter: AnyObject { -} +protocol BackupWalletScreenRouter: AnyObject {} struct BackupWalletScreen: View { - @State var router: BackupWalletScreenRouter? - @ObservedObject var viewModel: BackupWalletScreenViewModel - + + @State var router: BackupWalletScreenRouter? + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Text("Hello, World!") } } diff --git a/secant/Screens/Backup Wallet/BackupWalletScreenViewModel.swift b/secant/Screens/Backup Wallet/BackupWalletScreenViewModel.swift index 000ae11..85b0d61 100644 --- a/secant/Screens/Backup Wallet/BackupWalletScreenViewModel.swift +++ b/secant/Screens/Backup Wallet/BackupWalletScreenViewModel.swift @@ -5,9 +5,7 @@ // Created by Francisco Gindre on 8/9/21. // -import Foundation import Combine +import Foundation -class BackupWalletScreenViewModel: BaseViewModel, ObservableObject { - -} +class BackupWalletScreenViewModel: BaseViewModel, ObservableObject {} diff --git a/secant/Screens/Balance/BalanceScreen.swift b/secant/Screens/Balance/BalanceScreen.swift index 0f9f9f7..324a7e4 100644 --- a/secant/Screens/Balance/BalanceScreen.swift +++ b/secant/Screens/Balance/BalanceScreen.swift @@ -7,16 +7,15 @@ import SwiftUI -protocol BalanceScreenRouter: AnyObject { -} +protocol BalanceScreenRouter: AnyObject {} struct BalanceScreen: View { - @State var router: BalanceScreenRouter? - @ObservedObject var viewModel: BalanceScreenViewModel - + + @State var router: BalanceScreenRouter? + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Text("Hello, World!") } } diff --git a/secant/Screens/Balance/BalanceScreenViewModel.swift b/secant/Screens/Balance/BalanceScreenViewModel.swift index 3c1ffc7..b0666e0 100644 --- a/secant/Screens/Balance/BalanceScreenViewModel.swift +++ b/secant/Screens/Balance/BalanceScreenViewModel.swift @@ -5,9 +5,7 @@ // Created by Francisco Gindre on 8/12/21. // -import Foundation import Combine +import Foundation -class BalanceScreenViewModel: BaseViewModel, ObservableObject { - -} +class BalanceScreenViewModel: BaseViewModel, ObservableObject {} diff --git a/secant/Screens/History/HistoryScreen.swift b/secant/Screens/History/HistoryScreen.swift index 6aed7a2..0d1a76c 100644 --- a/secant/Screens/History/HistoryScreen.swift +++ b/secant/Screens/History/HistoryScreen.swift @@ -7,16 +7,15 @@ import SwiftUI -protocol HistoryScreenRouter: AnyObject { -} +protocol HistoryScreenRouter: AnyObject {} struct HistoryScreen: View { - @State var router: HistoryScreenRouter? - @ObservedObject var viewModel: HistoryScreenViewModel - + + @State var router: HistoryScreenRouter? + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Text("Hello, World!") } } diff --git a/secant/Screens/History/HistoryScreenViewModel.swift b/secant/Screens/History/HistoryScreenViewModel.swift index 07a01d7..710c5d5 100644 --- a/secant/Screens/History/HistoryScreenViewModel.swift +++ b/secant/Screens/History/HistoryScreenViewModel.swift @@ -5,9 +5,7 @@ // Created by Francisco Gindre on 8/12/21. // -import Foundation import Combine +import Foundation -class HistoryScreenViewModel: BaseViewModel, ObservableObject { - -} +class HistoryScreenViewModel: BaseViewModel, ObservableObject {} diff --git a/secant/Screens/Home/HomeScreen.swift b/secant/Screens/Home/HomeScreen.swift index 7406b3d..337b5ca 100644 --- a/secant/Screens/Home/HomeScreen.swift +++ b/secant/Screens/Home/HomeScreen.swift @@ -17,9 +17,9 @@ protocol HomeScreenRouter: AnyObject { } struct HomeScreen: View { - @State var router: HomeScreenRouter? - @ObservedObject var viewModel: HomeScreenViewModel + + @State var router: HomeScreenRouter? var body: some View { VStack { @@ -32,18 +32,18 @@ struct HomeScreen: View { .navigationBarTitle("", displayMode: .inline) .navigationBarItems( leading: qrCodeButton, - trailing: profileButton) + trailing: profileButton + ) } - + @ViewBuilder var qrCodeButton: some View { Button(action: {}, label: { Image(systemName: "qrcode.viewfinder") - .frame(width: 20, height: 20, alignment: /*@START_MENU_TOKEN@*/.center/*@END_MENU_TOKEN@*/) + .frame(width: 20, height: 20, alignment: .center) }) .contentShape(Circle()) - } - + @ViewBuilder var profileButton: some View { Button(action: {}, label: { Image(systemName: "person.crop.circle") @@ -51,21 +51,21 @@ struct HomeScreen: View { }) .contentShape(Circle()) } - + @ViewBuilder var requestButton: some View { Button(action: {}, label: { Text("Request ZEC") }) .buttonStyle(PlainButton()) } - + @ViewBuilder var sendButton: some View { Button(action: {}, label: { Text("Send ZEC") }) .buttonStyle(PlainButton()) } - + @ViewBuilder var historyButton: some View { Button(action: {}, label: { Text("History") @@ -74,14 +74,33 @@ struct HomeScreen: View { } } +// MARK: - Previews + struct HomeScreenPreviews: PreviewProvider { static var previews: some View { NavigationView { - HomeScreen(viewModel: HomeScreenViewModel.mockWithValues(services: MockServices(), status: .offline, balance: mockBalance, fiatConversion: 1.12453)) + HomeScreen( + viewModel: HomeScreenViewModel.mockWithValues( + services: MockServices(), + status: .offline, + balance: mockBalance, + fiatConversion: 1.12453 + ) + ) } } - + static var mockBalance: WalletBalance { - Balance(transaparent: ZcashFunds.noFunds, sapling: ZcashFunds(confirmed: 123456790, unconfirmed: 0), orchard: ZcashFunds(confirmed: 0, unconfirmed: 0)) + Balance( + transaparent: ZcashFunds.noFunds, + sapling: ZcashFunds( + confirmed: 123456790, + unconfirmed: 0 + ), + orchard: ZcashFunds( + confirmed: 0, + unconfirmed: 0 + ) + ) } } diff --git a/secant/Screens/Home/HomeScreenViewModel.swift b/secant/Screens/Home/HomeScreenViewModel.swift index 8da629b..28cb475 100644 --- a/secant/Screens/Home/HomeScreenViewModel.swift +++ b/secant/Screens/Home/HomeScreenViewModel.swift @@ -5,8 +5,8 @@ // Created by Francisco Gindre on 8/9/21. // -import Foundation import Combine +import Foundation class HomeScreenViewModel: BaseViewModel, ObservableObject { enum Status { @@ -14,24 +14,24 @@ class HomeScreenViewModel: BaseViewModel, ObservableObject { case offline case error(error: Error) } - + @Published var balance: WalletBalance = Balance.nullBalance - @Published var fiatConversion: Decimal = 0 - @Published var status = Status.offline - } extension HomeScreenViewModel { - static func mockWithValues(services: Services, - status: Status, - balance: WalletBalance, - fiatConversion: Decimal) -> HomeScreenViewModel { - let vm = HomeScreenViewModel(services: services) - vm.status = status - vm.balance = balance - vm.fiatConversion = fiatConversion - return vm + static func mockWithValues( + services: Services, + status: Status, + balance: WalletBalance, + fiatConversion: Decimal + ) -> HomeScreenViewModel { + let viewModel = HomeScreenViewModel(services: services) + viewModel.status = status + viewModel.balance = balance + viewModel.fiatConversion = fiatConversion + + return viewModel } } diff --git a/secant/Screens/Profile/ProfileScreen.swift b/secant/Screens/Profile/ProfileScreen.swift index eb5ff1a..5c47256 100644 --- a/secant/Screens/Profile/ProfileScreen.swift +++ b/secant/Screens/Profile/ProfileScreen.swift @@ -7,16 +7,15 @@ import SwiftUI -protocol ProfileScreenRouter: AnyObject { -} +protocol ProfileScreenRouter: AnyObject {} struct ProfileScreen: View { - @State var router: ProfileScreenRouter? - @ObservedObject var viewModel: ProfileScreenViewModel - + + @State var router: ProfileScreenRouter? + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Text("Hello, World!") } } diff --git a/secant/Screens/Profile/ProfileScreenViewModel.swift b/secant/Screens/Profile/ProfileScreenViewModel.swift index c5bdd0d..bbad7c9 100644 --- a/secant/Screens/Profile/ProfileScreenViewModel.swift +++ b/secant/Screens/Profile/ProfileScreenViewModel.swift @@ -5,9 +5,7 @@ // Created by Francisco Gindre on 8/12/21. // -import Foundation import Combine +import Foundation -class ProfileScreenViewModel: BaseViewModel, ObservableObject { - -} +class ProfileScreenViewModel: BaseViewModel, ObservableObject {} diff --git a/secant/Screens/Request ZEC/RequestZcashScreen.swift b/secant/Screens/Request ZEC/RequestZcashScreen.swift index 1686722..6936b82 100644 --- a/secant/Screens/Request ZEC/RequestZcashScreen.swift +++ b/secant/Screens/Request ZEC/RequestZcashScreen.swift @@ -7,16 +7,15 @@ import SwiftUI -protocol RequestZcashScreenRouter: AnyObject { -} +protocol RequestZcashScreenRouter: AnyObject {} struct RequestZcashScreen: View { - @State var router: RequestZcashScreenRouter? - @ObservedObject var viewModel: RequestZcashScreenViewModel - + + @State var router: RequestZcashScreenRouter? + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Text("Hello, World!") } } diff --git a/secant/Screens/Request ZEC/RequestZcashScreenViewModel.swift b/secant/Screens/Request ZEC/RequestZcashScreenViewModel.swift index 1e62f43..de1f33f 100644 --- a/secant/Screens/Request ZEC/RequestZcashScreenViewModel.swift +++ b/secant/Screens/Request ZEC/RequestZcashScreenViewModel.swift @@ -5,9 +5,7 @@ // Created by Francisco Gindre on 8/12/21. // -import Foundation import Combine +import Foundation -class RequestZcashScreenViewModel: BaseViewModel, ObservableObject { - -} +class RequestZcashScreenViewModel: BaseViewModel, ObservableObject {} diff --git a/secant/Screens/Restore Wallet/RestoreWalletScreen.swift b/secant/Screens/Restore Wallet/RestoreWalletScreen.swift index 5da48ea..5289af7 100644 --- a/secant/Screens/Restore Wallet/RestoreWalletScreen.swift +++ b/secant/Screens/Restore Wallet/RestoreWalletScreen.swift @@ -7,20 +7,19 @@ import SwiftUI -protocol RestoreWalletScreenRouter: AnyObject { -} +protocol RestoreWalletScreenRouter: AnyObject {} struct RestoreWalletScreen: View { - @State var router: RestoreWalletScreenRouter? - @ObservedObject var viewModel: RestoreWalletScreenViewModel - + + @State var router: RestoreWalletScreenRouter? + var body: some View { VStack { Text("Enter Seed Phrase") - + TextEditor(text: $viewModel.seedText) - + Button(action: {}, label: { Text("Restore Seed Phrase") }) diff --git a/secant/Screens/Restore Wallet/RestoreWalletScreenViewModel.swift b/secant/Screens/Restore Wallet/RestoreWalletScreenViewModel.swift index 7b8f6c4..c775926 100644 --- a/secant/Screens/Restore Wallet/RestoreWalletScreenViewModel.swift +++ b/secant/Screens/Restore Wallet/RestoreWalletScreenViewModel.swift @@ -5,12 +5,11 @@ // Created by Francisco Gindre on 8/9/21. // -import Foundation import Combine +import Foundation class RestoreWalletScreenViewModel: BaseViewModel, ObservableObject { - @Published var seedText: String = "" - + func restore() {} } diff --git a/secant/Screens/Scan/ScanQrScreen.swift b/secant/Screens/Scan/ScanQrScreen.swift index fa75f08..efbc638 100644 --- a/secant/Screens/Scan/ScanQrScreen.swift +++ b/secant/Screens/Scan/ScanQrScreen.swift @@ -7,16 +7,15 @@ import SwiftUI -protocol ScanQrScreenRouter: AnyObject { -} +protocol ScanQrScreenRouter: AnyObject {} struct ScanQrScreen: View { - @State var router: ScanQrScreenRouter? - @ObservedObject var viewModel: ScanQrScreenViewModel - + + @State var router: ScanQrScreenRouter? + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Text("Hello, World!") } } diff --git a/secant/Screens/Scan/ScanQrScreenViewModel.swift b/secant/Screens/Scan/ScanQrScreenViewModel.swift index 51f956c..71df046 100644 --- a/secant/Screens/Scan/ScanQrScreenViewModel.swift +++ b/secant/Screens/Scan/ScanQrScreenViewModel.swift @@ -5,9 +5,7 @@ // Created by Francisco Gindre on 8/12/21. // -import Foundation import Combine +import Foundation -class ScanQrScreenViewModel: BaseViewModel, ObservableObject { - -} +class ScanQrScreenViewModel: BaseViewModel, ObservableObject {} diff --git a/secant/Screens/Send ZEC/SendScreen.swift b/secant/Screens/Send ZEC/SendScreen.swift index 4f4a0e1..a8f2b11 100644 --- a/secant/Screens/Send ZEC/SendScreen.swift +++ b/secant/Screens/Send ZEC/SendScreen.swift @@ -7,16 +7,15 @@ import SwiftUI -protocol SendScreenRouter: AnyObject { -} +protocol SendScreenRouter: AnyObject {} struct SendScreen: View { - @State var router: SendScreenRouter? - @ObservedObject var viewModel: SendScreenViewModel - + + @State var router: SendScreenRouter? + var body: some View { - Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) + Text("Hello, World!") } } diff --git a/secant/Screens/Send ZEC/SendScreenViewModel.swift b/secant/Screens/Send ZEC/SendScreenViewModel.swift index 852621d..8ece18e 100644 --- a/secant/Screens/Send ZEC/SendScreenViewModel.swift +++ b/secant/Screens/Send ZEC/SendScreenViewModel.swift @@ -5,9 +5,7 @@ // Created by Francisco Gindre on 8/12/21. // -import Foundation import Combine +import Foundation -class SendScreenViewModel: BaseViewModel, ObservableObject { - -} +class SendScreenViewModel: BaseViewModel, ObservableObject {} diff --git a/secant/Screens/Welcome Screen/WelcomeScreen.swift b/secant/Screens/Welcome Screen/WelcomeScreen.swift index c9dae8b..c88e900 100644 --- a/secant/Screens/Welcome Screen/WelcomeScreen.swift +++ b/secant/Screens/Welcome Screen/WelcomeScreen.swift @@ -7,22 +7,21 @@ import SwiftUI -protocol WelcomeScreenRouter: AnyObject { - -} +protocol WelcomeScreenRouter: AnyObject {} struct WelcomeScreen: View { - @State var router: WelcomeScreenRouter? - @ObservedObject var viewModel: WelcomeScreenViewModel - + + @State var router: WelcomeScreenRouter? + var body: some View { VStack { - Spacer() + Text("Welcome and Onboarding") + Spacer() - + VStack(alignment: .center, spacing: 16) { Button(action: { self.viewModel.restoreWallet() @@ -30,7 +29,7 @@ struct WelcomeScreen: View { Text("RESTORE WALLET") }) .buttonStyle(PlainButton()) - + Button(action: { self.viewModel.createNew() }, label: { diff --git a/secant/Screens/Welcome Screen/WelcomeScreenViewModel.swift b/secant/Screens/Welcome Screen/WelcomeScreenViewModel.swift index 169b477..bf1d028 100644 --- a/secant/Screens/Welcome Screen/WelcomeScreenViewModel.swift +++ b/secant/Screens/Welcome Screen/WelcomeScreenViewModel.swift @@ -5,11 +5,10 @@ // Created by Francisco Gindre on 8/9/21. // -import Foundation import Combine +import Foundation class WelcomeScreenViewModel: BaseViewModel, ObservableObject { - func createNew() {} func restoreWallet() {} } diff --git a/secant/SecantApp.swift b/secant/SecantApp.swift index 7a63e93..060ebab 100644 --- a/secant/SecantApp.swift +++ b/secant/SecantApp.swift @@ -9,8 +9,8 @@ import SwiftUI @main struct SecantApp: App { - @StateObject var appRouter = AppRouter(services: MockServices()) + var body: some Scene { WindowGroup { appRouter.rootView() diff --git a/secant/Stubs/MockServices.swift b/secant/Stubs/MockServices.swift index d518dd3..05d2fa0 100644 --- a/secant/Stubs/MockServices.swift +++ b/secant/Stubs/MockServices.swift @@ -7,18 +7,21 @@ import Foundation +// swiftlint:disable line_length class MockServices: Services { - init(){} var networkProvider: ZcashNetworkProvider { MockNetworkProvider() } + var seedHandler: MnemonicSeedPhraseHandling { MockMnemonicPhraseHandling() } - + var keyStorage: KeyStoring { MockKeyStoring() } + + init() {} } class MockNetworkProvider: ZcashNetworkProvider { @@ -28,87 +31,90 @@ class MockNetworkProvider: ZcashNetworkProvider { } class MockMnemonicPhraseHandling: MnemonicSeedPhraseHandling { - class TestSeed { - /** - test account: "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" - */ - let seedString = Data(base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==")! - + Test account: "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" + */ + let seedString = Data( + base64Encoded: "9VDVOZZZOWWHpZtq1Ebridp3Qeux5C+HwiRR0g7Oi7HgnMs8Gfln83+/Q1NnvClcaSwM4ADFL1uZHxypEWlWXg==" + )!// swiftlint:disable:this force_unwrapping + func seed() -> [UInt8] { [UInt8](seedString) } } - + func randomMnemonic() throws -> String { "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" } - + func randomMnemonicWords() throws -> [String] { - "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread".components(separatedBy: " ") + "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" + .components(separatedBy: " ") } - + func toSeed(mnemonic: String) throws -> [UInt8] { TestSeed().seed() } - + func asWords(mnemonic: String) throws -> [String] { - "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread".components(separatedBy: " ") + "still champion voice habit trend flight survey between bitter process artefact blind carbon truly provide dizzy crush flush breeze blouse charge solid fish spread" + .components(separatedBy: " ") } - + func isValid(mnemonic: String) throws {} - - } class MockKeyStoring: KeyStoring { var birthday: BlockHeight? var phrase: String? + func importBirthday(_ height: BlockHeight) throws { guard birthday == nil else { throw KeyStoringError.alreadyImported } + birthday = height } - + func exportBirthday() throws -> BlockHeight { - guard let b = birthday else { + guard let birthday = birthday else { throw KeyStoringError.uninitializedWallet } - return b + + return birthday } - + func importPhrase(bip39 phrase: String) throws { guard self.phrase == nil else { throw KeyStoringError.alreadyImported } + self.phrase = phrase } - + func exportPhrase() throws -> String { - guard let p = self.phrase else { + guard let phrase = self.phrase else { throw KeyStoringError.uninitializedWallet } - return p + + return phrase } - + var keysPresent: Bool { return self.phrase != nil && self.birthday != nil } - + func nukePhrase() { self.phrase = nil } - + func nukeBirthday() { self.birthday = nil } - + func nukeWallet() { nukePhrase() nukeBirthday() } - - } diff --git a/secant/Stubs/ZcashSDKStubs.swift b/secant/Stubs/ZcashSDKStubs.swift index ecfad1e..ab9275b 100644 --- a/secant/Stubs/ZcashSDKStubs.swift +++ b/secant/Stubs/ZcashSDKStubs.swift @@ -6,7 +6,9 @@ // import Foundation + public typealias BlockHeight = Int + public protocol ZcashNetwork { var networkType: NetworkType { get } var constants: NetworkConstants.Type { get } @@ -15,13 +17,11 @@ public protocol ZcashNetwork { public enum NetworkType { case mainnet case testnet - + var networkId: UInt32 { switch self { - case .mainnet: - return 1 - case .testnet: - return 0 + case .mainnet: return 1 + case .testnet: return 0 } } } @@ -29,23 +29,18 @@ public enum NetworkType { extension NetworkType { static func forChainName(_ chainame: String) -> NetworkType? { switch chainame { - case "test": - return .testnet - case "main": - return .mainnet - default: - return nil + case "test": return .testnet + case "main": return .mainnet + default: return nil } } } -public class ZcashNetworkBuilder { +public enum ZcashNetworkBuilder { public static func network(for networkType: NetworkType) -> ZcashNetwork { switch networkType { - case .mainnet: - return ZcashMainnet() - case .testnet: - return ZcashTestnet() + case .mainnet: return ZcashMainnet() + case .testnet: return ZcashTestnet() } } } @@ -61,182 +56,182 @@ class ZcashMainnet: ZcashNetwork { } /** - Constants of ZcashLightClientKit. this constants don't - */ -public class ZcashSDK { - +Constants of ZcashLightClientKit. +*/ +public enum ZcashSDK { /** - The number of zatoshi that equal 1 ZEC. - */ - public static var ZATOSHI_PER_ZEC: BlockHeight = 100_000_000 - + The number of zatoshi that equal 1 ZEC. + */ + public static var zatoshiPerZEC: BlockHeight = 100_000_000 + /** - The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design. - */ - public static var MAX_REORG_SIZE = 100 + The theoretical maximum number of blocks in a reorg, due to other bottlenecks in the protocol design. + */ + public static var maxReorgSize = 100 + /** - The amount of blocks ahead of the current height where new transactions are set to expire. This value is controlled - by the rust backend but it is helpful to know what it is set to and should be kept in sync. - */ - public static var EXPIRY_OFFSET = 20 + The amount of blocks ahead of the current height where new transactions are set to expire. This value is controlled by the rust backend but it is helpful to know what it is set to and should be kept in sync. + */ + public static var expiryOffset = 20 + // // Defaults // /** - Default size of batches of blocks to request from the compact block service. - */ - public static var DEFAULT_BATCH_SIZE = 100 + Default size of batches of blocks to request from the compact block service. + */ + public static var defaultBatchSize = 100 + /** - Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average - block time. - */ - public static var DEFAULT_POLL_INTERVAL: TimeInterval = 20 + Default amount of time, in in seconds, to poll for new blocks. Typically, this should be about half the average block time. + */ + public static var defaultPollInterval: TimeInterval = 20 + /** - Default attempts at retrying. - */ - public static var DEFAULT_RETRIES: Int = 5 + Default attempts at retrying. + */ + public static var defaultRetrie: Int = 5 + /** - The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than - this before retyring. - */ - public static var DEFAULT_MAX_BACKOFF_INTERVAL: TimeInterval = 600 + The default maximum amount of time to wait during retry backoff intervals. Failed loops will never wait longer than this before retyring. + */ + public static var defaultMaxBackoffInterval: TimeInterval = 600 + /** - Default number of blocks to rewind when a chain reorg is detected. This should be large enough to recover from the - reorg but smaller than the theoretical max reorg size of 100. - */ - public static var DEFAULT_REWIND_DISTANCE: Int = 10 + Default number of blocks to rewind when a chain reorg is detected. This should be large enough to recover from the reorg but smaller than the theoretical max reorg size of 100. + */ + public static var defaultRewindDistance: Int = 10 + /** - The number of blocks to allow before considering our data to be stale. This usually helps with what to do when - returning from the background and is exposed via the Synchronizer's isStale function. - */ - public static var DEFAULT_STALE_TOLERANCE: Int = 10 - + The number of blocks to allow before considering our data to be stale. This usually helps with what to do when returning from the background and is exposed via the Synchronizer's isStale function. + */ + public static var defaultStaleTolerance: Int = 10 + /** - Default Name for LibRustZcash data.db - */ - public static var DEFAULT_DATA_DB_NAME = "data.db" - + Default Name for LibRustZcash data.db + */ + public static var defaultDataDbName = "data.db" + /** - Default Name for Compact Block caches db - */ - public static var DEFAULT_CACHES_DB_NAME = "caches.db" + Default Name for Compact Block caches db + */ + public static var defaultCachesDbName = "caches.db" + /** - Default name for pending transactions db - */ - public static var DEFAULT_PENDING_DB_NAME = "pending.db" - + Default name for pending transactions db + */ + public static var defaultPendingDbName = "pending.db" + /** - File name for the sapling spend params - */ - public static var SPEND_PARAM_FILE_NAME = "sapling-spend.params" + File name for the sapling spend params + */ + public static var spendParamFileName = "sapling-spend.params" + /** - File name for the sapling output params - */ - public static var OUTPUT_PARAM_FILE_NAME = "sapling-output.params" + File name for the sapling output params + */ + public static var outputParamFileName = "sapling-output.params" + /** - The Url that is used by default in zcashd. - We'll want to make this externally configurable, rather than baking it into the SDK but - this will do for now, since we're using a cloudfront URL that already redirects. - */ - public static var CLOUD_PARAM_DIR_URL = "https://z.cash/downloads/" + The Url that is used by default in zcashd. We'll want to make this externally configurable, rather than baking it into the SDK but this will do for now, since we're using a cloudfront URL that already redirects. + */ + public static var cloudParamDirURL = "https://z.cash/downloads/" } public protocol NetworkConstants { - /** - The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks - prior to this height, at all. - */ - static var SAPLING_ACTIVATION_HEIGHT: BlockHeight { get } - + The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any block prior to this height, at all. + */ + static var saplingActivationHeight: BlockHeight { get } + /** - Default Name for LibRustZcash data.db - */ - static var DEFAULT_DATA_DB_NAME: String { get } + Default Name for LibRustZcash data.db + */ + static var defaultDataDbName: String { get } + /** - Default Name for Compact Block caches db - */ - static var DEFAULT_CACHES_DB_NAME: String { get } + Default Name for Compact Block caches db + */ + static var defaultCachesDbName: String { get } + /** - Default name for pending transactions db - */ - static var DEFAULT_PENDING_DB_NAME: String { get } - static var DEFAULT_DB_NAME_PREFIX: String { get } - + Default name for pending transactions db + */ + static var defaultPendingDbName: String { get } + + static var defaultDbNamePrefix: String { get } + /** - fixed height where the SDK considers that the ZIP-321 was deployed. This is a workaround - for librustzcash not figuring out the tx fee from the tx itself. - */ - static var FEE_CHANGE_HEIGHT: BlockHeight { get } - + Fixed height where the SDK considers that the ZIP-321 was deployed. This is a workaround for librustzcash not figuring out the tx fee from the tx itself. + */ + static var feeChangeHeight: BlockHeight { get } + static func defaultFee(for height: BlockHeight) -> Int64 - } public extension NetworkConstants { - static func defaultFee(for height: BlockHeight = BlockHeight.max) -> Int64 { - guard height >= FEE_CHANGE_HEIGHT else { return 10_000 } - + guard height >= feeChangeHeight else { return 10_000 } + return 1_000 } } public class ZcashSDKMainnetConstants: NetworkConstants { - + /** + The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks prior to this height, at all. + */ + public static var saplingActivationHeight: BlockHeight = 419_200 + + /** + Default Name for LibRustZcash data.db + */ + public static var defaultDataDbName = "data.db" + + /** + Default Name for Compact Block caches db + */ + public static var defaultCachesDbName = "caches.db" + + /** + Default name for pending transactions db + */ + public static var defaultPendingDbName = "pending.db" + + public static var defaultDbNamePrefix = "ZcashSdk_mainnet_" + + public static var feeChangeHeight: BlockHeight = 1_077_550 + private init() {} - - /** - The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks - prior to this height, at all. - */ - public static var SAPLING_ACTIVATION_HEIGHT: BlockHeight = 419_200 - - /** - Default Name for LibRustZcash data.db - */ - public static var DEFAULT_DATA_DB_NAME = "data.db" - /** - Default Name for Compact Block caches db - */ - public static var DEFAULT_CACHES_DB_NAME = "caches.db" - /** - Default name for pending transactions db - */ - public static var DEFAULT_PENDING_DB_NAME = "pending.db" - - public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_mainnet_" - - public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_077_550 } public class ZcashSDKTestnetConstants: NetworkConstants { + /** + The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks prior to this height, at all. + */ + public static var saplingActivationHeight: BlockHeight = 280_000 + + /** + Default Name for LibRustZcash data.db + */ + public static var defaultDataDbName = "data.db" + + /** + Default Name for Compact Block caches db + */ + public static var defaultCachesDbName = "caches.db" + + /** + Default name for pending transactions db + */ + public static var defaultPendingDbName = "pending.db" + + public static var defaultDbNamePrefix = "ZcashSdk_testnet_" + + /** + Estimated height where wallets are supposed to change the fee + */ + public static var feeChangeHeight: BlockHeight = 1_028_500 + private init() {} - - /** - The height of the first sapling block. When it comes to shielded transactions, we do not need to consider any blocks - prior to this height, at all. - */ - public static var SAPLING_ACTIVATION_HEIGHT: BlockHeight = 280_000 - - /** - Default Name for LibRustZcash data.db - */ - public static var DEFAULT_DATA_DB_NAME = "data.db" - /** - Default Name for Compact Block caches db - */ - public static var DEFAULT_CACHES_DB_NAME = "caches.db" - /** - Default name for pending transactions db - */ - public static var DEFAULT_PENDING_DB_NAME = "pending.db" - - public static var DEFAULT_DB_NAME_PREFIX = "ZcashSdk_testnet_" - - /** - Estimated height where wallets are supposed to change the fee - */ - public static var FEE_CHANGE_HEIGHT: BlockHeight = 1_028_500 - } diff --git a/secant/UI Components/PlainButton.swift b/secant/UI Components/PlainButton.swift index af45fee..b5a55fe 100644 --- a/secant/UI Components/PlainButton.swift +++ b/secant/UI Components/PlainButton.swift @@ -12,9 +12,9 @@ struct PlainButton: ButtonStyle { case light case bold } - + var style = Theme.bold - + func makeBody(configuration: Configuration) -> some View { configuration.label .foregroundColor(style.foregroundColor) @@ -24,16 +24,18 @@ struct PlainButton: ButtonStyle { } } +// MARK: - Previews + struct PlainButton_Previews: PreviewProvider { static var previews: some View { VStack { - Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: { - /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/ + Button(action: {}, label: { + Text("Button") }) .buttonStyle(PlainButton()) - - Button(action: /*@START_MENU_TOKEN@*/{}/*@END_MENU_TOKEN@*/, label: { - /*@START_MENU_TOKEN@*/Text("Button")/*@END_MENU_TOKEN@*/ + + Button(action: {}, label: { + Text("Button") }) .buttonStyle(PlainButton(style: .bold)) } @@ -41,22 +43,20 @@ struct PlainButton_Previews: PreviewProvider { } } +// MARK: - Theme + extension PlainButton.Theme { var background: some View { switch self { - case .bold: - return Color.black - default: - return Color.white + case .bold: return Color.black + default: return Color.white } } - + var foregroundColor: Color { switch self { - case .bold: - return Color.white - default: - return Color.black + case .bold: return Color.white + default: return Color.black } } } diff --git a/secant/Utilities/SwiftUI+secant.swift b/secant/Utilities/SwiftUI+secant.swift index 1c7002c..b66a319 100644 --- a/secant/Utilities/SwiftUI+secant.swift +++ b/secant/Utilities/SwiftUI+secant.swift @@ -8,7 +8,6 @@ import Foundation import SwiftUI - extension Font { static func zboto(_ size: CGFloat) -> Font { Font.custom("Zboto", size: size) diff --git a/secantTests/secantTests.swift b/secantTests/secantTests.swift index 92754db..7631ea9 100644 --- a/secantTests/secantTests.swift +++ b/secantTests/secantTests.swift @@ -8,13 +8,14 @@ import XCTest @testable import secant_testnet -class secantTests: XCTestCase { - - override func setUpWithError() throws { +class SecantTests: XCTestCase { + override func setUp() { + super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. } - override func tearDownWithError() throws { + override func tearDown() { + super.tearDown() // Put teardown code here. This method is called after the invocation of each test method in the class. } @@ -29,5 +30,4 @@ class secantTests: XCTestCase { // Put the code you want to measure the time of here. } } - } diff --git a/secantUITests/secantUITests.swift b/secantUITests/secantUITests.swift index 493b6d9..12d8635 100644 --- a/secantUITests/secantUITests.swift +++ b/secantUITests/secantUITests.swift @@ -7,18 +7,21 @@ import XCTest -class secantUITests: XCTestCase { - - override func setUpWithError() throws { +class SecantUITests: XCTestCase { + override func setUp() { + super.setUp() // Put setup code here. This method is called before the invocation of each test method in the class. // In UI tests it is usually best to stop immediately when a failure occurs. continueAfterFailure = false - // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + // In UI tests it’s important to set the initial state - such as interface + // orientation - required for your tests before they run. + // The setUp method is a good place to do this. } - override func tearDownWithError() throws { + override func tearDown() { + super.tearDown() // Put teardown code here. This method is called after the invocation of each test method in the class. } diff --git a/xctemplates/Router Templates/Router.xctemplate/___FILEBASENAME___Router.swift b/xctemplates/Router Templates/Router.xctemplate/___FILEBASENAME___Router.swift index 7ba1f03..f39c22f 100644 --- a/xctemplates/Router Templates/Router.xctemplate/___FILEBASENAME___Router.swift +++ b/xctemplates/Router Templates/Router.xctemplate/___FILEBASENAME___Router.swift @@ -4,28 +4,16 @@ import Foundation import SwiftUI class ___FILEBASENAMEASIDENTIFIER___: Router { - - // MARK: - Published vars - // Put published vars here - - // MARK: - Private vars - - // MARK: - Internal vars var services: Services - - // MARK: - Initialization init(services: Services) { self.services = services } - - // MARK: - Methods - + func rootView() -> some View { // Add your content here NavigationView { - Text("Hello Word") + Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) } } - } diff --git a/xctemplates/Router Templates/SwiftUI Screen.xctemplate/___FILEBASENAME___Screen.swift b/xctemplates/Router Templates/SwiftUI Screen.xctemplate/___FILEBASENAME___Screen.swift index 5ea1633..11ecb9a 100644 --- a/xctemplates/Router Templates/SwiftUI Screen.xctemplate/___FILEBASENAME___Screen.swift +++ b/xctemplates/Router Templates/SwiftUI Screen.xctemplate/___FILEBASENAME___Screen.swift @@ -3,13 +3,14 @@ import SwiftUI protocol ___FILEBASENAMEASIDENTIFIER___Router: AnyObject { + } struct ___FILEBASENAMEASIDENTIFIER___: View { - @State var router: ___FILEBASENAMEASIDENTIFIER___Router? - @ObservedObject var viewModel: ___FILEBASENAME___ViewModel - + + @State var router: ___FILEBASENAMEASIDENTIFIER___Router? + var body: some View { Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) } diff --git a/xctemplates/Router Templates/SwiftUI Screen.xctemplate/___FILEBASENAME___ScreenViewModel.swift b/xctemplates/Router Templates/SwiftUI Screen.xctemplate/___FILEBASENAME___ScreenViewModel.swift index 19bbdc1..7a0a70f 100644 --- a/xctemplates/Router Templates/SwiftUI Screen.xctemplate/___FILEBASENAME___ScreenViewModel.swift +++ b/xctemplates/Router Templates/SwiftUI Screen.xctemplate/___FILEBASENAME___ScreenViewModel.swift @@ -4,5 +4,6 @@ import Foundation import Combine class ___FILEBASENAMEASIDENTIFIER___: BaseViewModel, ObservableObject { + }