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 */; };
|
2EDA07A027EDE18C00D6F09B /* TCATextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA079F27EDE18C00D6F09B /* TCATextField.swift */; };
|
||||||
2EDA07A227EDE1AE00D6F09B /* TextFieldFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA07A127EDE1AE00D6F09B /* TextFieldFooter.swift */; };
|
2EDA07A227EDE1AE00D6F09B /* TextFieldFooter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA07A127EDE1AE00D6F09B /* TextFieldFooter.swift */; };
|
||||||
2EDA07A427EDE2A900D6F09B /* DebugFrame.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2EDA07A327EDE2A900D6F09B /* DebugFrame.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 */; };
|
660558E9270C7A54009D6954 /* Colors.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 660558E8270C7A54009D6954 /* Colors.xcassets */; };
|
||||||
660558F7270C862F009D6954 /* Fonts+Generated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 660558F5270C862F009D6954 /* Fonts+Generated.swift */; };
|
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 */; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
660558F6270C862F009D6954 /* XCAssets+Generated.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "XCAssets+Generated.swift"; sourceTree = "<group>"; };
|
||||||
|
@ -488,6 +498,7 @@
|
||||||
0D0781C5278776B90083ACD7 /* Shapes */ = {
|
0D0781C5278776B90083ACD7 /* Shapes */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
34E0AF1028DEE5220034CF37 /* Wedge.swift */,
|
||||||
0D0781C7278776D20083ACD7 /* ZcashSymbol.swift */,
|
0D0781C7278776D20083ACD7 /* ZcashSymbol.swift */,
|
||||||
);
|
);
|
||||||
path = Shapes;
|
path = Shapes;
|
||||||
|
@ -707,6 +718,23 @@
|
||||||
path = Components;
|
path = Components;
|
||||||
sourceTree = "<group>";
|
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 */ = {
|
663FAB9A271D873300E495F8 /* Buttons */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -866,17 +894,18 @@
|
||||||
9E391162284E3ECF0073DD9A /* SnapshotTests */ = {
|
9E391162284E3ECF0073DD9A /* SnapshotTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
9E92AF0728530EBF007367AD /* View+UIImage.swift */,
|
||||||
9E94C62128AA7ECD008256E9 /* BalanceBreakdownSnapshotTests */,
|
9E94C62128AA7ECD008256E9 /* BalanceBreakdownSnapshotTests */,
|
||||||
9E7225EF2889537E00DF7F17 /* SettingsSnapshotTests */,
|
|
||||||
9E7CB6252874267B00A02233 /* ProfileSnapshotTests */,
|
|
||||||
9E7CB6102869881300A02233 /* WalletEventsSnapshotTests */,
|
|
||||||
9E9ECC8B28589E150099D5A2 /* HomeSnapshotTests */,
|
9E9ECC8B28589E150099D5A2 /* HomeSnapshotTests */,
|
||||||
9E9ECC9328589E150099D5A2 /* ImportWalletSnapshotTests */,
|
9E9ECC9328589E150099D5A2 /* ImportWalletSnapshotTests */,
|
||||||
9E9ECC9528589E150099D5A2 /* OnboardingSnapshotTests */,
|
9E9ECC9528589E150099D5A2 /* OnboardingSnapshotTests */,
|
||||||
|
9E7CB6252874267B00A02233 /* ProfileSnapshotTests */,
|
||||||
9E9ECC8F28589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests */,
|
9E9ECC8F28589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests */,
|
||||||
9E9ECC9128589E150099D5A2 /* RecoveryPhraseValidationFlowSnapshotTests */,
|
9E9ECC9128589E150099D5A2 /* RecoveryPhraseValidationFlowSnapshotTests */,
|
||||||
|
346715A628E20FB30035F7C4 /* SendSnapshotTests */,
|
||||||
|
9E7225EF2889537E00DF7F17 /* SettingsSnapshotTests */,
|
||||||
|
9E7CB6102869881300A02233 /* WalletEventsSnapshotTests */,
|
||||||
9E9ECC8D28589E150099D5A2 /* WelcomeSnapshotTests */,
|
9E9ECC8D28589E150099D5A2 /* WelcomeSnapshotTests */,
|
||||||
9E92AF0728530EBF007367AD /* View+UIImage.swift */,
|
|
||||||
);
|
);
|
||||||
path = SnapshotTests;
|
path = SnapshotTests;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1073,6 +1102,7 @@
|
||||||
9E7FE0BE282D1DFE00C374E8 /* UI Components */ = {
|
9E7FE0BE282D1DFE00C374E8 /* UI Components */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
346D41E228DF0B0900963F36 /* CheckCircle */,
|
||||||
9E7CB6132869E8A700A02233 /* CircularProgress */,
|
9E7CB6132869E8A700A02233 /* CircularProgress */,
|
||||||
0DF2DC5227235E1F00FA31E2 /* Extensions */,
|
0DF2DC5227235E1F00FA31E2 /* Extensions */,
|
||||||
0DB8AA80271DC7520035BC9D /* DesignGuide.swift */,
|
0DB8AA80271DC7520035BC9D /* DesignGuide.swift */,
|
||||||
|
@ -1355,8 +1385,9 @@
|
||||||
children = (
|
children = (
|
||||||
F9C165BB2740403600592F76 /* CreateTransactionView.swift */,
|
F9C165BB2740403600592F76 /* CreateTransactionView.swift */,
|
||||||
F9C165B92740403600592F76 /* TransactionConfirmationView.swift */,
|
F9C165B92740403600592F76 /* TransactionConfirmationView.swift */,
|
||||||
F9C165BD2740403600592F76 /* TransactionSentView.swift */,
|
|
||||||
9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */,
|
9E5BF640281FD7B600BA3F17 /* TransactionFailedView.swift */,
|
||||||
|
F9C165BD2740403600592F76 /* TransactionSentView.swift */,
|
||||||
|
34E0AF0E28DEE4C70034CF37 /* HoldToSendButton.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1588,6 +1619,7 @@
|
||||||
2EB7758727FC67FD00269373 /* TransactionAmountTextFieldStore.swift in Sources */,
|
2EB7758727FC67FD00269373 /* TransactionAmountTextFieldStore.swift in Sources */,
|
||||||
669FDAE9272C23B3007B9422 /* CircularFrame.swift in Sources */,
|
669FDAE9272C23B3007B9422 /* CircularFrame.swift in Sources */,
|
||||||
9EF8136027F043CC0075AF48 /* AppDelegate.swift in Sources */,
|
9EF8136027F043CC0075AF48 /* AppDelegate.swift in Sources */,
|
||||||
|
34E0AF1128DEE5220034CF37 /* Wedge.swift in Sources */,
|
||||||
F96B41E8273B501F0021B49A /* TransactionDetailView.swift in Sources */,
|
F96B41E8273B501F0021B49A /* TransactionDetailView.swift in Sources */,
|
||||||
9E02B56A27FED43E005B809B /* WrappedFileManager.swift in Sources */,
|
9E02B56A27FED43E005B809B /* WrappedFileManager.swift in Sources */,
|
||||||
663FABA2271D876C00E495F8 /* SecondaryButton.swift in Sources */,
|
663FABA2271D876C00E495F8 /* SecondaryButton.swift in Sources */,
|
||||||
|
@ -1617,6 +1649,7 @@
|
||||||
9E2DF99D27CF704D00649636 /* ImportSeedEditor.swift in Sources */,
|
9E2DF99D27CF704D00649636 /* ImportSeedEditor.swift in Sources */,
|
||||||
F9971A5327680DD000A2DB75 /* ProfileStore.swift in Sources */,
|
F9971A5327680DD000A2DB75 /* ProfileStore.swift in Sources */,
|
||||||
9E39114D2848EEB90073DD9A /* WalletStorage.swift in Sources */,
|
9E39114D2848EEB90073DD9A /* WalletStorage.swift in Sources */,
|
||||||
|
346D41E428DF0B8600963F36 /* CheckCircle.swift in Sources */,
|
||||||
669FDAEB272C23C2007B9422 /* CircularFrameBadge.swift in Sources */,
|
669FDAEB272C23C2007B9422 /* CircularFrameBadge.swift in Sources */,
|
||||||
9E39113B2848D5180073DD9A /* WrappedNumberFormatter.swift in Sources */,
|
9E39113B2848D5180073DD9A /* WrappedNumberFormatter.swift in Sources */,
|
||||||
2E8719CD27FB0D3B0082C926 /* CurrencySelectionView.swift in Sources */,
|
2E8719CD27FB0D3B0082C926 /* CurrencySelectionView.swift in Sources */,
|
||||||
|
@ -1671,6 +1704,7 @@
|
||||||
663FAB9C271D874D00E495F8 /* ActiveButton.swift in Sources */,
|
663FAB9C271D874D00E495F8 /* ActiveButton.swift in Sources */,
|
||||||
9E2F1C842809B606004E65FE /* DebugMenu.swift in Sources */,
|
9E2F1C842809B606004E65FE /* DebugMenu.swift in Sources */,
|
||||||
9E02B5C3280458D2005B809B /* WrappedDerivationTool.swift in Sources */,
|
9E02B5C3280458D2005B809B /* WrappedDerivationTool.swift in Sources */,
|
||||||
|
34E0AF0F28DEE4C70034CF37 /* HoldToSendButton.swift in Sources */,
|
||||||
F9C165C02740403600592F76 /* TransactionConfirmationView.swift in Sources */,
|
F9C165C02740403600592F76 /* TransactionConfirmationView.swift in Sources */,
|
||||||
0DF2DC5427235E3E00FA31E2 /* View+InnerShadow.swift in Sources */,
|
0DF2DC5427235E3E00FA31E2 /* View+InnerShadow.swift in Sources */,
|
||||||
9E39113F2848EC360073DD9A /* WrappedRecoveryPhraseRandomizer.swift in Sources */,
|
9E39113F2848EC360073DD9A /* WrappedRecoveryPhraseRandomizer.swift in Sources */,
|
||||||
|
@ -1689,6 +1723,7 @@
|
||||||
66A0807B271993C500118B79 /* OnboardingProgressIndicator.swift in Sources */,
|
66A0807B271993C500118B79 /* OnboardingProgressIndicator.swift in Sources */,
|
||||||
0D7DF08C271DCC0E00530046 /* ScreenBackground.swift in Sources */,
|
0D7DF08C271DCC0E00530046 /* ScreenBackground.swift in Sources */,
|
||||||
9E01F8242833C0D8000EFC57 /* WrappedURIParser.swift in Sources */,
|
9E01F8242833C0D8000EFC57 /* WrappedURIParser.swift in Sources */,
|
||||||
|
346715A528E2027D0035F7C4 /* CheckCircleStore.swift in Sources */,
|
||||||
F9C165C22740403600592F76 /* CreateTransactionView.swift in Sources */,
|
F9C165C22740403600592F76 /* CreateTransactionView.swift in Sources */,
|
||||||
F9C165B4274031F600592F76 /* Bindings.swift in Sources */,
|
F9C165B4274031F600592F76 /* Bindings.swift in Sources */,
|
||||||
2E35F99A27B3E99C00EB79CD /* TextFieldTitleAccessoryButtonStyle.swift in Sources */,
|
2E35F99A27B3E99C00EB79CD /* TextFieldTitleAccessoryButtonStyle.swift in Sources */,
|
||||||
|
@ -1747,6 +1782,7 @@
|
||||||
9E391132284644580073DD9A /* AppInitializationTests.swift in Sources */,
|
9E391132284644580073DD9A /* AppInitializationTests.swift in Sources */,
|
||||||
9E9ECC9928589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift in Sources */,
|
9E9ECC9928589E150099D5A2 /* RecoveryPhraseDisplaySnapshotTests.swift in Sources */,
|
||||||
9E391124283E4CAC0073DD9A /* ImportWalletTests.swift in Sources */,
|
9E391124283E4CAC0073DD9A /* ImportWalletTests.swift in Sources */,
|
||||||
|
346715A828E20FE40035F7C4 /* TransactionConfirmationSnapshotTests.swift in Sources */,
|
||||||
9E5BF63F2819542C00BA3F17 /* WalletEventsTests.swift in Sources */,
|
9E5BF63F2819542C00BA3F17 /* WalletEventsTests.swift in Sources */,
|
||||||
0D4E7A1B26B364180058B01E /* secantTests.swift in Sources */,
|
0D4E7A1B26B364180058B01E /* secantTests.swift in Sources */,
|
||||||
0DFE93E6272CB6F7000FCCA5 /* RecoveryPhraseValidationTests.swift in Sources */,
|
0DFE93E6272CB6F7000FCCA5 /* RecoveryPhraseValidationTests.swift in Sources */,
|
||||||
|
@ -2082,7 +2118,7 @@
|
||||||
repositoryURL = "https://github.com/zcash/ZcashLightClientKit/";
|
repositoryURL = "https://github.com/zcash/ZcashLightClientKit/";
|
||||||
requirement = {
|
requirement = {
|
||||||
kind = exactVersion;
|
kind = exactVersion;
|
||||||
version = "0.16.6-beta";
|
version = "0.16.10-beta";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
|
6654C7382715A38000901167 /* XCRemoteSwiftPackageReference "swift-composable-architecture" */ = {
|
||||||
|
|
|
@ -203,8 +203,8 @@
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
"location" : "https://github.com/zcash/ZcashLightClientKit",
|
"location" : "https://github.com/zcash/ZcashLightClientKit",
|
||||||
"state" : {
|
"state" : {
|
||||||
"revision" : "a37c140441d78fa6ad9c89e2fbb539f1ddb7e5a1",
|
"revision" : "9e41fb43757fd7b0eb8e817320537230774258cf",
|
||||||
"version" : "0.16.6-beta"
|
"version" : "0.16.10-beta"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct SendFlowState: Equatable {
|
||||||
case done
|
case done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var addMemoState: Bool
|
||||||
var isSendingTransaction = false
|
var isSendingTransaction = false
|
||||||
var memoState: MultiLineTextFieldState
|
var memoState: MultiLineTextFieldState
|
||||||
var route: Route?
|
var route: Route?
|
||||||
|
@ -74,6 +75,7 @@ struct SendFlowState: Equatable {
|
||||||
// MARK: - Action
|
// MARK: - Action
|
||||||
|
|
||||||
enum SendFlowAction: Equatable {
|
enum SendFlowAction: Equatable {
|
||||||
|
case addMemo(CheckCircleAction)
|
||||||
case memo(MultiLineTextFieldAction)
|
case memo(MultiLineTextFieldAction)
|
||||||
case onAppear
|
case onAppear
|
||||||
case onDisappear
|
case onDisappear
|
||||||
|
@ -107,12 +109,16 @@ extension SendFlowReducer {
|
||||||
sendReducer,
|
sendReducer,
|
||||||
transactionAddressInputReducer,
|
transactionAddressInputReducer,
|
||||||
transactionAmountInputReducer,
|
transactionAmountInputReducer,
|
||||||
memoReducer
|
memoReducer,
|
||||||
|
addMemoReducer
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
private static let sendReducer = SendFlowReducer { state, action, environment in
|
private static let sendReducer = SendFlowReducer { state, action, environment in
|
||||||
switch action {
|
switch action {
|
||||||
|
case .addMemo:
|
||||||
|
return .none
|
||||||
|
|
||||||
case .updateRoute(.failure):
|
case .updateRoute(.failure):
|
||||||
state.route = .failure
|
state.route = .failure
|
||||||
state.isSendingTransaction = false
|
state.isSendingTransaction = false
|
||||||
|
@ -146,7 +152,7 @@ extension SendFlowReducer {
|
||||||
with: spendingKey,
|
with: spendingKey,
|
||||||
zatoshi: state.amount,
|
zatoshi: state.amount,
|
||||||
to: state.address,
|
to: state.address,
|
||||||
memo: state.memoState.text,
|
memo: state.addMemoState ? state.memoState.text : nil,
|
||||||
from: 0
|
from: 0
|
||||||
)
|
)
|
||||||
.receive(on: environment.scheduler)
|
.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(
|
private static let transactionAddressInputReducer: SendFlowReducer = TransactionAddressTextFieldReducer.default.pullback(
|
||||||
state: \SendFlowState.transactionAddressInputState,
|
state: \SendFlowState.transactionAddressInputState,
|
||||||
action: /SendFlowAction.transactionAddressInput,
|
action: /SendFlowAction.transactionAddressInput,
|
||||||
|
@ -237,6 +249,13 @@ extension SendFlowReducer {
|
||||||
// MARK: - Store
|
// MARK: - Store
|
||||||
|
|
||||||
extension SendFlowStore {
|
extension SendFlowStore {
|
||||||
|
func addMemoStore() -> CheckCircleStore {
|
||||||
|
self.scope(
|
||||||
|
state: \.addMemoState,
|
||||||
|
action: SendFlowAction.addMemo
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
func memoStore() -> MultiLineTextFieldStore {
|
func memoStore() -> MultiLineTextFieldStore {
|
||||||
self.scope(
|
self.scope(
|
||||||
state: \.memoState,
|
state: \.memoState,
|
||||||
|
@ -289,6 +308,7 @@ extension SendFlowViewStore {
|
||||||
extension SendFlowState {
|
extension SendFlowState {
|
||||||
static var placeholder: Self {
|
static var placeholder: Self {
|
||||||
.init(
|
.init(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
route: nil,
|
route: nil,
|
||||||
transactionAddressInputState: .placeholder,
|
transactionAddressInputState: .placeholder,
|
||||||
|
@ -298,6 +318,7 @@ extension SendFlowState {
|
||||||
|
|
||||||
static var emptyPlaceholder: Self {
|
static var emptyPlaceholder: Self {
|
||||||
.init(
|
.init(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
route: nil,
|
route: nil,
|
||||||
transactionAddressInputState: .placeholder,
|
transactionAddressInputState: .placeholder,
|
||||||
|
@ -310,12 +331,7 @@ extension SendFlowState {
|
||||||
extension SendFlowStore {
|
extension SendFlowStore {
|
||||||
static var placeholder: SendFlowStore {
|
static var placeholder: SendFlowStore {
|
||||||
return SendFlowStore(
|
return SendFlowStore(
|
||||||
initialState: .init(
|
initialState: .emptyPlaceholder,
|
||||||
memoState: .placeholder,
|
|
||||||
route: nil,
|
|
||||||
transactionAddressInputState: .placeholder,
|
|
||||||
transactionAmountInputState: .placeholder
|
|
||||||
),
|
|
||||||
reducer: .default,
|
reducer: .default,
|
||||||
environment: SendFlowEnvironment(
|
environment: SendFlowEnvironment(
|
||||||
derivationTool: .live(),
|
derivationTool: .live(),
|
||||||
|
|
|
@ -19,7 +19,7 @@ struct SendFlowView: View {
|
||||||
.navigationLinkEmpty(
|
.navigationLinkEmpty(
|
||||||
isActive: viewStore.bindingForConfirmation,
|
isActive: viewStore.bindingForConfirmation,
|
||||||
destination: {
|
destination: {
|
||||||
TransactionConfirmation(viewStore: viewStore)
|
TransactionConfirmation(store: store)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ struct SendFLowView_Previews: PreviewProvider {
|
||||||
SendFlowView(
|
SendFlowView(
|
||||||
store: .init(
|
store: .init(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
route: nil,
|
route: nil,
|
||||||
transactionAddressInputState: .placeholder,
|
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,37 +2,45 @@ import SwiftUI
|
||||||
import ComposableArchitecture
|
import ComposableArchitecture
|
||||||
|
|
||||||
struct TransactionConfirmation: View {
|
struct TransactionConfirmation: View {
|
||||||
let viewStore: SendFlowViewStore
|
let store: SendFlowStore
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
WithViewStore(store) { viewStore in
|
||||||
Text("Send \(viewStore.amount.decimalString()) ZEC")
|
VStack {
|
||||||
.padding()
|
Text("Send \(viewStore.amount.decimalString()) ZEC to")
|
||||||
|
.padding()
|
||||||
|
.foregroundColor(Asset.Colors.Text.forDarkBackground.color)
|
||||||
|
|
||||||
Text("To \(viewStore.address)")
|
Text("\(viewStore.address)?")
|
||||||
.padding()
|
.truncationMode(.middle)
|
||||||
|
.lineLimit(1)
|
||||||
|
.padding()
|
||||||
|
.foregroundColor(Asset.Colors.Text.forDarkBackground.color)
|
||||||
|
|
||||||
Spacer()
|
HStack {
|
||||||
|
CheckCircle(viewStore: ViewStore(store.addMemoStore()))
|
||||||
|
Text("Includes memo")
|
||||||
|
.foregroundColor(Asset.Colors.Text.forDarkBackground.color)
|
||||||
|
}
|
||||||
|
|
||||||
Button(
|
Spacer()
|
||||||
action: { viewStore.send(.sendConfirmationPressed) },
|
|
||||||
label: { Text("Confirm") }
|
HoldToSendButton {
|
||||||
|
viewStore.send(.sendConfirmationPressed)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
.applyDarkScreenBackground()
|
||||||
|
.navigationLinkEmpty(
|
||||||
|
isActive: viewStore.bindingForSuccess,
|
||||||
|
destination: { TransactionSent(viewStore: viewStore) }
|
||||||
|
)
|
||||||
|
.navigationLinkEmpty(
|
||||||
|
isActive: viewStore.bindingForFailure,
|
||||||
|
destination: { TransactionFailed(viewStore: viewStore) }
|
||||||
)
|
)
|
||||||
.activeButtonStyle
|
|
||||||
.frame(height: 50)
|
|
||||||
.padding()
|
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
.applyScreenBackground()
|
|
||||||
.navigationLinkEmpty(
|
|
||||||
isActive: viewStore.bindingForSuccess,
|
|
||||||
destination: { TransactionSent(viewStore: viewStore) }
|
|
||||||
)
|
|
||||||
.navigationLinkEmpty(
|
|
||||||
isActive: viewStore.bindingForFailure,
|
|
||||||
destination: { TransactionFailed(viewStore: viewStore) }
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,11 +52,8 @@ struct Confirmation_Previews: PreviewProvider {
|
||||||
StateContainer(
|
StateContainer(
|
||||||
initialState: (false)
|
initialState: (false)
|
||||||
) { _ in
|
) { _ in
|
||||||
TransactionConfirmation(
|
TransactionConfirmation(store: .placeholder)
|
||||||
viewStore: ViewStore(.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",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0x45",
|
"blue" : "69",
|
||||||
"green" : "0x1F",
|
"green" : "31",
|
||||||
"red" : "0x13"
|
"red" : "19"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|
|
@ -23,9 +23,9 @@
|
||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0x00",
|
"blue" : "0",
|
||||||
"green" : "0x00",
|
"green" : "0",
|
||||||
"red" : "0x00"
|
"red" : "0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"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",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "0.200",
|
"alpha" : "0.200",
|
||||||
"blue" : "0x36",
|
"blue" : "54",
|
||||||
"green" : "0x2C",
|
"green" : "44",
|
||||||
"red" : "0x27"
|
"red" : "39"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
@ -23,9 +23,9 @@
|
||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "0.250",
|
"alpha" : "0.250",
|
||||||
"blue" : "0x00",
|
"blue" : "0",
|
||||||
"green" : "0x00",
|
"green" : "0",
|
||||||
"red" : "0x00"
|
"red" : "0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"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",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "0.827",
|
"alpha" : "0.827",
|
||||||
"blue" : "0.623",
|
"blue" : "0x9E",
|
||||||
"green" : "0.589",
|
"green" : "0x96",
|
||||||
"red" : "0.560"
|
"red" : "0x8E"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
@ -23,9 +23,9 @@
|
||||||
"color-space" : "srgb",
|
"color-space" : "srgb",
|
||||||
"components" : {
|
"components" : {
|
||||||
"alpha" : "1.000",
|
"alpha" : "1.000",
|
||||||
"blue" : "0.290",
|
"blue" : "0x49",
|
||||||
"green" : "0.275",
|
"green" : "0x46",
|
||||||
"red" : "0.259"
|
"red" : "0x42"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"idiom" : "universal"
|
"idiom" : "universal"
|
||||||
|
|
|
@ -35,6 +35,7 @@ internal enum Asset {
|
||||||
}
|
}
|
||||||
internal enum Icons {
|
internal enum Icons {
|
||||||
internal static let bank = ImageAsset(name: "bank")
|
internal static let bank = ImageAsset(name: "bank")
|
||||||
|
internal static let checkmark = ImageAsset(name: "checkmark")
|
||||||
internal static let list = ImageAsset(name: "list")
|
internal static let list = ImageAsset(name: "list")
|
||||||
internal static let profile = ImageAsset(name: "profile")
|
internal static let profile = ImageAsset(name: "profile")
|
||||||
internal static let qrCode = ImageAsset(name: "qr-code")
|
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 secondaryButton = ColorAsset(name: "SecondaryButton")
|
||||||
internal static let secondaryButtonPressed = ColorAsset(name: "SecondaryButtonPressed")
|
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 enum Cursor {
|
||||||
internal static let bar = ColorAsset(name: "Bar")
|
internal static let bar = ColorAsset(name: "Bar")
|
||||||
}
|
}
|
||||||
|
@ -86,11 +91,14 @@ internal enum Asset {
|
||||||
internal static let gradientLeft = ColorAsset(name: "GradientLeft")
|
internal static let gradientLeft = ColorAsset(name: "GradientLeft")
|
||||||
internal static let gradientRight = ColorAsset(name: "GradientRight")
|
internal static let gradientRight = ColorAsset(name: "GradientRight")
|
||||||
internal static let negativeSpace = ColorAsset(name: "NegativeSpace")
|
internal static let negativeSpace = ColorAsset(name: "NegativeSpace")
|
||||||
|
internal static let holdToSendButton = ColorAsset(name: "holdToSendButton")
|
||||||
}
|
}
|
||||||
internal enum QRScan {
|
internal enum QRScan {
|
||||||
internal static let frame = ColorAsset(name: "frame")
|
internal static let frame = ColorAsset(name: "frame")
|
||||||
}
|
}
|
||||||
internal enum ScreenBackground {
|
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 gradientEnd = ColorAsset(name: "gradientEnd")
|
||||||
internal static let gradientStart = ColorAsset(name: "gradientStart")
|
internal static let gradientStart = ColorAsset(name: "gradientStart")
|
||||||
internal static let greenGradientEnd = ColorAsset(name: "greenGradientEnd")
|
internal static let greenGradientEnd = ColorAsset(name: "greenGradientEnd")
|
||||||
|
@ -104,6 +112,7 @@ internal enum Asset {
|
||||||
internal enum Shadow {
|
internal enum Shadow {
|
||||||
internal static let drawerShadow = ColorAsset(name: "drawerShadow")
|
internal static let drawerShadow = ColorAsset(name: "drawerShadow")
|
||||||
internal static let emptyChipInnerShadow = ColorAsset(name: "emptyChipInnerShadow")
|
internal static let emptyChipInnerShadow = ColorAsset(name: "emptyChipInnerShadow")
|
||||||
|
internal static let holdToSendButtonShadow = ColorAsset(name: "holdToSendButtonShadow")
|
||||||
internal static let numberedTextShadow = ColorAsset(name: "numberedTextShadow")
|
internal static let numberedTextShadow = ColorAsset(name: "numberedTextShadow")
|
||||||
}
|
}
|
||||||
internal enum Text {
|
internal enum Text {
|
||||||
|
@ -124,6 +133,7 @@ internal enum Asset {
|
||||||
internal static let balanceText = ColorAsset(name: "balanceText")
|
internal static let balanceText = ColorAsset(name: "balanceText")
|
||||||
internal static let captionText = ColorAsset(name: "captionText")
|
internal static let captionText = ColorAsset(name: "captionText")
|
||||||
internal static let captionTextShadow = ColorAsset(name: "captionTextShadow")
|
internal static let captionTextShadow = ColorAsset(name: "captionTextShadow")
|
||||||
|
internal static let forDarkBackground = ColorAsset(name: "forDarkBackground")
|
||||||
internal static let highlightedSuperscriptText = ColorAsset(name: "highlightedSuperscriptText")
|
internal static let highlightedSuperscriptText = ColorAsset(name: "highlightedSuperscriptText")
|
||||||
internal static let moreInfoText = ColorAsset(name: "moreInfoText")
|
internal static let moreInfoText = ColorAsset(name: "moreInfoText")
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ extension ScreenBackground {
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ScreenBackgroundModifier: ViewModifier {
|
struct ScreenBackgroundModifier: ViewModifier {
|
||||||
var colors: [Color]
|
var colors: [Color]
|
||||||
var darkGradientEndPointY = 1.0
|
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 {
|
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
|
// MARK: - Placeholders
|
||||||
|
|
||||||
extension MultiLineTextFieldState {
|
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> {
|
) -> Effect<Result<TransactionState, NSError>, Never> {
|
||||||
let transactionState = TransactionState(
|
let transactionState = TransactionState(
|
||||||
expirationHeight: 40,
|
expirationHeight: 40,
|
||||||
memo: "test",
|
memo: memo,
|
||||||
minedHeight: 50,
|
minedHeight: 50,
|
||||||
shielded: true,
|
shielded: true,
|
||||||
zAddress: "tteafadlamnelkqe",
|
zAddress: "tteafadlamnelkqe",
|
||||||
|
|
|
@ -84,6 +84,67 @@ class SendTests: XCTestCase {
|
||||||
state.route = .success
|
state.route = .success
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 {
|
func testSendFailed() throws {
|
||||||
// the test needs to pass the exportWallet() so we simulate some in the keychain
|
// the test needs to pass the exportWallet() so we simulate some in the keychain
|
||||||
|
@ -235,6 +296,7 @@ class SendTests: XCTestCase {
|
||||||
|
|
||||||
func testFundsSufficiency() throws {
|
func testFundsSufficiency() throws {
|
||||||
let sendState = SendFlowState(
|
let sendState = SendFlowState(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
transactionAddressInputState: .placeholder,
|
transactionAddressInputState: .placeholder,
|
||||||
transactionAmountInputState:
|
transactionAmountInputState:
|
||||||
|
@ -313,6 +375,7 @@ class SendTests: XCTestCase {
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: .init(
|
initialState: .init(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
route: nil,
|
route: nil,
|
||||||
transactionAddressInputState: .placeholder,
|
transactionAddressInputState: .placeholder,
|
||||||
|
@ -346,6 +409,7 @@ class SendTests: XCTestCase {
|
||||||
|
|
||||||
func testValidForm() throws {
|
func testValidForm() throws {
|
||||||
let sendState = SendFlowState(
|
let sendState = SendFlowState(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
transactionAddressInputState: .placeholder,
|
transactionAddressInputState: .placeholder,
|
||||||
transactionAmountInputState:
|
transactionAmountInputState:
|
||||||
|
@ -394,6 +458,7 @@ class SendTests: XCTestCase {
|
||||||
|
|
||||||
func testInvalidForm_InsufficientFunds() throws {
|
func testInvalidForm_InsufficientFunds() throws {
|
||||||
let sendState = SendFlowState(
|
let sendState = SendFlowState(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
transactionAddressInputState: .placeholder,
|
transactionAddressInputState: .placeholder,
|
||||||
transactionAmountInputState:
|
transactionAmountInputState:
|
||||||
|
@ -441,6 +506,7 @@ class SendTests: XCTestCase {
|
||||||
|
|
||||||
func testInvalidForm_AddressFormat() throws {
|
func testInvalidForm_AddressFormat() throws {
|
||||||
let sendState = SendFlowState(
|
let sendState = SendFlowState(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
transactionAddressInputState: .placeholder,
|
transactionAddressInputState: .placeholder,
|
||||||
transactionAmountInputState:
|
transactionAmountInputState:
|
||||||
|
@ -488,6 +554,7 @@ class SendTests: XCTestCase {
|
||||||
|
|
||||||
func testInvalidForm_AmountFormat() throws {
|
func testInvalidForm_AmountFormat() throws {
|
||||||
let sendState = SendFlowState(
|
let sendState = SendFlowState(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
transactionAddressInputState: .placeholder,
|
transactionAddressInputState: .placeholder,
|
||||||
transactionAmountInputState:
|
transactionAmountInputState:
|
||||||
|
@ -535,6 +602,7 @@ class SendTests: XCTestCase {
|
||||||
|
|
||||||
func testInvalidForm_ExceededMemoCharLimit() throws {
|
func testInvalidForm_ExceededMemoCharLimit() throws {
|
||||||
let sendState = SendFlowState(
|
let sendState = SendFlowState(
|
||||||
|
addMemoState: true,
|
||||||
memoState: MultiLineTextFieldState(charLimit: 3),
|
memoState: MultiLineTextFieldState(charLimit: 3),
|
||||||
shieldedBalance: WalletBalance(verified: Zatoshi(1), total: Zatoshi(1)),
|
shieldedBalance: WalletBalance(verified: Zatoshi(1), total: Zatoshi(1)),
|
||||||
transactionAddressInputState:
|
transactionAddressInputState:
|
||||||
|
@ -588,6 +656,7 @@ class SendTests: XCTestCase {
|
||||||
|
|
||||||
func testMemoCharLimitSet() throws {
|
func testMemoCharLimitSet() throws {
|
||||||
let sendState = SendFlowState(
|
let sendState = SendFlowState(
|
||||||
|
addMemoState: true,
|
||||||
memoState: .placeholder,
|
memoState: .placeholder,
|
||||||
transactionAddressInputState: .placeholder,
|
transactionAddressInputState: .placeholder,
|
||||||
transactionAmountInputState:
|
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