[#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.
This commit is contained in:
Michal Fousek 2022-10-03 15:39:40 +02:00 committed by GitHub
parent ad575b8173
commit 91af5782c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 293 additions and 13 deletions

View File

@ -71,9 +71,12 @@
3448CB3228E47666006ADEDB /* NotEnoughFreeSpaceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3128E47666006ADEDB /* NotEnoughFreeSpaceView.swift */; }; 3448CB3228E47666006ADEDB /* NotEnoughFreeSpaceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3128E47666006ADEDB /* NotEnoughFreeSpaceView.swift */; };
3448CB3428E47787006ADEDB /* WrappedDiskSpaceChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3328E47787006ADEDB /* WrappedDiskSpaceChecker.swift */; }; 3448CB3428E47787006ADEDB /* WrappedDiskSpaceChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3328E47787006ADEDB /* WrappedDiskSpaceChecker.swift */; };
3448CB3728E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3448CB3628E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.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 */; }; 346715A528E2027D0035F7C4 /* CheckCircleStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346715A428E2027D0035F7C4 /* CheckCircleStore.swift */; };
346715A828E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */; }; 346715A828E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */; };
346D41E428DF0B8600963F36 /* CheckCircle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 346D41E328DF0B8600963F36 /* CheckCircle.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 */; }; 34E0AF0F28DEE4C70034CF37 /* HoldToSendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */; };
34E0AF1128DEE5220034CF37 /* Wedge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0AF1028DEE5220034CF37 /* Wedge.swift */; }; 34E0AF1128DEE5220034CF37 /* Wedge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0AF1028DEE5220034CF37 /* Wedge.swift */; };
34E5F2F328E46DB700C17E5F /* DiskSpaceChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E5F2F228E46DB700C17E5F /* DiskSpaceChecker.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 = "<group>"; }; 3448CB3128E47666006ADEDB /* NotEnoughFreeSpaceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotEnoughFreeSpaceView.swift; sourceTree = "<group>"; };
3448CB3328E47787006ADEDB /* WrappedDiskSpaceChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedDiskSpaceChecker.swift; sourceTree = "<group>"; }; 3448CB3328E47787006ADEDB /* WrappedDiskSpaceChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WrappedDiskSpaceChecker.swift; sourceTree = "<group>"; };
3448CB3628E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotEnoughFeeSpaceSnapshots.swift; sourceTree = "<group>"; }; 3448CB3628E485CB006ADEDB /* NotEnoughFeeSpaceSnapshots.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotEnoughFeeSpaceSnapshots.swift; sourceTree = "<group>"; };
34429C6D28E703CD00F2B929 /* TransactionSendingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionSendingTests.swift; sourceTree = "<group>"; };
346715A428E2027D0035F7C4 /* CheckCircleStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckCircleStore.swift; sourceTree = "<group>"; }; 346715A428E2027D0035F7C4 /* CheckCircleStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckCircleStore.swift; sourceTree = "<group>"; };
346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionConfirmationSnapshotTests.swift; sourceTree = "<group>"; }; 346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionConfirmationSnapshotTests.swift; sourceTree = "<group>"; };
346D41E328DF0B8600963F36 /* CheckCircle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckCircle.swift; sourceTree = "<group>"; }; 346D41E328DF0B8600963F36 /* CheckCircle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckCircle.swift; sourceTree = "<group>"; };
34DA414628E4385800F8CC61 /* TransactionSendingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionSendingView.swift; sourceTree = "<group>"; };
34DA414828E439CD00F8CC61 /* sendingTransaction.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = sendingTransaction.json; sourceTree = "<group>"; };
34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoldToSendButton.swift; sourceTree = "<group>"; }; 34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HoldToSendButton.swift; sourceTree = "<group>"; };
34E0AF1028DEE5220034CF37 /* Wedge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wedge.swift; sourceTree = "<group>"; }; 34E0AF1028DEE5220034CF37 /* Wedge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wedge.swift; sourceTree = "<group>"; };
34E5F2F228E46DB700C17E5F /* DiskSpaceChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskSpaceChecker.swift; sourceTree = "<group>"; }; 34E5F2F228E46DB700C17E5F /* DiskSpaceChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DiskSpaceChecker.swift; sourceTree = "<group>"; };
@ -738,6 +744,7 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */, 346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */,
34429C6D28E703CD00F2B929 /* TransactionSendingTests.swift */,
); );
path = SendSnapshotTests; path = SendSnapshotTests;
sourceTree = "<group>"; sourceTree = "<group>";
@ -968,6 +975,7 @@
9E6612342878341F00C75B70 /* Lotties */ = { 9E6612342878341F00C75B70 /* Lotties */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
34DA414828E439CD00F8CC61 /* sendingTransaction.json */,
9E6612352878345000C75B70 /* endlessCircleProgress.json */, 9E6612352878345000C75B70 /* endlessCircleProgress.json */,
); );
path = Lotties; path = Lotties;
@ -1404,10 +1412,11 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F9C165BB2740403600592F76 /* CreateTransactionView.swift */, F9C165BB2740403600592F76 /* CreateTransactionView.swift */,
34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */,
F9C165B92740403600592F76 /* TransactionConfirmationView.swift */, F9C165B92740403600592F76 /* TransactionConfirmationView.swift */,
9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */, 9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */,
34DA414628E4385800F8CC61 /* TransactionSendingView.swift */,
F9C165BD2740403600592F76 /* TransactionSentView.swift */, F9C165BD2740403600592F76 /* TransactionSentView.swift */,
34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */,
); );
path = Views; path = Views;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1537,6 +1546,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
0DACFA9327209FA70039EEA5 /* Roboto-Medium.ttf in Resources */, 0DACFA9327209FA70039EEA5 /* Roboto-Medium.ttf in Resources */,
34DA414928E439CD00F8CC61 /* sendingTransaction.json in Resources */,
0DACFA9827209FA70039EEA5 /* Roboto-MediumItalic.ttf in Resources */, 0DACFA9827209FA70039EEA5 /* Roboto-MediumItalic.ttf in Resources */,
0DACFA9427209FA70039EEA5 /* Roboto-BoldItalic.ttf in Resources */, 0DACFA9427209FA70039EEA5 /* Roboto-BoldItalic.ttf in Resources */,
9E6612362878345000C75B70 /* endlessCircleProgress.json in Resources */, 9E6612362878345000C75B70 /* endlessCircleProgress.json in Resources */,
@ -1631,6 +1641,7 @@
9EAFEB902808183D00199FC9 /* SandboxStore.swift in Sources */, 9EAFEB902808183D00199FC9 /* SandboxStore.swift in Sources */,
0D35CC46277A36E00074316A /* ScrollableWhenScaled.swift in Sources */, 0D35CC46277A36E00074316A /* ScrollableWhenScaled.swift in Sources */,
9E39114A2848EEB90073DD9A /* UserPreferencesStorage.swift in Sources */, 9E39114A2848EEB90073DD9A /* UserPreferencesStorage.swift in Sources */,
34DA414728E4385800F8CC61 /* TransactionSendingView.swift in Sources */,
9EAB466A2859F42E002904A0 /* WrappedDeeplinkHandler.swift in Sources */, 9EAB466A2859F42E002904A0 /* WrappedDeeplinkHandler.swift in Sources */,
F96B41E9273B501F0021B49A /* WalletEventsFlowView.swift in Sources */, F96B41E9273B501F0021B49A /* WalletEventsFlowView.swift in Sources */,
9E01F8202833861A000EFC57 /* WrappedCaptureDevice.swift in Sources */, 9E01F8202833861A000EFC57 /* WrappedCaptureDevice.swift in Sources */,
@ -1789,6 +1800,7 @@
9EDDEAA42829610D00B4100C /* TransactionAddressInputTests.swift in Sources */, 9EDDEAA42829610D00B4100C /* TransactionAddressInputTests.swift in Sources */,
9E7CB6272874269F00A02233 /* ProfileSnapshotTests.swift in Sources */, 9E7CB6272874269F00A02233 /* ProfileSnapshotTests.swift in Sources */,
9E92AF0828530EBF007367AD /* View+UIImage.swift in Sources */, 9E92AF0828530EBF007367AD /* View+UIImage.swift in Sources */,
34429C6E28E703CD00F2B929 /* TransactionSendingTests.swift in Sources */,
6654C7442715A4AC00901167 /* OnboardingStoreTests.swift in Sources */, 6654C7442715A4AC00901167 /* OnboardingStoreTests.swift in Sources */,
9E94C62328AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift in Sources */, 9E94C62328AA7EE0008256E9 /* BalanceBreakdownSnapshotTests.swift in Sources */,
9E39112E283F91600073DD9A /* ZatoshiTests.swift in Sources */, 9E39112E283F91600073DD9A /* ZatoshiTests.swift in Sources */,

View File

@ -18,6 +18,7 @@ typealias SendFlowViewStore = ViewStore<SendFlowState, SendFlowAction>
struct SendFlowState: Equatable { struct SendFlowState: Equatable {
enum Route: Equatable { enum Route: Equatable {
case confirmation case confirmation
case inProgress
case success case success
case failure case failure
case done case done
@ -148,7 +149,7 @@ extension SendFlowReducer {
state.isSendingTransaction = true state.isSendingTransaction = true
return environment.SDKSynchronizer.sendTransaction( let sendTransActionEffect = environment.SDKSynchronizer.sendTransaction(
with: spendingKey, with: spendingKey,
zatoshi: state.amount, zatoshi: state.amount,
to: state.address, to: state.address,
@ -158,6 +159,8 @@ extension SendFlowReducer {
.receive(on: environment.scheduler) .receive(on: environment.scheduler)
.map(SendFlowAction.sendTransactionResult) .map(SendFlowAction.sendTransactionResult)
.eraseToEffect() .eraseToEffect()
return .concatenate(Effect(value: .updateRoute(.inProgress)), sendTransActionEffect)
} catch { } catch {
return Effect(value: .updateRoute(.failure)) return Effect(value: .updateRoute(.failure))
} }
@ -276,22 +279,38 @@ extension SendFlowViewStore {
var bindingForConfirmation: Binding<Bool> { var bindingForConfirmation: Binding<Bool> {
self.routeBinding.map( 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 } embed: { $0 ? SendFlowState.Route.confirmation : nil }
) )
} }
var bindingForInProgress: Binding<Bool> {
self.routeBinding.map(
extract: {
$0 == .inProgress ||
self.bindingForSuccess.wrappedValue ||
self.bindingForFailure.wrappedValue
},
embed: { $0 ? SendFlowState.Route.inProgress : SendFlowState.Route.confirmation }
)
}
var bindingForSuccess: Binding<Bool> { var bindingForSuccess: Binding<Bool> {
self.routeBinding.map( self.routeBinding.map(
extract: { $0 == .success || self.bindingForDone.wrappedValue }, 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<Bool> { var bindingForFailure: Binding<Bool> {
self.routeBinding.map( self.routeBinding.map(
extract: { $0 == .failure || self.bindingForDone.wrappedValue }, extract: { $0 == .failure || self.bindingForDone.wrappedValue },
embed: { $0 ? SendFlowState.Route.failure : SendFlowState.Route.confirmation } embed: { $0 ? SendFlowState.Route.failure : SendFlowState.Route.inProgress }
) )
} }

View File

@ -33,12 +33,8 @@ struct TransactionConfirmation: View {
} }
.applyDarkScreenBackground() .applyDarkScreenBackground()
.navigationLinkEmpty( .navigationLinkEmpty(
isActive: viewStore.bindingForSuccess, isActive: viewStore.bindingForInProgress,
destination: { TransactionSent(viewStore: viewStore) } destination: { TransactionSendingView(viewStore: viewStore) }
)
.navigationLinkEmpty(
isActive: viewStore.bindingForFailure,
destination: { TransactionFailed(viewStore: viewStore) }
) )
} }
} }

View File

@ -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))
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -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
}
}

View File

@ -97,6 +97,9 @@ internal enum Asset {
internal static let frame = ColorAsset(name: "frame") internal static let frame = ColorAsset(name: "frame")
} }
internal enum ScreenBackground { 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 gradientDarkEnd = ColorAsset(name: "gradientDarkEnd")
internal static let gradientDarkStart = ColorAsset(name: "gradientDarkStart") internal static let gradientDarkStart = ColorAsset(name: "gradientDarkStart")
internal static let gradientEnd = ColorAsset(name: "gradientEnd") internal static let gradientEnd = ColorAsset(name: "gradientEnd")

View File

@ -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":[]}

View File

@ -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 { struct ScreenBackground_Previews: PreviewProvider {

View File

@ -72,6 +72,11 @@ class SendTests: XCTestCase {
zecAmount: Zatoshi(10) 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 // check the success transaction to be received back
store.receive(.sendTransactionResult(Result.success(transactionState))) { state in store.receive(.sendTransactionResult(Result.success(transactionState))) { state in
// from this moment on the sending next transaction is allowed again // from this moment on the sending next transaction is allowed again
@ -133,6 +138,11 @@ class SendTests: XCTestCase {
zecAmount: Zatoshi(10) 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 // check the success transaction to be received back
store.receive(.sendTransactionResult(Result.success(transactionState))) { state in store.receive(.sendTransactionResult(Result.success(transactionState))) { state in
// from this moment on the sending next transaction is allowed again // from this moment on the sending next transaction is allowed again
@ -178,6 +188,11 @@ class SendTests: XCTestCase {
testScheduler.advance(by: 0.01) 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 // check the failure transaction to be received back
store.receive(.sendTransactionResult(Result.failure(SynchronizerError.criticalError as NSError))) { state in store.receive(.sendTransactionResult(Result.failure(SynchronizerError.criticalError as NSError))) { state in
// from this moment on the sending next transaction is allowed again // from this moment on the sending next transaction is allowed again

View File

@ -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)))
}
}