Closes #81 - Ported ZcashHoldToSendButton from ECC referecne wallet and make it work with TCA. And then use it on Send Confirmation screen. - Added colors that are used by HoldToSendButton to asset catalogue. - Update Send confirmation screen look according to designs. - Ported ZcashCheckCircle from ECC reference wallet and use it on Send confirmation screen. - Added colors used by CheckCircle to assets catalogue. - Add test for the case when not including memo in transaction. - Updated ZcashLightClientKit to 0.16.10-beta to fix transaction failure when memo is nil.
This commit is contained in:
parent
92289bb036
commit
d807f86d49
|
@ -68,6 +68,11 @@
|
|||
2EDA07A027EDE18C00D6F09B /* TCATextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA079F27EDE18C00D6F09B /* TCATextField.swift */; };
|
||||
2EDA07A227EDE1AE00D6F09B /* TextFieldFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA07A127EDE1AE00D6F09B /* TextFieldFooter.swift */; };
|
||||
2EDA07A427EDE2A900D6F09B /* DebugFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA07A327EDE2A900D6F09B /* DebugFrame.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 */; };
|
||||
34E0AF0F28DEE4C70034CF37 /* HoldToSendButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */; };
|
||||
34E0AF1128DEE5220034CF37 /* Wedge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E0AF1028DEE5220034CF37 /* Wedge.swift */; };
|
||||
660558E9270C7A54009D6954 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 660558E8270C7A54009D6954 /* Colors.xcassets */; };
|
||||
660558F7270C862F009D6954 /* Fonts+Generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660558F5270C862F009D6954 /* Fonts+Generated.swift */; };
|
||||
660558F8270C862F009D6954 /* XCAssets+Generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660558F6270C862F009D6954 /* XCAssets+Generated.swift */; };
|
||||
|
@ -302,6 +307,11 @@
|
|||
2EDA079F27EDE18C00D6F09B /* TCATextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TCATextField.swift; sourceTree = "<group>"; };
|
||||
2EDA07A127EDE1AE00D6F09B /* TextFieldFooter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextFieldFooter.swift; sourceTree = "<group>"; };
|
||||
2EDA07A327EDE2A900D6F09B /* DebugFrame.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugFrame.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>"; };
|
||||
346D41E328DF0B8600963F36 /* CheckCircle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckCircle.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>"; };
|
||||
660558E8270C7A54009D6954 /* Colors.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Colors.xcassets; sourceTree = "<group>"; };
|
||||
660558F5270C862F009D6954 /* Fonts+Generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Fonts+Generated.swift"; sourceTree = "<group>"; };
|
||||
660558F6270C862F009D6954 /* XCAssets+Generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCAssets+Generated.swift"; sourceTree = "<group>"; };
|
||||
|
@ -488,6 +498,7 @@
|
|||
0D0781C5278776B90083ACD7 /* Shapes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34E0AF1028DEE5220034CF37 /* Wedge.swift */,
|
||||
0D0781C7278776D20083ACD7 /* ZcashSymbol.swift */,
|
||||
);
|
||||
path = Shapes;
|
||||
|
@ -707,6 +718,23 @@
|
|||
path = Components;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
346715A628E20FB30035F7C4 /* SendSnapshotTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
346715A728E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift */,
|
||||
);
|
||||
path = SendSnapshotTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
346D41E228DF0B0900963F36 /* CheckCircle */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
346D41E328DF0B8600963F36 /* CheckCircle.swift */,
|
||||
346715A428E2027D0035F7C4 /* CheckCircleStore.swift */,
|
||||
);
|
||||
path = CheckCircle;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
663FAB9A271D873300E495F8 /* Buttons */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -866,17 +894,18 @@
|
|||
9E391162284E3ECF0073DD9A /* SnapshotTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9E92AF0728530EBF007367AD /* View+UIImage.swift */,
|
||||
9E94C62128AA7ECD008256E9 /* BalanceBreakdownSnapshotTests */,
|
||||
9E7225EF2889537E00DF7F17 /* SettingsSnapshotTests */,
|
||||
9E7CB6252874267B00A02233 /* ProfileSnapshotTests */,
|
||||
9E7CB6102869881300A02233 /* WalletEventsSnapshotTests */,
|
||||
9E9ECC8B28589E150099D5A2 /* HomeSnapshotTests */,
|
||||
9E9ECC9328589E150099D5A2 /* ImportWalletSnapshotTests */,
|
||||
9E9ECC9528589E150099D5A2 /* OnboardingSnapshotTests */,
|
||||
9E7CB6252874267B00A02233 /* ProfileSnapshotTests */,
|
||||
9E9ECC8F28589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests */,
|
||||
9E9ECC9128589E150099D5A2 /* RecoveryPhraseValidationFlowSnapshotTests */,
|
||||
346715A628E20FB30035F7C4 /* SendSnapshotTests */,
|
||||
9E7225EF2889537E00DF7F17 /* SettingsSnapshotTests */,
|
||||
9E7CB6102869881300A02233 /* WalletEventsSnapshotTests */,
|
||||
9E9ECC8D28589E150099D5A2 /* WelcomeSnapshotTests */,
|
||||
9E92AF0728530EBF007367AD /* View+UIImage.swift */,
|
||||
);
|
||||
path = SnapshotTests;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1073,6 +1102,7 @@
|
|||
9E7FE0BE282D1DFE00C374E8 /* UI Components */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
346D41E228DF0B0900963F36 /* CheckCircle */,
|
||||
9E7CB6132869E8A700A02233 /* CircularProgress */,
|
||||
0DF2DC5227235E1F00FA31E2 /* Extensions */,
|
||||
0DB8AA80271DC7520035BC9D /* DesignGuide.swift */,
|
||||
|
@ -1355,8 +1385,9 @@
|
|||
children = (
|
||||
F9C165BB2740403600592F76 /* CreateTransactionView.swift */,
|
||||
F9C165B92740403600592F76 /* TransactionConfirmationView.swift */,
|
||||
F9C165BD2740403600592F76 /* TransactionSentView.swift */,
|
||||
9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */,
|
||||
F9C165BD2740403600592F76 /* TransactionSentView.swift */,
|
||||
34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1588,6 +1619,7 @@
|
|||
2EB7758727FC67FD00269373 /* TransactionAmountTextFieldStore.swift in Sources */,
|
||||
669FDAE9272C23B3007B9422 /* CircularFrame.swift in Sources */,
|
||||
9EF8136027F043CC0075AF48 /* AppDelegate.swift in Sources */,
|
||||
34E0AF1128DEE5220034CF37 /* Wedge.swift in Sources */,
|
||||
F96B41E8273B501F0021B49A /* TransactionDetailView.swift in Sources */,
|
||||
9E02B56A27FED43E005B809B /* WrappedFileManager.swift in Sources */,
|
||||
663FABA2271D876C00E495F8 /* SecondaryButton.swift in Sources */,
|
||||
|
@ -1617,6 +1649,7 @@
|
|||
9E2DF99D27CF704D00649636 /* ImportSeedEditor.swift in Sources */,
|
||||
F9971A5327680DD000A2DB75 /* ProfileStore.swift in Sources */,
|
||||
9E39114D2848EEB90073DD9A /* WalletStorage.swift in Sources */,
|
||||
346D41E428DF0B8600963F36 /* CheckCircle.swift in Sources */,
|
||||
669FDAEB272C23C2007B9422 /* CircularFrameBadge.swift in Sources */,
|
||||
9E39113B2848D5180073DD9A /* WrappedNumberFormatter.swift in Sources */,
|
||||
2E8719CD27FB0D3B0082C926 /* CurrencySelectionView.swift in Sources */,
|
||||
|
@ -1671,6 +1704,7 @@
|
|||
663FAB9C271D874D00E495F8 /* ActiveButton.swift in Sources */,
|
||||
9E2F1C842809B606004E65FE /* DebugMenu.swift in Sources */,
|
||||
9E02B5C3280458D2005B809B /* WrappedDerivationTool.swift in Sources */,
|
||||
34E0AF0F28DEE4C70034CF37 /* HoldToSendButton.swift in Sources */,
|
||||
F9C165C02740403600592F76 /* TransactionConfirmationView.swift in Sources */,
|
||||
0DF2DC5427235E3E00FA31E2 /* View+InnerShadow.swift in Sources */,
|
||||
9E39113F2848EC360073DD9A /* WrappedRecoveryPhraseRandomizer.swift in Sources */,
|
||||
|
@ -1689,6 +1723,7 @@
|
|||
66A0807B271993C500118B79 /* OnboardingProgressIndicator.swift in Sources */,
|
||||
0D7DF08C271DCC0E00530046 /* ScreenBackground.swift in Sources */,
|
||||
9E01F8242833C0D8000EFC57 /* WrappedURIParser.swift in Sources */,
|
||||
346715A528E2027D0035F7C4 /* CheckCircleStore.swift in Sources */,
|
||||
F9C165C22740403600592F76 /* CreateTransactionView.swift in Sources */,
|
||||
F9C165B4274031F600592F76 /* Bindings.swift in Sources */,
|
||||
2E35F99A27B3E99C00EB79CD /* TextFieldTitleAccessoryButtonStyle.swift in Sources */,
|
||||
|
@ -1747,6 +1782,7 @@
|
|||
9E391132284644580073DD9A /* AppInitializationTests.swift in Sources */,
|
||||
9E9ECC9928589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift in Sources */,
|
||||
9E391124283E4CAC0073DD9A /* ImportWalletTests.swift in Sources */,
|
||||
346715A828E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift in Sources */,
|
||||
9E5BF63F2819542C00BA3F17 /* WalletEventsTests.swift in Sources */,
|
||||
0D4E7A1B26B364180058B01E /* secantTests.swift in Sources */,
|
||||
0DFE93E6272CB6F7000FCCA5 /* RecoveryPhraseValidationTests.swift in Sources */,
|
||||
|
@ -2082,7 +2118,7 @@
|
|||
repositoryURL = "https://github.com/zcash/ZcashLightClientKit/";
|
||||
requirement = {
|
||||
kind = exactVersion;
|
||||
version = "0.16.6-beta";
|
||||
version = "0.16.10-beta";
|
||||
};
|
||||
};
|
||||
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
|
||||
|
|
|
@ -203,8 +203,8 @@
|
|||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/zcash/ZcashLightClientKit",
|
||||
"state" : {
|
||||
"revision" : "a37c140441d78fa6ad9c89e2fbb539f1ddb7e5a1",
|
||||
"version" : "0.16.6-beta"
|
||||
"revision" : "9e41fb43757fd7b0eb8e817320537230774258cf",
|
||||
"version" : "0.16.10-beta"
|
||||
}
|
||||
}
|
||||
],
|
||||
|
|
|
@ -23,6 +23,7 @@ struct SendFlowState: Equatable {
|
|||
case done
|
||||
}
|
||||
|
||||
var addMemoState: Bool
|
||||
var isSendingTransaction = false
|
||||
var memoState: MultiLineTextFieldState
|
||||
var route: Route?
|
||||
|
@ -74,6 +75,7 @@ struct SendFlowState: Equatable {
|
|||
// MARK: - Action
|
||||
|
||||
enum SendFlowAction: Equatable {
|
||||
case addMemo(CheckCircleAction)
|
||||
case memo(MultiLineTextFieldAction)
|
||||
case onAppear
|
||||
case onDisappear
|
||||
|
@ -107,12 +109,16 @@ extension SendFlowReducer {
|
|||
sendReducer,
|
||||
transactionAddressInputReducer,
|
||||
transactionAmountInputReducer,
|
||||
memoReducer
|
||||
memoReducer,
|
||||
addMemoReducer
|
||||
]
|
||||
)
|
||||
|
||||
private static let sendReducer = SendFlowReducer { state, action, environment in
|
||||
switch action {
|
||||
case .addMemo:
|
||||
return .none
|
||||
|
||||
case .updateRoute(.failure):
|
||||
state.route = .failure
|
||||
state.isSendingTransaction = false
|
||||
|
@ -146,7 +152,7 @@ extension SendFlowReducer {
|
|||
with: spendingKey,
|
||||
zatoshi: state.amount,
|
||||
to: state.address,
|
||||
memo: state.memoState.text,
|
||||
memo: state.addMemoState ? state.memoState.text : nil,
|
||||
from: 0
|
||||
)
|
||||
.receive(on: environment.scheduler)
|
||||
|
@ -196,6 +202,12 @@ extension SendFlowReducer {
|
|||
}
|
||||
}
|
||||
|
||||
private static let addMemoReducer: SendFlowReducer = CheckCircleReducer.default.pullback(
|
||||
state: \SendFlowState.addMemoState,
|
||||
action: /SendFlowAction.addMemo,
|
||||
environment: { _ in Void() }
|
||||
)
|
||||
|
||||
private static let transactionAddressInputReducer: SendFlowReducer = TransactionAddressTextFieldReducer.default.pullback(
|
||||
state: \SendFlowState.transactionAddressInputState,
|
||||
action: /SendFlowAction.transactionAddressInput,
|
||||
|
@ -237,6 +249,13 @@ extension SendFlowReducer {
|
|||
// MARK: - Store
|
||||
|
||||
extension SendFlowStore {
|
||||
func addMemoStore() -> CheckCircleStore {
|
||||
self.scope(
|
||||
state: \.addMemoState,
|
||||
action: SendFlowAction.addMemo
|
||||
)
|
||||
}
|
||||
|
||||
func memoStore() -> MultiLineTextFieldStore {
|
||||
self.scope(
|
||||
state: \.memoState,
|
||||
|
@ -289,6 +308,7 @@ extension SendFlowViewStore {
|
|||
extension SendFlowState {
|
||||
static var placeholder: Self {
|
||||
.init(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
route: nil,
|
||||
transactionAddressInputState: .placeholder,
|
||||
|
@ -298,6 +318,7 @@ extension SendFlowState {
|
|||
|
||||
static var emptyPlaceholder: Self {
|
||||
.init(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
route: nil,
|
||||
transactionAddressInputState: .placeholder,
|
||||
|
@ -310,12 +331,7 @@ extension SendFlowState {
|
|||
extension SendFlowStore {
|
||||
static var placeholder: SendFlowStore {
|
||||
return SendFlowStore(
|
||||
initialState: .init(
|
||||
memoState: .placeholder,
|
||||
route: nil,
|
||||
transactionAddressInputState: .placeholder,
|
||||
transactionAmountInputState: .placeholder
|
||||
),
|
||||
initialState: .emptyPlaceholder,
|
||||
reducer: .default,
|
||||
environment: SendFlowEnvironment(
|
||||
derivationTool: .live(),
|
||||
|
|
|
@ -19,7 +19,7 @@ struct SendFlowView: View {
|
|||
.navigationLinkEmpty(
|
||||
isActive: viewStore.bindingForConfirmation,
|
||||
destination: {
|
||||
TransactionConfirmation(viewStore: viewStore)
|
||||
TransactionConfirmation(store: store)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ struct SendFLowView_Previews: PreviewProvider {
|
|||
SendFlowView(
|
||||
store: .init(
|
||||
initialState: .init(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
route: nil,
|
||||
transactionAddressInputState: .placeholder,
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
//
|
||||
// ZcashSendButton.swift
|
||||
// wallet
|
||||
//
|
||||
// Created by Francisco Gindre on 1/9/20.
|
||||
// Copyright © 2020 Francisco Gindre. All rights reserved.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import ComposableArchitecture
|
||||
|
||||
struct HoldToSendButton: View {
|
||||
var minimumDuration: TimeInterval = 5
|
||||
let innerCircleScale: CGFloat = 0.8
|
||||
var completionStrokeWidth: CGFloat = 16.0
|
||||
@State var isPressing = false
|
||||
@State var startAngle: CGFloat = -90
|
||||
@State var endAngle: CGFloat = -90
|
||||
|
||||
var longPressSucceded: () -> Void
|
||||
|
||||
var body: some View {
|
||||
ZStack(alignment: .center) {
|
||||
GeometryReader { geometry in
|
||||
Circle()
|
||||
.size(geometry.size)
|
||||
.fill(Color.black)
|
||||
.shadow(color: Asset.Colors.Shadow.holdToSendButtonShadow.color, radius: 2, x: 0, y: 2)
|
||||
|
||||
Circle()
|
||||
.size(geometry.size)
|
||||
.fill(Asset.Colors.Shadow.holdToSendButtonShadow.color)
|
||||
.scaleEffect(self.innerCircleScale)
|
||||
.opacity(0.35)
|
||||
|
||||
Wedge(
|
||||
startAngle: self.startAngle,
|
||||
endAngle: self.endAngle,
|
||||
clockwise: false
|
||||
)
|
||||
.stroke(Asset.Colors.ProgressIndicator.holdToSendButton.color, lineWidth: self.completionStrokeWidth)
|
||||
.frame(
|
||||
width: geometry.size.width - self.completionStrokeWidth,
|
||||
height: geometry.size.height - self.completionStrokeWidth
|
||||
)
|
||||
.offset(x: self.completionStrokeWidth / 2, y: self.completionStrokeWidth / 2)
|
||||
|
||||
Text("Press and hold\nto send ZEC")
|
||||
.foregroundColor(.white)
|
||||
.multilineTextAlignment(.center)
|
||||
.frame(
|
||||
minWidth: geometry.size.width,
|
||||
idealWidth: geometry.size.width,
|
||||
maxWidth: geometry.size.width,
|
||||
minHeight: geometry.size.height,
|
||||
idealHeight: geometry.size.height,
|
||||
maxHeight: geometry.size.height,
|
||||
alignment: .center
|
||||
)
|
||||
}
|
||||
}
|
||||
.frame(
|
||||
width: 167,
|
||||
height: 167,
|
||||
alignment: .center
|
||||
)
|
||||
.onLongPressGesture(
|
||||
minimumDuration: minimumDuration,
|
||||
maximumDistance: 167,
|
||||
pressing: { isPressing in
|
||||
if !self.isPressing && isPressing {
|
||||
self.isPressing = isPressing
|
||||
withAnimation(.linear(duration: self.minimumDuration)) {
|
||||
self.startAnimation()
|
||||
}
|
||||
} else if self.isPressing && !isPressing {
|
||||
self.isPressing = isPressing
|
||||
withAnimation(.easeOut(duration: 0.3)) {
|
||||
self.cancelAnimation()
|
||||
}
|
||||
}
|
||||
},
|
||||
perform: {
|
||||
self.endAnimation()
|
||||
self.isPressing = false
|
||||
longPressSucceded()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
func startAnimation() {
|
||||
self.startAngle = -90
|
||||
self.endAngle = 270
|
||||
}
|
||||
|
||||
func endAnimation() {
|
||||
self.startAngle = -90
|
||||
self.endAngle = 270
|
||||
}
|
||||
|
||||
func cancelAnimation() {
|
||||
self.startAngle = -90
|
||||
self.endAngle = -90
|
||||
}
|
||||
}
|
||||
|
||||
struct HoldToSendButton_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
ZStack {
|
||||
HoldToSendButton(longPressSucceded: { })
|
||||
.applyDarkScreenBackground()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,29 +2,36 @@ import SwiftUI
|
|||
import ComposableArchitecture
|
||||
|
||||
struct TransactionConfirmation: View {
|
||||
let viewStore: SendFlowViewStore
|
||||
let store: SendFlowStore
|
||||
|
||||
var body: some View {
|
||||
WithViewStore(store) { viewStore in
|
||||
VStack {
|
||||
Text("Send \(viewStore.amount.decimalString()) ZEC")
|
||||
Text("Send \(viewStore.amount.decimalString()) ZEC to")
|
||||
.padding()
|
||||
.foregroundColor(Asset.Colors.Text.forDarkBackground.color)
|
||||
|
||||
Text("To \(viewStore.address)")
|
||||
Text("\(viewStore.address)?")
|
||||
.truncationMode(.middle)
|
||||
.lineLimit(1)
|
||||
.padding()
|
||||
.foregroundColor(Asset.Colors.Text.forDarkBackground.color)
|
||||
|
||||
HStack {
|
||||
CheckCircle(viewStore: ViewStore(store.addMemoStore()))
|
||||
Text("Includes memo")
|
||||
.foregroundColor(Asset.Colors.Text.forDarkBackground.color)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
Button(
|
||||
action: { viewStore.send(.sendConfirmationPressed) },
|
||||
label: { Text("Confirm") }
|
||||
)
|
||||
.activeButtonStyle
|
||||
.frame(height: 50)
|
||||
.padding()
|
||||
HoldToSendButton {
|
||||
viewStore.send(.sendConfirmationPressed)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.applyScreenBackground()
|
||||
.applyDarkScreenBackground()
|
||||
.navigationLinkEmpty(
|
||||
isActive: viewStore.bindingForSuccess,
|
||||
destination: { TransactionSent(viewStore: viewStore) }
|
||||
|
@ -34,6 +41,7 @@ struct TransactionConfirmation: View {
|
|||
destination: { TransactionFailed(viewStore: viewStore) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
@ -44,11 +52,8 @@ struct Confirmation_Previews: PreviewProvider {
|
|||
StateContainer(
|
||||
initialState: (false)
|
||||
) { _ in
|
||||
TransactionConfirmation(
|
||||
viewStore: ViewStore(.placeholder)
|
||||
)
|
||||
TransactionConfirmation(store: .placeholder)
|
||||
}
|
||||
}
|
||||
.preferredColorScheme(.dark)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "checkmark.pdf",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x65",
|
||||
"green" : "0x65",
|
||||
"red" : "0x65"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x65",
|
||||
"green" : "0x65",
|
||||
"red" : "0x65"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0x94",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0x94",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0x94",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0x94",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x1E",
|
||||
"green" : "0x1B",
|
||||
"red" : "0x19"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x1E",
|
||||
"green" : "0x1B",
|
||||
"red" : "0x19"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x3D",
|
||||
"green" : "0x38",
|
||||
"red" : "0x33"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x3D",
|
||||
"green" : "0x38",
|
||||
"red" : "0x33"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -23,9 +23,9 @@
|
|||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x45",
|
||||
"green" : "0x1F",
|
||||
"red" : "0x13"
|
||||
"blue" : "69",
|
||||
"green" : "31",
|
||||
"red" : "19"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x00",
|
||||
"green" : "0x00",
|
||||
"red" : "0x00"
|
||||
"blue" : "0",
|
||||
"green" : "0",
|
||||
"red" : "0"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x97",
|
||||
"green" : "0x97",
|
||||
"red" : "0x97"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x97",
|
||||
"green" : "0x97",
|
||||
"red" : "0x97"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -5,9 +5,9 @@
|
|||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "0.200",
|
||||
"blue" : "0x36",
|
||||
"green" : "0x2C",
|
||||
"red" : "0x27"
|
||||
"blue" : "54",
|
||||
"green" : "44",
|
||||
"red" : "39"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
@ -23,9 +23,9 @@
|
|||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "0.250",
|
||||
"blue" : "0x00",
|
||||
"green" : "0x00",
|
||||
"red" : "0x00"
|
||||
"blue" : "0",
|
||||
"green" : "0",
|
||||
"red" : "0"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xFF",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0xFF",
|
||||
"green" : "0xFF",
|
||||
"red" : "0xFF"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -5,9 +5,9 @@
|
|||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "0.827",
|
||||
"blue" : "0.623",
|
||||
"green" : "0.589",
|
||||
"red" : "0.560"
|
||||
"blue" : "0x9E",
|
||||
"green" : "0x96",
|
||||
"red" : "0x8E"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
@ -23,9 +23,9 @@
|
|||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0.290",
|
||||
"green" : "0.275",
|
||||
"red" : "0.259"
|
||||
"blue" : "0x49",
|
||||
"green" : "0x46",
|
||||
"red" : "0x42"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
|
|
|
@ -35,6 +35,7 @@ internal enum Asset {
|
|||
}
|
||||
internal enum Icons {
|
||||
internal static let bank = ImageAsset(name: "bank")
|
||||
internal static let checkmark = ImageAsset(name: "checkmark")
|
||||
internal static let list = ImageAsset(name: "list")
|
||||
internal static let profile = ImageAsset(name: "profile")
|
||||
internal static let qrCode = ImageAsset(name: "qr-code")
|
||||
|
@ -67,6 +68,10 @@ internal enum Asset {
|
|||
internal static let secondaryButton = ColorAsset(name: "SecondaryButton")
|
||||
internal static let secondaryButtonPressed = ColorAsset(name: "SecondaryButtonPressed")
|
||||
}
|
||||
internal enum CheckCircle {
|
||||
internal static let externalRing = ColorAsset(name: "externalRing")
|
||||
internal static let internalRing = ColorAsset(name: "internalRing")
|
||||
}
|
||||
internal enum Cursor {
|
||||
internal static let bar = ColorAsset(name: "Bar")
|
||||
}
|
||||
|
@ -86,11 +91,14 @@ internal enum Asset {
|
|||
internal static let gradientLeft = ColorAsset(name: "GradientLeft")
|
||||
internal static let gradientRight = ColorAsset(name: "GradientRight")
|
||||
internal static let negativeSpace = ColorAsset(name: "NegativeSpace")
|
||||
internal static let holdToSendButton = ColorAsset(name: "holdToSendButton")
|
||||
}
|
||||
internal enum QRScan {
|
||||
internal static let frame = ColorAsset(name: "frame")
|
||||
}
|
||||
internal enum ScreenBackground {
|
||||
internal static let gradientDarkEnd = ColorAsset(name: "gradientDarkEnd")
|
||||
internal static let gradientDarkStart = ColorAsset(name: "gradientDarkStart")
|
||||
internal static let gradientEnd = ColorAsset(name: "gradientEnd")
|
||||
internal static let gradientStart = ColorAsset(name: "gradientStart")
|
||||
internal static let greenGradientEnd = ColorAsset(name: "greenGradientEnd")
|
||||
|
@ -104,6 +112,7 @@ internal enum Asset {
|
|||
internal enum Shadow {
|
||||
internal static let drawerShadow = ColorAsset(name: "drawerShadow")
|
||||
internal static let emptyChipInnerShadow = ColorAsset(name: "emptyChipInnerShadow")
|
||||
internal static let holdToSendButtonShadow = ColorAsset(name: "holdToSendButtonShadow")
|
||||
internal static let numberedTextShadow = ColorAsset(name: "numberedTextShadow")
|
||||
}
|
||||
internal enum Text {
|
||||
|
@ -124,6 +133,7 @@ internal enum Asset {
|
|||
internal static let balanceText = ColorAsset(name: "balanceText")
|
||||
internal static let captionText = ColorAsset(name: "captionText")
|
||||
internal static let captionTextShadow = ColorAsset(name: "captionTextShadow")
|
||||
internal static let forDarkBackground = ColorAsset(name: "forDarkBackground")
|
||||
internal static let highlightedSuperscriptText = ColorAsset(name: "highlightedSuperscriptText")
|
||||
internal static let moreInfoText = ColorAsset(name: "moreInfoText")
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ extension ScreenBackground {
|
|||
]
|
||||
)
|
||||
}
|
||||
|
||||
struct ScreenBackgroundModifier: ViewModifier {
|
||||
var colors: [Color]
|
||||
var darkGradientEndPointY = 1.0
|
||||
|
@ -97,6 +98,17 @@ extension View {
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
func applyDarkScreenBackground() -> some View {
|
||||
self.modifier(
|
||||
ScreenBackgroundModifier(
|
||||
colors: [
|
||||
Asset.Colors.ScreenBackground.gradientDarkStart.color,
|
||||
Asset.Colors.ScreenBackground.gradientDarkEnd.color
|
||||
]
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
struct ScreenBackground_Previews: PreviewProvider {
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
//
|
||||
// ZcashCheckCircle.swift
|
||||
// wallet
|
||||
//
|
||||
// Created by Francisco Gindre on 1/7/20.
|
||||
// Copyright © 2020 Francisco Gindre. All rights reserved.
|
||||
//
|
||||
|
||||
import ComposableArchitecture
|
||||
import SwiftUI
|
||||
|
||||
struct CheckCircle: View {
|
||||
let viewStore: CheckCircleViewStore
|
||||
|
||||
var externalRingColor: Color = Asset.Colors.CheckCircle.externalRing.color
|
||||
var internalRingColor: Color = Asset.Colors.CheckCircle.internalRing.color
|
||||
|
||||
var backgroundColor: Color = .clear
|
||||
|
||||
func backgroundShape(size: CGSize) -> some View {
|
||||
Path { path in
|
||||
path.addArc(
|
||||
center: CGPoint(
|
||||
x: size.width / 2,
|
||||
y: size.height / 2
|
||||
),
|
||||
radius: size.width / 2,
|
||||
startAngle: Angle(degrees: 0),
|
||||
endAngle: Angle(degrees: 360),
|
||||
clockwise: true
|
||||
)
|
||||
}
|
||||
.fill(self.backgroundColor)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
GeometryReader { geometry in
|
||||
ZStack(alignment: .center) {
|
||||
self.backgroundShape(size: geometry.size)
|
||||
self.ring(size: geometry.size, color: self.externalRingColor, lineWidth: 2)
|
||||
self.ring(
|
||||
size: CGSize(width: geometry.size.width, height: geometry.size.height),
|
||||
color: self.internalRingColor,
|
||||
lineWidth: 4
|
||||
)
|
||||
.scaleEffect(0.9, anchor: UnitPoint(x: 0.5, y: 0.5))
|
||||
.opacity(self.viewStore.state ? 1 : 0)
|
||||
|
||||
Image("checkmark")
|
||||
.opacity(self.viewStore.state ? 1 : 0)
|
||||
}
|
||||
.gesture(
|
||||
TapGesture()
|
||||
.onEnded { _ in self.viewStore.send(.updateIsChecked) }
|
||||
)
|
||||
}
|
||||
.frame(width: 30, height: 30, alignment: .center)
|
||||
}
|
||||
|
||||
func ringPath(size: CGSize) -> Path {
|
||||
Path { path in
|
||||
path.addArc(
|
||||
center: CGPoint(
|
||||
x: size.width / 2,
|
||||
y: size.height / 2
|
||||
),
|
||||
radius: size.width / 2,
|
||||
startAngle: Angle(degrees: 0),
|
||||
endAngle: Angle(degrees: 360),
|
||||
clockwise: true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
func ring(size: CGSize, color: Color, lineWidth: CGFloat) -> some View {
|
||||
ringPath(size: size)
|
||||
.stroke(color, lineWidth: lineWidth)
|
||||
}
|
||||
}
|
||||
|
||||
struct ZcashCheckCircle_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
VStack {
|
||||
Spacer()
|
||||
CheckCircle(viewStore: ViewStore(CheckCircleStore.mock(isChecked: true)))
|
||||
CheckCircle(viewStore: ViewStore(CheckCircleStore.mock(isChecked: false)))
|
||||
Spacer()
|
||||
}
|
||||
.applyDarkScreenBackground()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
// CheckCircleStore.swift
|
||||
// secant-testnet
|
||||
//
|
||||
// Created by Michal Fousek on 26.09.2022.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import ComposableArchitecture
|
||||
import SwiftUI
|
||||
|
||||
typealias CheckCircleReducer = Reducer<Bool, CheckCircleAction, Void>
|
||||
typealias CheckCircleStore = Store<Bool, CheckCircleAction>
|
||||
typealias CheckCircleViewStore = ViewStore<Bool, CheckCircleAction>
|
||||
|
||||
// MARK: - Action
|
||||
|
||||
enum CheckCircleAction: Equatable {
|
||||
case updateIsChecked
|
||||
}
|
||||
|
||||
// MARK: - Reducer
|
||||
|
||||
extension CheckCircleReducer {
|
||||
static let `default` = CheckCircleReducer { state, action, _ in
|
||||
switch action {
|
||||
case .updateIsChecked:
|
||||
state.toggle()
|
||||
return .none
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Store
|
||||
|
||||
extension CheckCircleStore {
|
||||
static func mock(isChecked: Bool) -> CheckCircleStore {
|
||||
return CheckCircleStore(
|
||||
initialState: isChecked,
|
||||
reducer: .default,
|
||||
environment: Void()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ViewStore
|
||||
|
||||
extension CheckCircleViewStore {
|
||||
static let placeholder = CheckCircleStore(
|
||||
initialState: true,
|
||||
reducer: .default,
|
||||
environment: Void()
|
||||
)
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// Wedge.swift
|
||||
// secant-testnet
|
||||
//
|
||||
// Created by Michal Fousek on 24.09.2022.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct Wedge: Shape {
|
||||
var startAngle: CGFloat
|
||||
var endAngle: CGFloat
|
||||
var clockwise = true
|
||||
|
||||
var animatableData: AnimatablePair<CGFloat, CGFloat> {
|
||||
get { AnimatablePair(startAngle, endAngle) }
|
||||
set {
|
||||
startAngle = newValue.first
|
||||
endAngle = newValue.second
|
||||
}
|
||||
}
|
||||
|
||||
func path(in rect: CGRect) -> Path {
|
||||
let callback: (inout Path) -> Void = { path in
|
||||
path.addArc(
|
||||
center: CGPoint(
|
||||
x: rect.midX,
|
||||
y: rect.midY
|
||||
),
|
||||
radius: rect.width / 2 ,
|
||||
startAngle: Angle(degrees: Double(startAngle)),
|
||||
endAngle: Angle(degrees: Double(endAngle)),
|
||||
clockwise: clockwise
|
||||
)
|
||||
}
|
||||
|
||||
return Path(callback)
|
||||
}
|
||||
}
|
|
@ -86,5 +86,9 @@ extension MultiLineTextFieldStore {
|
|||
// MARK: - Placeholders
|
||||
|
||||
extension MultiLineTextFieldState {
|
||||
static let placeholder = MultiLineTextFieldState()
|
||||
static let placeholder: MultiLineTextFieldState = {
|
||||
var state = MultiLineTextFieldState()
|
||||
state.text = "test"
|
||||
return state
|
||||
}()
|
||||
}
|
||||
|
|
|
@ -405,7 +405,7 @@ class MockWrappedSDKSynchronizer: WrappedSDKSynchronizer {
|
|||
) -> Effect<Result<TransactionState, NSError>, Never> {
|
||||
let transactionState = TransactionState(
|
||||
expirationHeight: 40,
|
||||
memo: "test",
|
||||
memo: memo,
|
||||
minedHeight: 50,
|
||||
shielded: true,
|
||||
zAddress: "tteafadlamnelkqe",
|
||||
|
|
|
@ -85,6 +85,67 @@ class SendTests: XCTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
func testSendSucceededWithoutMemo() throws {
|
||||
// the test needs to pass the exportWallet() so we simulate some in the keychain
|
||||
try storage.importWallet(bip39: "one two three", birthday: nil)
|
||||
|
||||
// setup the store and environment to be fully mocked
|
||||
let testScheduler = DispatchQueue.test
|
||||
|
||||
let testEnvironment = SendFlowEnvironment(
|
||||
derivationTool: .live(),
|
||||
mnemonic: .mock,
|
||||
numberFormatter: .live(),
|
||||
SDKSynchronizer: MockWrappedSDKSynchronizer(),
|
||||
scheduler: testScheduler.eraseToAnyScheduler(),
|
||||
walletStorage: .live(walletStorage: storage),
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
var state = SendFlowState.placeholder
|
||||
state.addMemoState = false
|
||||
|
||||
let store = TestStore(
|
||||
initialState: state,
|
||||
reducer: SendFlowReducer.default,
|
||||
environment: testEnvironment
|
||||
)
|
||||
|
||||
// simulate the sending confirmation button to be pressed
|
||||
store.send(.sendConfirmationPressed) { state in
|
||||
// once sending is confirmed, the attemts to try to send again by pressing the button
|
||||
// needs to be eliminated, indicated by the flag `isSendingTransaction`, need to be true
|
||||
state.isSendingTransaction = true
|
||||
}
|
||||
|
||||
testScheduler.advance(by: 0.01)
|
||||
|
||||
let transactionState = TransactionState(
|
||||
expirationHeight: 40,
|
||||
memo: nil,
|
||||
minedHeight: 50,
|
||||
shielded: true,
|
||||
zAddress: "tteafadlamnelkqe",
|
||||
fee: Zatoshi(10),
|
||||
id: "id",
|
||||
status: .paid(success: true),
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(10)
|
||||
)
|
||||
|
||||
// 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
|
||||
// the 'isSendingTransaction' needs to be false again
|
||||
state.isSendingTransaction = false
|
||||
}
|
||||
|
||||
// all went well, the success screen is triggered
|
||||
store.receive(.updateRoute(.success)) { state in
|
||||
state.route = .success
|
||||
}
|
||||
}
|
||||
|
||||
func testSendFailed() throws {
|
||||
// the test needs to pass the exportWallet() so we simulate some in the keychain
|
||||
try storage.importWallet(bip39: "one two three", birthday: nil)
|
||||
|
@ -235,6 +296,7 @@ class SendTests: XCTestCase {
|
|||
|
||||
func testFundsSufficiency() throws {
|
||||
let sendState = SendFlowState(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
transactionAddressInputState: .placeholder,
|
||||
transactionAmountInputState:
|
||||
|
@ -313,6 +375,7 @@ class SendTests: XCTestCase {
|
|||
|
||||
let store = TestStore(
|
||||
initialState: .init(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
route: nil,
|
||||
transactionAddressInputState: .placeholder,
|
||||
|
@ -346,6 +409,7 @@ class SendTests: XCTestCase {
|
|||
|
||||
func testValidForm() throws {
|
||||
let sendState = SendFlowState(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
transactionAddressInputState: .placeholder,
|
||||
transactionAmountInputState:
|
||||
|
@ -394,6 +458,7 @@ class SendTests: XCTestCase {
|
|||
|
||||
func testInvalidForm_InsufficientFunds() throws {
|
||||
let sendState = SendFlowState(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
transactionAddressInputState: .placeholder,
|
||||
transactionAmountInputState:
|
||||
|
@ -441,6 +506,7 @@ class SendTests: XCTestCase {
|
|||
|
||||
func testInvalidForm_AddressFormat() throws {
|
||||
let sendState = SendFlowState(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
transactionAddressInputState: .placeholder,
|
||||
transactionAmountInputState:
|
||||
|
@ -488,6 +554,7 @@ class SendTests: XCTestCase {
|
|||
|
||||
func testInvalidForm_AmountFormat() throws {
|
||||
let sendState = SendFlowState(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
transactionAddressInputState: .placeholder,
|
||||
transactionAmountInputState:
|
||||
|
@ -535,6 +602,7 @@ class SendTests: XCTestCase {
|
|||
|
||||
func testInvalidForm_ExceededMemoCharLimit() throws {
|
||||
let sendState = SendFlowState(
|
||||
addMemoState: true,
|
||||
memoState: MultiLineTextFieldState(charLimit: 3),
|
||||
shieldedBalance: WalletBalance(verified: Zatoshi(1), total: Zatoshi(1)),
|
||||
transactionAddressInputState:
|
||||
|
@ -588,6 +656,7 @@ class SendTests: XCTestCase {
|
|||
|
||||
func testMemoCharLimitSet() throws {
|
||||
let sendState = SendFlowState(
|
||||
addMemoState: true,
|
||||
memoState: .placeholder,
|
||||
transactionAddressInputState: .placeholder,
|
||||
transactionAmountInputState:
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
//
|
||||
// TransactionConfirmationSnapshotTests.swift
|
||||
// secantTests
|
||||
//
|
||||
// Created by Michal Fousek on 26.09.2022.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import secant_testnet
|
||||
import ComposableArchitecture
|
||||
import SwiftUI
|
||||
import ZcashLightClientKit
|
||||
|
||||
class TransactionConfirmationSnapshotTests: XCTestCase {
|
||||
func testTransactionConfirmationSnapshot_addMemo() 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(TransactionConfirmation(store: store))
|
||||
}
|
||||
|
||||
func testTransactionConfirmationSnapshot_dontAddMemo() 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(TransactionConfirmation(store: store))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue