From 91af5782c39c14cce41fbb5c7ffe8fc68f1fd06d Mon Sep 17 00:00:00 2001 From: Michal Fousek Date: Mon, 3 Oct 2022 15:39:40 +0200 Subject: [PATCH] [#82] Add Sending in progress screen (#430) Closes #82 - Add new `TransactionSendingView` which implements in progress state. - Copied lottie animation from ECC reference wallet. - Update routing in send flow to support new screen. --- secant.xcodeproj/project.pbxproj | 14 ++++- secant/Features/SendFlow/SendFlowStore.swift | 31 ++++++++-- .../Views/TransactionConfirmationView.swift | 8 +-- .../Views/TransactionSendingView.swift | 56 +++++++++++++++++++ .../amberGradientEnd.colorset/Contents.json | 38 +++++++++++++ .../Contents.json | 38 +++++++++++++ .../amberGradientStart.colorset/Contents.json | 38 +++++++++++++ .../Generated/XCAssets+Generated.swift | 3 + .../Resources/Lotties/sendingTransaction.json | 1 + .../Backgrounds/ScreenBackground.swift | 13 +++++ secantTests/SendTests/SendTests.swift | 15 +++++ .../TransactionSendingTests.swift | 51 +++++++++++++++++ 12 files changed, 293 insertions(+), 13 deletions(-) create mode 100644 secant/Features/SendFlow/Views/TransactionSendingView.swift create mode 100644 secant/Resources/Colors.xcassets/ScreenBackground/amberGradientEnd.colorset/Contents.json create mode 100644 secant/Resources/Colors.xcassets/ScreenBackground/amberGradientMiddle.colorset/Contents.json create mode 100644 secant/Resources/Colors.xcassets/ScreenBackground/amberGradientStart.colorset/Contents.json create mode 100644 secant/Resources/Lotties/sendingTransaction.json create mode 100644 secantTests/SnapshotTests/SendSnapshotTests/TransactionSendingTests.swift diff --git a/secant.xcodeproj/project.pbxproj b/secant.xcodeproj/project.pbxproj index f926d47..78625bf 100644 --- a/secant.xcodeproj/project.pbxproj +++ b/secant.xcodeproj/project.pbxproj @@ -71,9 +71,12 @@ 3448CB3228E47666006ADEDB /* NotEnoughFreeSpaceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3128E47666006ADEDB /* NotEnoughFreeSpaceView.swift */; }; 3448CB3428E47787006ADEDB /* WrappedDiskSpaceChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3328E47787006ADEDB /* WrappedDiskSpaceChecker.swift */; }; 3448CB3728E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3628E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift */; }; + 34429C6E28E703CD00F2B929 /* TransactionSendingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34429C6D28E703CD00F2B929 /* TransactionSendingTests.swift */; }; 346715A528E2027D0035F7C4 /* CheckCircleStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346715A428E2027D0035F7C4 /* CheckCircleStore.swift */; }; 346715A828E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */; }; 346D41E428DF0B8600963F36 /* CheckCircle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346D41E328DF0B8600963F36 /* CheckCircle.swift */; }; + 34DA414728E4385800F8CC61 /* TransactionSendingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34DA414628E4385800F8CC61 /* TransactionSendingView.swift */; }; + 34DA414928E439CD00F8CC61 /* sendingTransaction.json in Resources */ = {isa = PBXBuildFile; fileRef = 34DA414828E439CD00F8CC61 /* sendingTransaction.json */; }; 34E0AF0F28DEE4C70034CF37 /* HoldToSendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */; }; 34E0AF1128DEE5220034CF37 /* Wedge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0AF1028DEE5220034CF37 /* Wedge.swift */; }; 34E5F2F328E46DB700C17E5F /* DiskSpaceChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E5F2F228E46DB700C17E5F /* DiskSpaceChecker.swift */; }; @@ -314,9 +317,12 @@ 3448CB3128E47666006ADEDB /* NotEnoughFreeSpaceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotEnoughFreeSpaceView.swift; sourceTree = ""; }; 3448CB3328E47787006ADEDB /* WrappedDiskSpaceChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedDiskSpaceChecker.swift; sourceTree = ""; }; 3448CB3628E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotEnoughFeeSpaceSnapshots.swift; sourceTree = ""; }; + 34429C6D28E703CD00F2B929 /* TransactionSendingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionSendingTests.swift; sourceTree = ""; }; 346715A428E2027D0035F7C4 /* CheckCircleStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckCircleStore.swift; sourceTree = ""; }; 346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionConfirmationSnapshotTests.swift; sourceTree = ""; }; 346D41E328DF0B8600963F36 /* CheckCircle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckCircle.swift; sourceTree = ""; }; + 34DA414628E4385800F8CC61 /* TransactionSendingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionSendingView.swift; sourceTree = ""; }; + 34DA414828E439CD00F8CC61 /* sendingTransaction.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = sendingTransaction.json; sourceTree = ""; }; 34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoldToSendButton.swift; sourceTree = ""; }; 34E0AF1028DEE5220034CF37 /* Wedge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wedge.swift; sourceTree = ""; }; 34E5F2F228E46DB700C17E5F /* DiskSpaceChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskSpaceChecker.swift; sourceTree = ""; }; @@ -738,6 +744,7 @@ isa = PBXGroup; children = ( 346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */, + 34429C6D28E703CD00F2B929 /* TransactionSendingTests.swift */, ); path = SendSnapshotTests; sourceTree = ""; @@ -968,6 +975,7 @@ 9E6612342878341F00C75B70 /* Lotties */ = { isa = PBXGroup; children = ( + 34DA414828E439CD00F8CC61 /* sendingTransaction.json */, 9E6612352878345000C75B70 /* endlessCircleProgress.json */, ); path = Lotties; @@ -1404,10 +1412,11 @@ isa = PBXGroup; children = ( F9C165BB2740403600592F76 /* CreateTransactionView.swift */, + 34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */, F9C165B92740403600592F76 /* TransactionConfirmationView.swift */, 9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */, + 34DA414628E4385800F8CC61 /* TransactionSendingView.swift */, F9C165BD2740403600592F76 /* TransactionSentView.swift */, - 34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */, ); path = Views; sourceTree = ""; @@ -1537,6 +1546,7 @@ buildActionMask = 2147483647; files = ( 0DACFA9327209FA70039EEA5 /* Roboto-Medium.ttf in Resources */, + 34DA414928E439CD00F8CC61 /* sendingTransaction.json in Resources */, 0DACFA9827209FA70039EEA5 /* Roboto-MediumItalic.ttf in Resources */, 0DACFA9427209FA70039EEA5 /* Roboto-BoldItalic.ttf in Resources */, 9E6612362878345000C75B70 /* endlessCircleProgress.json in Resources */, @@ -1631,6 +1641,7 @@ 9EAFEB902808183D00199FC9 /* SandboxStore.swift in Sources */, 0D35CC46277A36E00074316A /* ScrollableWhenScaled.swift in Sources */, 9E39114A2848EEB90073DD9A /* UserPreferencesStorage.swift in Sources */, + 34DA414728E4385800F8CC61 /* TransactionSendingView.swift in Sources */, 9EAB466A2859F42E002904A0 /* WrappedDeeplinkHandler.swift in Sources */, F96B41E9273B501F0021B49A /* WalletEventsFlowView.swift in Sources */, 9E01F8202833861A000EFC57 /* WrappedCaptureDevice.swift in Sources */, @@ -1789,6 +1800,7 @@ 9EDDEAA42829610D00B4100C /* TransactionAddressInputTests.swift in Sources */, 9E7CB6272874269F00A02233 /* ProfileSnapshotTests.swift in Sources */, 9E92AF0828530EBF007367AD /* View+UIImage.swift in Sources */, + 34429C6E28E703CD00F2B929 /* TransactionSendingTests.swift in Sources */, 6654C7442715A4AC00901167 /* OnboardingStoreTests.swift in Sources */, 9E94C62328AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift in Sources */, 9E39112E283F91600073DD9A /* ZatoshiTests.swift in Sources */, diff --git a/secant/Features/SendFlow/SendFlowStore.swift b/secant/Features/SendFlow/SendFlowStore.swift index 82444ab..41412e2 100644 --- a/secant/Features/SendFlow/SendFlowStore.swift +++ b/secant/Features/SendFlow/SendFlowStore.swift @@ -18,6 +18,7 @@ typealias SendFlowViewStore = ViewStore struct SendFlowState: Equatable { enum Route: Equatable { case confirmation + case inProgress case success case failure case done @@ -145,10 +146,10 @@ extension SendFlowReducer { guard let spendingKey = try environment.derivationTool.deriveSpendingKeys(seedBytes, 1).first else { return Effect(value: .updateRoute(.failure)) } - + state.isSendingTransaction = true - - return environment.SDKSynchronizer.sendTransaction( + + let sendTransActionEffect = environment.SDKSynchronizer.sendTransaction( with: spendingKey, zatoshi: state.amount, to: state.address, @@ -158,6 +159,8 @@ extension SendFlowReducer { .receive(on: environment.scheduler) .map(SendFlowAction.sendTransactionResult) .eraseToEffect() + + return .concatenate(Effect(value: .updateRoute(.inProgress)), sendTransActionEffect) } catch { return Effect(value: .updateRoute(.failure)) } @@ -276,22 +279,38 @@ extension SendFlowViewStore { var bindingForConfirmation: Binding { self.routeBinding.map( - extract: { $0 == .confirmation || self.bindingForSuccess.wrappedValue || self.bindingForFailure.wrappedValue }, + extract: { + $0 == .confirmation || + self.bindingForInProgress.wrappedValue || + self.bindingForSuccess.wrappedValue || + self.bindingForFailure.wrappedValue + }, embed: { $0 ? SendFlowState.Route.confirmation : nil } ) } + var bindingForInProgress: Binding { + self.routeBinding.map( + extract: { + $0 == .inProgress || + self.bindingForSuccess.wrappedValue || + self.bindingForFailure.wrappedValue + }, + embed: { $0 ? SendFlowState.Route.inProgress : SendFlowState.Route.confirmation } + ) + } + var bindingForSuccess: Binding { self.routeBinding.map( extract: { $0 == .success || self.bindingForDone.wrappedValue }, - embed: { $0 ? SendFlowState.Route.success : SendFlowState.Route.confirmation } + embed: { $0 ? SendFlowState.Route.success : SendFlowState.Route.inProgress } ) } var bindingForFailure: Binding { self.routeBinding.map( extract: { $0 == .failure || self.bindingForDone.wrappedValue }, - embed: { $0 ? SendFlowState.Route.failure : SendFlowState.Route.confirmation } + embed: { $0 ? SendFlowState.Route.failure : SendFlowState.Route.inProgress } ) } diff --git a/secant/Features/SendFlow/Views/TransactionConfirmationView.swift b/secant/Features/SendFlow/Views/TransactionConfirmationView.swift index 2a1640d..514a2e5 100644 --- a/secant/Features/SendFlow/Views/TransactionConfirmationView.swift +++ b/secant/Features/SendFlow/Views/TransactionConfirmationView.swift @@ -33,12 +33,8 @@ struct TransactionConfirmation: View { } .applyDarkScreenBackground() .navigationLinkEmpty( - isActive: viewStore.bindingForSuccess, - destination: { TransactionSent(viewStore: viewStore) } - ) - .navigationLinkEmpty( - isActive: viewStore.bindingForFailure, - destination: { TransactionFailed(viewStore: viewStore) } + isActive: viewStore.bindingForInProgress, + destination: { TransactionSendingView(viewStore: viewStore) } ) } } diff --git a/secant/Features/SendFlow/Views/TransactionSendingView.swift b/secant/Features/SendFlow/Views/TransactionSendingView.swift new file mode 100644 index 0000000..929433b --- /dev/null +++ b/secant/Features/SendFlow/Views/TransactionSendingView.swift @@ -0,0 +1,56 @@ +// +// TransactionSendingView.swift +// secant-testnet +// +// Created by Michal Fousek on 28.09.2022. +// + +import ComposableArchitecture +import Foundation +import SwiftUI + +struct TransactionSendingView: View { + let viewStore: SendFlowViewStore + + var body: some View { + ZStack { + VStack(alignment: .center, spacing: 40) { + Spacer() + Text("Send \(viewStore.amount.decimalString()) ZEC to") + .foregroundColor(Asset.Colors.Text.forDarkBackground.color) + + Text(viewStore.address) + .truncationMode(.middle) + .foregroundColor(Asset.Colors.Text.forDarkBackground.color) + .lineLimit(1) + + LottieAnimation( + isPlaying: true, + filename: "sendingTransaction", + animationType: .circularLoop + ) + .frame(height: 48) + + Spacer() + } + } + .applyAmberScreenBackground() + .navigationBarHidden(true) + .navigationLinkEmpty( + isActive: viewStore.bindingForSuccess, + destination: { TransactionSent(viewStore: viewStore) } + ) + .navigationLinkEmpty( + isActive: viewStore.bindingForFailure, + destination: { TransactionFailed(viewStore: viewStore) } + ) + } +} + +// MARK: - Previews + +struct TransactionSendingView_Previews: PreviewProvider { + static var previews: some View { + TransactionSendingView(viewStore: ViewStore(SendFlowStore.placeholder)) + } +} diff --git a/secant/Resources/Colors.xcassets/ScreenBackground/amberGradientEnd.colorset/Contents.json b/secant/Resources/Colors.xcassets/ScreenBackground/amberGradientEnd.colorset/Contents.json new file mode 100644 index 0000000..5e9de05 --- /dev/null +++ b/secant/Resources/Colors.xcassets/ScreenBackground/amberGradientEnd.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x00", + "green" : "0x93", + "red" : "0xFF" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x00", + "green" : "0x93", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/secant/Resources/Colors.xcassets/ScreenBackground/amberGradientMiddle.colorset/Contents.json b/secant/Resources/Colors.xcassets/ScreenBackground/amberGradientMiddle.colorset/Contents.json new file mode 100644 index 0000000..4f89c29 --- /dev/null +++ b/secant/Resources/Colors.xcassets/ScreenBackground/amberGradientMiddle.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x00", + "green" : "0xB3", + "red" : "0xFF" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x00", + "green" : "0xB3", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/secant/Resources/Colors.xcassets/ScreenBackground/amberGradientStart.colorset/Contents.json b/secant/Resources/Colors.xcassets/ScreenBackground/amberGradientStart.colorset/Contents.json new file mode 100644 index 0000000..298575c --- /dev/null +++ b/secant/Resources/Colors.xcassets/ScreenBackground/amberGradientStart.colorset/Contents.json @@ -0,0 +1,38 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x00", + "green" : "0xD0", + "red" : "0xFF" + } + }, + "idiom" : "universal" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x00", + "green" : "0xD0", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/secant/Resources/Generated/XCAssets+Generated.swift b/secant/Resources/Generated/XCAssets+Generated.swift index cf1bab3..f02e12f 100644 --- a/secant/Resources/Generated/XCAssets+Generated.swift +++ b/secant/Resources/Generated/XCAssets+Generated.swift @@ -97,6 +97,9 @@ internal enum Asset { internal static let frame = ColorAsset(name: "frame") } internal enum ScreenBackground { + internal static let amberGradientEnd = ColorAsset(name: "amberGradientEnd") + internal static let amberGradientMiddle = ColorAsset(name: "amberGradientMiddle") + internal static let amberGradientStart = ColorAsset(name: "amberGradientStart") internal static let gradientDarkEnd = ColorAsset(name: "gradientDarkEnd") internal static let gradientDarkStart = ColorAsset(name: "gradientDarkStart") internal static let gradientEnd = ColorAsset(name: "gradientEnd") diff --git a/secant/Resources/Lotties/sendingTransaction.json b/secant/Resources/Lotties/sendingTransaction.json new file mode 100644 index 0000000..e1dc21b --- /dev/null +++ b/secant/Resources/Lotties/sendingTransaction.json @@ -0,0 +1 @@ +{"v":"5.5.8","fr":60,"ip":0,"op":90,"w":170,"h":130,"nm":"loader3","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":20,"s":[0]},{"t":89,"s":[180]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.145,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[34,65,0],"to":[0,-2.917,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.588},"o":{"x":0.732,"y":0},"t":20,"s":[34,47.5,0],"to":[0,0,0],"ti":[-55.765,0.067,0]},{"i":{"x":0.096,"y":1},"o":{"x":0.167,"y":0.414},"t":45,"s":[90.504,121.958,0],"to":[42.185,-0.051,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.984,"y":0},"t":70,"s":[139,40,0],"to":[0,0,0],"ti":[0,-0.833,0]},{"t":90,"s":[139,65,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":1,"k":[{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":20,"s":[20,20]},{"i":{"x":[0.667,0.667],"y":[1,1]},"o":{"x":[0.333,0.333],"y":[0,0]},"t":45,"s":[15,15]},{"t":70,"s":[20,20]}],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":3,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.125490196078,0.133333333333,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('CHANGE COLORS').layer('CHANGE COLOR').content('CHANGE COLOR HERE').color;"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":90,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 4","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.408,"y":1},"o":{"x":0.518,"y":0},"t":35,"s":[139,65,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.396,"y":1},"o":{"x":0.461,"y":0},"t":59,"s":[94,65,0],"to":[0,0,0],"ti":[0,0,0]},{"t":83,"s":[104,65,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[20,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":3,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.125490196078,0.133333333333,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('CHANGE COLORS').layer('CHANGE COLOR').content('CHANGE COLOR HERE').color;"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":90,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Shape Layer 3","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.408,"y":1},"o":{"x":0.518,"y":0},"t":32,"s":[104,65,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.396,"y":1},"o":{"x":0.461,"y":0},"t":56,"s":[59,65,0],"to":[0,0,0],"ti":[0,0,0]},{"t":80,"s":[69,65,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[20,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":3,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.125490196078,0.133333333333,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('CHANGE COLORS').layer('CHANGE COLOR').content('CHANGE COLOR HERE').color;"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":90,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[0]},{"t":54,"s":[-90]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.408,"y":1},"o":{"x":0.518,"y":0},"t":30,"s":[69,65,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.396,"y":1},"o":{"x":0.461,"y":0},"t":54,"s":[24,65,0],"to":[0,0,0],"ti":[0,0,0]},{"t":78,"s":[34,65,0]}],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"rc","d":1,"s":{"a":0,"k":[20,20],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"r":{"a":0,"k":3,"ix":4},"nm":"Rectangle Path 1","mn":"ADBE Vector Shape - Rect","hd":false},{"ty":"fl","c":{"a":0,"k":[0.125490196078,0.125490196078,0.133333333333,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('CHANGE COLORS').layer('CHANGE COLOR').content('CHANGE COLOR HERE').color;"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false}],"ip":0,"op":90,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/secant/UI Components/Backgrounds/ScreenBackground.swift b/secant/UI Components/Backgrounds/ScreenBackground.swift index b3c7445..bae7e3b 100644 --- a/secant/UI Components/Backgrounds/ScreenBackground.swift +++ b/secant/UI Components/Backgrounds/ScreenBackground.swift @@ -109,6 +109,19 @@ extension View { ) ) } + + func applyAmberScreenBackground() -> some View { + self.modifier( + ScreenBackgroundModifier( + colors: [ + Asset.Colors.ScreenBackground.amberGradientStart.color, + Asset.Colors.ScreenBackground.amberGradientMiddle.color, + Asset.Colors.ScreenBackground.amberGradientEnd.color + ] + ) + ) + + } } struct ScreenBackground_Previews: PreviewProvider { diff --git a/secantTests/SendTests/SendTests.swift b/secantTests/SendTests/SendTests.swift index 318cbff..32a12e6 100644 --- a/secantTests/SendTests/SendTests.swift +++ b/secantTests/SendTests/SendTests.swift @@ -72,6 +72,11 @@ class SendTests: XCTestCase { zecAmount: Zatoshi(10) ) + // first it's expected that progress screen is showed + store.receive(.updateRoute(.inProgress)) { state in + state.route = .inProgress + } + // check the success transaction to be received back store.receive(.sendTransactionResult(Result.success(transactionState))) { state in // from this moment on the sending next transaction is allowed again @@ -133,6 +138,11 @@ class SendTests: XCTestCase { zecAmount: Zatoshi(10) ) + // first it's expected that progress screen is showed + store.receive(.updateRoute(.inProgress)) { state in + state.route = .inProgress + } + // check the success transaction to be received back store.receive(.sendTransactionResult(Result.success(transactionState))) { state in // from this moment on the sending next transaction is allowed again @@ -178,6 +188,11 @@ class SendTests: XCTestCase { testScheduler.advance(by: 0.01) + // first it's expected that progress screen is showed + store.receive(.updateRoute(.inProgress)) { state in + state.route = .inProgress + } + // check the failure transaction to be received back store.receive(.sendTransactionResult(Result.failure(SynchronizerError.criticalError as NSError))) { state in // from this moment on the sending next transaction is allowed again diff --git a/secantTests/SnapshotTests/SendSnapshotTests/TransactionSendingTests.swift b/secantTests/SnapshotTests/SendSnapshotTests/TransactionSendingTests.swift new file mode 100644 index 0000000..3d4328f --- /dev/null +++ b/secantTests/SnapshotTests/SendSnapshotTests/TransactionSendingTests.swift @@ -0,0 +1,51 @@ +// +// TransactionSendingTests.swift +// secantTests +// +// Created by Michal Fousek on 30.09.2022. +// + +import XCTest +@testable import secant_testnet +import ComposableArchitecture +import SwiftUI +import ZcashLightClientKit + +class TransactionSendingTests: XCTestCase { + func testTransactionSendingSnapshot() throws { + let testEnvironment = SendFlowEnvironment( + derivationTool: .live(derivationTool: DerivationTool(networkType: .testnet)), + mnemonic: .mock, + numberFormatter: .live(), + SDKSynchronizer: MockWrappedSDKSynchronizer(), + scheduler: DispatchQueue.main.eraseToAnyScheduler(), + walletStorage: .live(), + zcashSDKEnvironment: .testnet + ) + + var state = SendFlowState.placeholder + state.addMemoState = true + state.transactionAddressInputState = TransactionAddressTextFieldState( + textFieldState: TCATextFieldState( + validationType: nil, + text: "ztestmockeddestinationaddress" + ) + ) + state.transactionAmountInputState = TransactionAmountTextFieldState( + currencySelectionState: CurrencySelectionState(), + textFieldState: TCATextFieldState( + validationType: nil, + text: "2.91" + ) + ) + + let store = Store( + initialState: state, + reducer: SendFlowReducer.default, + environment: testEnvironment + ) + + ViewStore(store).send(.onAppear) + addAttachments(TransactionSendingView(viewStore: ViewStore(store))) + } +}