[#102] [Functional] Full Wallet History
- initial frame connected to available data (progress) - zboto balance - $ balance - inner / outer progress logic - isDownloading and isUpToDate controls added - outer circle parametrical solution implemented - unit tests fixed - SyncStatusSnapshot implemented - snapshot tests [102] [Functional] Full Wallet History - latest design updates - solved issue with the List and accessory views [102] [Functional] Full Wallet History - fixes for the 'all' button - reduced actions for the detail binding [102] [Functional] Full Wallet History - padding fixes (all events are visible) - home screen drawer's height set to show 3 events on screen [102] [Functional] Full Wallet History - final UI for all states of transaction for rows - Lottie package added - Lottie animation for the pending transaction added [102] [Functional] Full Wallet History - snapshot tests cleaned up and refactored - snapshotting all 4 types of transaction wallet events rows (sent, pending, received, failed) [102] [Functional] Full Wallet History (393) - Rubik fonts [102] [Functional] Full Wallet History (393) - leading padding fixed - UITableView appearance moved to onAppear() [153] [Scaffold] Progress Status Circular Bar (#389) - rebased
This commit is contained in:
parent
282fdbcdf0
commit
5b158b9e72
|
@ -124,6 +124,12 @@
|
|||
9E69A24D27FB002800A55317 /* WelcomeStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E69A24C27FB002800A55317 /* WelcomeStore.swift */; };
|
||||
9E7CB6122869882D00A02233 /* WalletEventsSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB6112869882D00A02233 /* WalletEventsSnapshotTests.swift */; };
|
||||
9E7CB6152869E8C300A02233 /* CircularProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB6142869E8C300A02233 /* CircularProgress.swift */; };
|
||||
9E6612312878337F00C75B70 /* Lottie in Frameworks */ = {isa = PBXBuildFile; productRef = 9E6612302878337F00C75B70 /* Lottie */; };
|
||||
9E6612332878338C00C75B70 /* LottieAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E6612322878338C00C75B70 /* LottieAnimation.swift */; };
|
||||
9E6612362878345000C75B70 /* endlessCircleProgress.json in Resources */ = {isa = PBXBuildFile; fileRef = 9E6612352878345000C75B70 /* endlessCircleProgress.json */; };
|
||||
9E69A24D27FB002800A55317 /* WelcomeStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E69A24C27FB002800A55317 /* WelcomeStore.swift */; };
|
||||
9E7CB6122869882D00A02233 /* WalletEventsSnapshotTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB6112869882D00A02233 /* WalletEventsSnapshotTests.swift */; };
|
||||
9E7CB6182872D3DF00A02233 /* URLRouting in Frameworks */ = {isa = PBXBuildFile; productRef = 9E7CB6172872D3DF00A02233 /* URLRouting */; };
|
||||
9E7CB61A287310EC00A02233 /* QRCodeGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB619287310EC00A02233 /* QRCodeGenerator.swift */; };
|
||||
9E7CB6202874143800A02233 /* AddressDetailsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB61F2874143800A02233 /* AddressDetailsStore.swift */; };
|
||||
9E7CB6212874143800A02233 /* AddressDetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E7CB61E2874143800A02233 /* AddressDetailsView.swift */; };
|
||||
|
@ -340,6 +346,8 @@
|
|||
9E5BF64E2823E94900BA3F17 /* TransactionAddressTextFieldStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionAddressTextFieldStore.swift; sourceTree = "<group>"; };
|
||||
9E661229287717A900C75B70 /* HomeCircularProgressSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeCircularProgressSnapshotTests.swift; sourceTree = "<group>"; };
|
||||
9E66122B2877188700C75B70 /* SyncStatusSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SyncStatusSnapshot.swift; sourceTree = "<group>"; };
|
||||
9E6612322878338C00C75B70 /* LottieAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LottieAnimation.swift; sourceTree = "<group>"; };
|
||||
9E6612352878345000C75B70 /* endlessCircleProgress.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = endlessCircleProgress.json; sourceTree = "<group>"; };
|
||||
9E69A24C27FB002800A55317 /* WelcomeStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeStore.swift; sourceTree = "<group>"; };
|
||||
9E7CB6112869882D00A02233 /* WalletEventsSnapshotTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletEventsSnapshotTests.swift; sourceTree = "<group>"; };
|
||||
9E7CB6142869E8C300A02233 /* CircularProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircularProgress.swift; sourceTree = "<group>"; };
|
||||
|
@ -423,7 +431,8 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
9EF8139827F1FAEC0075AF48 /* ZcashLightClientKit in Frameworks */,
|
||||
9E7CB62C2875C6E700A02233 /* URLRouting in Frameworks */,
|
||||
9E6612312878337F00C75B70 /* Lottie in Frameworks */,
|
||||
9E7CB6182872D3DF00A02233 /* URLRouting in Frameworks */,
|
||||
9E2AC0FF27D8EC120042AA47 /* MnemonicSwift in Frameworks */,
|
||||
6654C73A2715A38000901167 /* ComposableArchitecture in Frameworks */,
|
||||
9EAB466F285A0468002904A0 /* _URLRouting in Frameworks */,
|
||||
|
@ -883,6 +892,14 @@
|
|||
path = TransactionAddress;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9E6612342878341F00C75B70 /* Lotties */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9E6612352878345000C75B70 /* endlessCircleProgress.json */,
|
||||
);
|
||||
path = Lotties;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9E7CB6102869881300A02233 /* WalletEventsSnapshotTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -927,6 +944,7 @@
|
|||
9E7FE0B6282D1D9800C374E8 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9E6612342878341F00C75B70 /* Lotties */,
|
||||
0D4E7A0C26B364180058B01E /* Assets.xcassets */,
|
||||
660558E8270C7A54009D6954 /* Colors.xcassets */,
|
||||
9E37A2B727C8F59F00AE57B3 /* Localizable.strings */,
|
||||
|
@ -955,6 +973,7 @@
|
|||
9E7FE0D2282D274E00C374E8 /* Date+Readable.swift */,
|
||||
0DACFA7E27208CE00039EEA5 /* Clamped.swift */,
|
||||
F9322DBF273B555C00C105B5 /* NavigationLinks.swift */,
|
||||
9E6612322878338C00C75B70 /* LottieAnimation.swift */,
|
||||
F9C165B3274031F600592F76 /* Bindings.swift */,
|
||||
F9EEB8152742C2210032EEB8 /* WithStateBinding.swift */,
|
||||
F93673D52742CB840099C6AF /* Previews.swift */,
|
||||
|
@ -1280,7 +1299,8 @@
|
|||
9EF8139727F1FAEC0075AF48 /* ZcashLightClientKit */,
|
||||
9EAB466C285A0468002904A0 /* Parsing */,
|
||||
9EAB466E285A0468002904A0 /* _URLRouting */,
|
||||
9E7CB62B2875C6E700A02233 /* URLRouting */,
|
||||
9E7CB6172872D3DF00A02233 /* URLRouting */,
|
||||
9E6612302878337F00C75B70 /* Lottie */,
|
||||
);
|
||||
productName = secant;
|
||||
productReference = 0D4E7A0526B364170058B01E /* secant-testnet.app */;
|
||||
|
@ -1360,7 +1380,8 @@
|
|||
9E2AC0FD27D8EC120042AA47 /* XCRemoteSwiftPackageReference "MnemonicSwift" */,
|
||||
9EF8139627F1FAEC0075AF48 /* XCRemoteSwiftPackageReference "ZcashLightClientKit" */,
|
||||
9EAB466B285A0468002904A0 /* XCRemoteSwiftPackageReference "swift-parsing" */,
|
||||
9E7CB62A2875C6E700A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */,
|
||||
9E7CB6162872D3DF00A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */,
|
||||
9E66122F2878337F00C75B70 /* XCRemoteSwiftPackageReference "lottie-ios" */,
|
||||
);
|
||||
productRefGroup = 0D4E7A0626B364170058B01E /* Products */;
|
||||
projectDirPath = "";
|
||||
|
@ -1381,6 +1402,7 @@
|
|||
0DACFA9327209FA70039EEA5 /* Roboto-Medium.ttf in Resources */,
|
||||
0DACFA9827209FA70039EEA5 /* Roboto-MediumItalic.ttf in Resources */,
|
||||
0DACFA9427209FA70039EEA5 /* Roboto-BoldItalic.ttf in Resources */,
|
||||
9E6612362878345000C75B70 /* endlessCircleProgress.json in Resources */,
|
||||
0DACFA9027209FA70039EEA5 /* Roboto-Bold.ttf in Resources */,
|
||||
0DACFA9227209FA70039EEA5 /* Roboto-Italic.ttf in Resources */,
|
||||
0D535FDE271F4214009A9E3E /* Rubik-Italic-VariableFont_wght.ttf in Resources */,
|
||||
|
@ -1540,6 +1562,7 @@
|
|||
2EA11F5B27467EF800709571 /* OnboardingFooterView.swift in Sources */,
|
||||
66D50668271D9B6100E51F0D /* NavigationButtonStyle.swift in Sources */,
|
||||
2EDA07A427EDE2A900D6F09B /* DebugFrame.swift in Sources */,
|
||||
9E6612332878338C00C75B70 /* LottieAnimation.swift in Sources */,
|
||||
0D3D040A2728B3A10032ABC1 /* RecoveryPhraseDisplayStore.swift in Sources */,
|
||||
9EAB4671285A1C77002904A0 /* DeeplinkHandler.swift in Sources */,
|
||||
9E2AC10127D8EF0B0042AA47 /* WrappedMnemonic.swift in Sources */,
|
||||
|
@ -1973,7 +1996,15 @@
|
|||
minimumVersion = 2.0.0;
|
||||
};
|
||||
};
|
||||
9E7CB62A2875C6E700A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */ = {
|
||||
9E66122F2878337F00C75B70 /* XCRemoteSwiftPackageReference "lottie-ios" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "https://github.com/airbnb/lottie-ios";
|
||||
requirement = {
|
||||
kind = upToNextMajorVersion;
|
||||
minimumVersion = 3.0.0;
|
||||
};
|
||||
};
|
||||
9E7CB6162872D3DF00A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */ = {
|
||||
isa = XCRemoteSwiftPackageReference;
|
||||
repositoryURL = "http://github.com/pointfreeco/swift-url-routing";
|
||||
requirement = {
|
||||
|
@ -2010,9 +2041,14 @@
|
|||
package = 9E2AC0FD27D8EC120042AA47 /* XCRemoteSwiftPackageReference "MnemonicSwift" */;
|
||||
productName = MnemonicSwift;
|
||||
};
|
||||
9E7CB62B2875C6E700A02233 /* URLRouting */ = {
|
||||
9E6612302878337F00C75B70 /* Lottie */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9E7CB62A2875C6E700A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */;
|
||||
package = 9E66122F2878337F00C75B70 /* XCRemoteSwiftPackageReference "lottie-ios" */;
|
||||
productName = Lottie;
|
||||
};
|
||||
9E7CB6172872D3DF00A02233 /* URLRouting */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
package = 9E7CB6162872D3DF00A02233 /* XCRemoteSwiftPackageReference "swift-url-routing" */;
|
||||
productName = URLRouting;
|
||||
};
|
||||
9EAB466C285A0468002904A0 /* Parsing */ = {
|
||||
|
|
|
@ -18,6 +18,15 @@
|
|||
"version" : "1.8.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "lottie-ios",
|
||||
"kind" : "remoteSourceControl",
|
||||
"location" : "https://github.com/airbnb/lottie-ios",
|
||||
"state" : {
|
||||
"revision" : "246bab7ef72bad56abefb88e84a08871cecf9cb8",
|
||||
"version" : "3.4.0"
|
||||
}
|
||||
},
|
||||
{
|
||||
"identity" : "mnemonicswift",
|
||||
"kind" : "remoteSourceControl",
|
||||
|
|
|
@ -18,12 +18,7 @@ struct HomeView: View {
|
|||
|
||||
if proxy.size.height > 0 {
|
||||
Drawer(overlay: viewStore.bindingForDrawer(), maxHeight: proxy.size.height) {
|
||||
VStack {
|
||||
WalletEventsFlowView(store: store.historyStore())
|
||||
.padding(.top, 10)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.applyScreenBackground()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,47 +11,111 @@ struct TransactionRowView: View {
|
|||
var transaction: TransactionState
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
Circle()
|
||||
.foregroundColor(.white)
|
||||
.frame(width: 30, height: 30, alignment: .center)
|
||||
ZStack {
|
||||
icon
|
||||
|
||||
HStack {
|
||||
VStack {
|
||||
HStack {
|
||||
Text(transaction.status == .received ? "Unknown paid you" : "You sent to")
|
||||
.font(.system(size: 14))
|
||||
.fontWeight(.bold)
|
||||
Text(operationTitle)
|
||||
.font(.custom(FontFamily.Rubik.regular.name, size: 14))
|
||||
|
||||
Spacer()
|
||||
|
||||
Text(transaction.status == .received ? "+" : "")
|
||||
.font(.custom(FontFamily.Rubik.regular.name, size: 17))
|
||||
+ Text("\(transaction.zecAmount.decimalString()) ZEC")
|
||||
.font(.custom(FontFamily.Rubik.regular.name, size: 17))
|
||||
}
|
||||
.padding(.trailing, 30)
|
||||
|
||||
HStack {
|
||||
Text(transaction.address)
|
||||
.font(.system(size: 14))
|
||||
.fontWeight(.thin)
|
||||
.foregroundColor(Asset.Colors.Text.transactionRowSubtitle.color)
|
||||
.font(.custom(FontFamily.Rubik.regular.name, size: 12))
|
||||
.truncationMode(.middle)
|
||||
.lineLimit(1)
|
||||
|
||||
Spacer(minLength: 80)
|
||||
|
||||
Text("$145")
|
||||
.font(.system(size: 14))
|
||||
.fontWeight(.thin)
|
||||
// TODO: - Get the ZEC price from the SDK, issue 311, https://github.com/zcash/secant-ios-wallet/issues/311
|
||||
}
|
||||
.padding(.trailing, 15)
|
||||
}
|
||||
}
|
||||
.padding(.leading, 80)
|
||||
|
||||
VStack {
|
||||
Spacer()
|
||||
Rectangle()
|
||||
.padding(.horizontal, 30)
|
||||
.frame(height: 1, alignment: .center)
|
||||
.foregroundColor(Asset.Colors.Text.transactionRowSubtitle.color)
|
||||
}
|
||||
}
|
||||
.frame(height: 60)
|
||||
}
|
||||
}
|
||||
|
||||
struct SendTransactionRowView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
VStack {
|
||||
TransactionRowView(transaction: .placeholder)
|
||||
extension TransactionRowView {
|
||||
var operationTitle: String {
|
||||
switch transaction.status {
|
||||
case .paid(success: _):
|
||||
return "You sent to"
|
||||
case .received:
|
||||
return "Unknown paid you"
|
||||
case .failed:
|
||||
// TODO: final text to be provided, issue 392 (https://github.com/zcash/secant-ios-wallet/issues/392)
|
||||
return "Transaction failed"
|
||||
case .pending:
|
||||
return "You are sending to"
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
|
||||
var icon: some View {
|
||||
HStack {
|
||||
switch transaction.status {
|
||||
case .paid(success: _), .received:
|
||||
Image(transaction.status == .received ? Asset.Assets.Icons.received.name : Asset.Assets.Icons.sent.name)
|
||||
.resizable()
|
||||
.frame(width: 60, height: 60)
|
||||
case .failed:
|
||||
// TODO: final icon to be provided, issue 392 (https://github.com/zcash/secant-ios-wallet/issues/392)
|
||||
Circle()
|
||||
.frame(width: 30, height: 30)
|
||||
.foregroundColor(Color.red)
|
||||
.padding(15)
|
||||
case .pending:
|
||||
LottieAnimation(
|
||||
isPlaying: true,
|
||||
filename: "endlessCircleProgress",
|
||||
animationType: .circularLoop
|
||||
)
|
||||
.frame(width: 60, height: 60)
|
||||
.scaleEffect(0.45)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading, 15)
|
||||
}
|
||||
}
|
||||
|
||||
struct TransactionRowView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
TransactionRowView(
|
||||
transaction:
|
||||
.init(
|
||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||
fee: Zatoshi(amount: 10),
|
||||
id: "2",
|
||||
status: .paid(success: true),
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 123_000_000)
|
||||
)
|
||||
)
|
||||
.preferredColorScheme(.dark)
|
||||
.applyScreenBackground()
|
||||
.previewLayout(.fixed(width: 428, height: 60))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ struct WalletEventsFlowState: Equatable {
|
|||
var isScrollable = false
|
||||
var requiredTransactionConfirmations = 0
|
||||
var walletEvents = IdentifiedArrayOf<WalletEvent>.placeholder
|
||||
var selectedWalletEvent: WalletEvent?
|
||||
}
|
||||
|
||||
// MARK: - Action
|
||||
|
@ -81,8 +82,16 @@ extension WalletEventsFlowReducer {
|
|||
state.walletEvents = IdentifiedArrayOf(uniqueElements: sortedWalletEvents)
|
||||
return .none
|
||||
|
||||
case .updateRoute(.showWalletEvent(let walletEvent)):
|
||||
state.selectedWalletEvent = walletEvent
|
||||
state.route = .showWalletEvent(walletEvent)
|
||||
return .none
|
||||
|
||||
case .updateRoute(let route):
|
||||
state.route = route
|
||||
if route == nil {
|
||||
state.selectedWalletEvent = nil
|
||||
}
|
||||
return .none
|
||||
|
||||
case .copyToPastboard(let value):
|
||||
|
@ -100,11 +109,21 @@ extension WalletEventsFlowReducer {
|
|||
extension WalletEventsFlowViewStore {
|
||||
private typealias Route = WalletEventsFlowState.Route
|
||||
|
||||
func bindingForSelectingWalletEvent(_ walletEvent: WalletEvent) -> Binding<Bool> {
|
||||
func bindingForSelectedWalletEvent(_ walletEvent: WalletEvent?) -> Binding<Bool> {
|
||||
self.binding(
|
||||
get: { $0.route.map(/WalletEventsFlowState.Route.showWalletEvent) == walletEvent },
|
||||
get: {
|
||||
guard let walletEvent = walletEvent else {
|
||||
return false
|
||||
}
|
||||
|
||||
return $0.route.map(/WalletEventsFlowState.Route.showWalletEvent) == walletEvent
|
||||
},
|
||||
send: { isActive in
|
||||
WalletEventsFlowAction.updateRoute( isActive ? WalletEventsFlowState.Route.showWalletEvent(walletEvent) : nil)
|
||||
guard let walletEvent = walletEvent else {
|
||||
return WalletEventsFlowAction.updateRoute(nil)
|
||||
}
|
||||
|
||||
return WalletEventsFlowAction.updateRoute( isActive ? WalletEventsFlowState.Route.showWalletEvent(walletEvent) : nil)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -115,11 +134,23 @@ extension WalletEventsFlowViewStore {
|
|||
extension TransactionState {
|
||||
static var placeholder: Self {
|
||||
.init(
|
||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||
fee: Zatoshi(amount: 10),
|
||||
id: "2",
|
||||
status: .paid(success: true),
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25)
|
||||
zecAmount: Zatoshi(amount: 123_000_000)
|
||||
)
|
||||
}
|
||||
|
||||
static func statePlaceholder(_ status: Status) -> Self {
|
||||
.init(
|
||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||
fee: Zatoshi(amount: 10),
|
||||
id: "2",
|
||||
status: status,
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 123_000_000)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,27 +3,36 @@ import ComposableArchitecture
|
|||
|
||||
struct WalletEventsFlowView: View {
|
||||
let store: WalletEventsFlowStore
|
||||
@State var flag = true
|
||||
|
||||
var body: some View {
|
||||
UITableView.appearance().backgroundColor = .clear
|
||||
UITableViewCell.appearance().backgroundColor = .clear
|
||||
|
||||
return WithViewStore(store) { viewStore in
|
||||
Group {
|
||||
VStack {
|
||||
header(with: viewStore)
|
||||
|
||||
if viewStore.isScrollable {
|
||||
List {
|
||||
walletEventsList(with: viewStore)
|
||||
}
|
||||
.listStyle(.sidebar)
|
||||
.listStyle(.plain)
|
||||
.padding(.bottom, 60)
|
||||
} else {
|
||||
walletEventsList(with: viewStore)
|
||||
.padding(.horizontal, 32)
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.onAppear(perform: { viewStore.send(.onAppear) })
|
||||
.onAppear(
|
||||
perform: {
|
||||
UITableView.appearance().backgroundColor = .clear
|
||||
UITableView.appearance().separatorColor = .clear
|
||||
viewStore.send(.onAppear)
|
||||
}
|
||||
)
|
||||
.onDisappear(perform: { viewStore.send(.onDisappear) })
|
||||
.navigationLinkEmpty(isActive: viewStore.bindingForSelectedWalletEvent(viewStore.selectedWalletEvent)) {
|
||||
viewStore.selectedWalletEvent?.detailView(viewStore)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,43 +40,59 @@ struct WalletEventsFlowView: View {
|
|||
extension WalletEventsFlowView {
|
||||
func walletEventsList(with viewStore: WalletEventsFlowViewStore) -> some View {
|
||||
ForEach(viewStore.walletEvents) { walletEvent in
|
||||
WithStateBinding(binding: viewStore.bindingForSelectingWalletEvent(walletEvent)) { active in
|
||||
VStack {
|
||||
walletEvent.rowView(viewStore)
|
||||
.onTapGesture {
|
||||
viewStore.send(.updateRoute(.showWalletEvent(walletEvent)))
|
||||
}
|
||||
.navigationLink(
|
||||
isActive: active,
|
||||
destination: { walletEvent.detailView(viewStore) }
|
||||
)
|
||||
.listRowInsets(EdgeInsets())
|
||||
.foregroundColor(Asset.Colors.Text.body.color)
|
||||
.listRowBackground(Color.clear)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func header(with viewStore: WalletEventsFlowViewStore) -> some View {
|
||||
HStack(spacing: 0) {
|
||||
VStack {
|
||||
Button("Latest") {
|
||||
Button {
|
||||
viewStore.send(.updateRoute(.latest))
|
||||
} label: {
|
||||
Text("Latest")
|
||||
.font(.custom(FontFamily.Rubik.regular.name, size: 18))
|
||||
}
|
||||
.frame(width: 100)
|
||||
.foregroundColor(Asset.Colors.Text.drawerTabsText.color)
|
||||
.opacity(viewStore.isScrollable ? 0.23 : 1.0)
|
||||
|
||||
Rectangle()
|
||||
.frame(height: 1.5)
|
||||
.foregroundColor(Asset.Colors.TextField.Underline.purple.color)
|
||||
.foregroundColor(latestUnderline(viewStore))
|
||||
}
|
||||
|
||||
VStack {
|
||||
Button("All") {
|
||||
Button {
|
||||
viewStore.send(.updateRoute(.all))
|
||||
} label: {
|
||||
Text("All")
|
||||
.font(.custom(FontFamily.Rubik.regular.name, size: 18))
|
||||
}
|
||||
.frame(width: 100)
|
||||
.foregroundColor(Asset.Colors.Text.drawerTabsText.color)
|
||||
.opacity(viewStore.isScrollable ? 1.0 : 0.23)
|
||||
|
||||
Rectangle()
|
||||
.frame(height: 1.5)
|
||||
.foregroundColor(Asset.Colors.TextField.Underline.gray.color)
|
||||
.foregroundColor(allUnderline(viewStore))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func latestUnderline(_ viewStore: WalletEventsFlowViewStore) -> Color {
|
||||
viewStore.isScrollable ? Asset.Colors.TextField.Underline.gray.color : Asset.Colors.TextField.Underline.purple.color
|
||||
}
|
||||
|
||||
private func allUnderline(_ viewStore: WalletEventsFlowViewStore) -> Color {
|
||||
viewStore.isScrollable ? Asset.Colors.TextField.Underline.purple.color : Asset.Colors.TextField.Underline.gray.color
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Previews
|
||||
|
|
|
@ -38,8 +38,12 @@ extension WalletEvent {
|
|||
.failed(let transaction):
|
||||
TransactionRowView(transaction: transaction)
|
||||
case .shielded(let zatoshi):
|
||||
// TODO: implement design once shielding is supported, issue 390
|
||||
// https://github.com/zcash/secant-ios-wallet/issues/390
|
||||
Text("shielded wallet event \(zatoshi.decimalString())")
|
||||
case .walletImport:
|
||||
// TODO: implement design once shielding is supported, issue 391
|
||||
// https://github.com/zcash/secant-ios-wallet/issues/391
|
||||
Text("wallet import wallet event")
|
||||
}
|
||||
}
|
||||
|
@ -56,8 +60,12 @@ extension WalletEvent {
|
|||
.failed(let transaction):
|
||||
TransactionDetailView(transaction: transaction, viewStore: viewStore)
|
||||
case .shielded(let zatoshi):
|
||||
// TODO: implement design once shielding is supported, issue 390
|
||||
// https://github.com/zcash/secant-ios-wallet/issues/390
|
||||
Text("shielded \(zatoshi.decimalString()) detail")
|
||||
case .walletImport:
|
||||
// TODO: implement design once shielding is supported, issue 391
|
||||
// https://github.com/zcash/secant-ios-wallet/issues/391
|
||||
Text("wallet import wallet event")
|
||||
}
|
||||
}
|
||||
|
@ -67,11 +75,12 @@ extension WalletEvent {
|
|||
|
||||
private extension WalletEvent {
|
||||
static func randomWalletEventState() -> WalletEvent.WalletEventState {
|
||||
switch Int.random(in: 0..<5) {
|
||||
case 1: return .received(.placeholder)
|
||||
case 2: return .failed(.placeholder)
|
||||
switch Int.random(in: 0..<6) {
|
||||
case 1: return .received(.statePlaceholder(.received))
|
||||
case 2: return .failed(.statePlaceholder(.failed))
|
||||
case 3: return .shielded(Zatoshi(amount: 234_000_000))
|
||||
case 4: return .walletImport(BlockHeight(1_629_724))
|
||||
case 5: return .pending(.statePlaceholder(.pending))
|
||||
default: return .send(.placeholder)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "received.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "received@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "received@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "sent.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"filename" : "sent@2x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"filename" : "sent@3x.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.5 KiB |
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "1.000",
|
||||
"green" : "1.000",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "1.000",
|
||||
"green" : "1.000",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x84",
|
||||
"green" : "0x80",
|
||||
"red" : "0x7D"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x84",
|
||||
"green" : "0x80",
|
||||
"red" : "0x7D"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
|
@ -38,6 +38,8 @@ internal enum Asset {
|
|||
internal static let list = ImageAsset(name: "list")
|
||||
internal static let profile = ImageAsset(name: "profile")
|
||||
internal static let qrCode = ImageAsset(name: "qr-code")
|
||||
internal static let received = ImageAsset(name: "received")
|
||||
internal static let sent = ImageAsset(name: "sent")
|
||||
internal static let shield = ImageAsset(name: "shield")
|
||||
internal static let swap = ImageAsset(name: "swap")
|
||||
}
|
||||
|
@ -105,6 +107,7 @@ internal enum Asset {
|
|||
internal static let activeButtonText = ColorAsset(name: "ActiveButtonText")
|
||||
internal static let body = ColorAsset(name: "Body")
|
||||
internal static let button = ColorAsset(name: "Button")
|
||||
internal static let drawerTabsText = ColorAsset(name: "DrawerTabsText")
|
||||
internal static let heading = ColorAsset(name: "Heading")
|
||||
internal static let importSeedEditor = ColorAsset(name: "ImportSeedEditor")
|
||||
internal static let medium = ColorAsset(name: "Medium")
|
||||
|
@ -112,6 +115,7 @@ internal enum Asset {
|
|||
internal static let secondaryButtonText = ColorAsset(name: "SecondaryButtonText")
|
||||
internal static let titleText = ColorAsset(name: "TitleText")
|
||||
internal static let transactionDetailText = ColorAsset(name: "TransactionDetailText")
|
||||
internal static let transactionRowSubtitle = ColorAsset(name: "TransactionRowSubtitle")
|
||||
internal static let validMnemonic = ColorAsset(name: "ValidMnemonic")
|
||||
internal static let balanceText = ColorAsset(name: "balanceText")
|
||||
internal static let captionText = ColorAsset(name: "captionText")
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
{"v":"5.7.4","fr":60,"ip":0,"op":173,"w":512,"h":512,"nm":"Композиция 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Слой-фигура 2","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-31.206,-31.617,0],"ix":2,"l":2},"a":{"a":0,"k":[0.316,-0.493,0],"ix":1,"l":2},"s":{"a":0,"k":[94.839,94.839,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[24.137,0],[0,-24.137],[-24.137,0],[0,24.137]],"o":[[-24.137,0],[0,24.137],[24.137,0],[0,-24.137]],"v":[[0,-43.704],[-43.704,0],[0,43.704],[43.704,0]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":26,"s":[0.341176470588,0.721568627451,0.90588241278,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":52,"s":[0.341176480055,0.905882418156,0.572549045086,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":102,"s":[0.336421877146,0.900118291378,0.567380785942,1]},{"t":119,"s":[0.341176480055,0.721568644047,0.905882358551,1]}],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":27,"s":[4]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":43,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":52,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":63,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":102,"s":[4]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":118,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":129,"s":[0]},{"t":142,"s":[4]}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Обводка 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0.316,-0.493],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Эллипс 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Слой-фигура 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[256,256,0],"ix":2,"l":2},"a":{"a":0,"k":[-31,-32,0],"ix":1,"l":2},"s":{"a":1,"k":[{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[1,1,0.333],"y":[0,0,0]},"t":26,"s":[100,100,100]},{"i":{"x":[0,0,0.667],"y":[0.965,0.965,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":48,"s":[141,141,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":63,"s":[100,100,100]},{"i":{"x":[0.667,0.667,0.667],"y":[1,1,1]},"o":{"x":[1,1,0.333],"y":[-0.061,-0.061,0]},"t":102,"s":[100,100,100]},{"i":{"x":[0,0,0.667],"y":[1.084,1.084,1]},"o":{"x":[0.333,0.333,0.333],"y":[0,0,0]},"t":123,"s":[150,150,100]},{"t":141,"s":[100,100,100]}],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[19.128,0],[0,-19.128],[-19.128,0],[0,19.128]],"o":[[-19.128,0],[0,19.128],[19.128,0],[0,-19.128]],"v":[[0,-34.635],[-34.635,0],[0,34.635],[34.635,0]],"c":true},"ix":2},"nm":"Контур 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.89503401214,0.89503401214,0.89503401214,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":0,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Обводка 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":26,"s":[0.342066297344,0.721552889955,0.90709623449,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":49,"s":[0.342066287994,0.907096207142,0.574288725853,1]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":101,"s":[0.336265683174,0.898185789585,0.567210018635,1]},{"t":124,"s":[0.341176480055,0.721568644047,0.905882358551,1]}],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Заливка 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[-31,-32],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Преобразовать"}],"nm":"Эллипс 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":600,"st":0,"bm":0}],"markers":[]}
|
|
@ -23,7 +23,7 @@ struct Drawer<Content: View>: View {
|
|||
private var offset: CGFloat {
|
||||
switch overlay {
|
||||
case .full: return 70.0
|
||||
case .partial: return maxHeight * 0.75
|
||||
case .partial: return maxHeight - 230.0
|
||||
case .bottom: return maxHeight
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
//
|
||||
// LottieView.swift
|
||||
// lottie-test
|
||||
//
|
||||
// Created by Francisco Gindre on 1/30/20.
|
||||
// Copyright © 2020 Francisco Gindre. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
import Lottie
|
||||
|
||||
struct LottieAnimation: UIViewRepresentable {
|
||||
enum AnimationType {
|
||||
case progress(progress: Float)
|
||||
case frameProgress(startFrame: Float, endFrame: Float, progress: Float, loop: Bool)
|
||||
case circularLoop
|
||||
case playOnce
|
||||
}
|
||||
var isPlaying = false
|
||||
var filename: String
|
||||
var animationType: AnimationType
|
||||
|
||||
class Coordinator: NSObject {
|
||||
var lastProgress: Float
|
||||
var parent: LottieAnimation
|
||||
|
||||
init(parent: LottieAnimation) {
|
||||
self.parent = parent
|
||||
|
||||
if case AnimationType.frameProgress(let startFrame, _, _, _) = self.parent.animationType {
|
||||
self.lastProgress = startFrame
|
||||
} else {
|
||||
self.lastProgress = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeUIView(context: UIViewRepresentableContext<LottieAnimation>) -> AnimationView {
|
||||
let animationView = AnimationView()
|
||||
|
||||
let animation = Lottie.Animation.named(filename)
|
||||
|
||||
animationView.backgroundBehavior = .pauseAndRestore
|
||||
animationView.animation = animation
|
||||
animationView.contentMode = .scaleAspectFit
|
||||
|
||||
return animationView
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator {
|
||||
Coordinator(parent: self)
|
||||
}
|
||||
|
||||
func updateUIView(_ uiView: AnimationView, context: UIViewRepresentableContext<LottieAnimation>) {
|
||||
guard isPlaying else {
|
||||
uiView.stop()
|
||||
return
|
||||
}
|
||||
|
||||
switch self.animationType {
|
||||
case .circularLoop:
|
||||
if !uiView.isAnimationPlaying {
|
||||
uiView.play(fromProgress: 0, toProgress: 1, loopMode: .loop, completion: nil)
|
||||
}
|
||||
case .progress(let progress):
|
||||
uiView.currentProgress = AnimationProgressTime(progress)
|
||||
if !uiView.isAnimationPlaying {
|
||||
uiView.play(fromProgress: 0, toProgress: 1, loopMode: .loop, completion: nil)
|
||||
}
|
||||
case let .frameProgress(startFrame, endFrame, progress, loop):
|
||||
let progressTimeFrame = AnimationFrameTime(startFrame + (progress * (endFrame - startFrame)))
|
||||
|
||||
uiView.play(fromFrame: nil, toFrame: progressTimeFrame, loopMode: loop ? .loop : .none, completion: nil)
|
||||
context.coordinator.lastProgress = progress
|
||||
case .playOnce:
|
||||
uiView.play()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,15 +12,14 @@ import ComposableArchitecture
|
|||
class HomeSnapshotTests: XCTestCase {
|
||||
func testHomeSnapshot() throws {
|
||||
let transactionsHelper: [TransactionStateMockHelper] = [
|
||||
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(amount: 1), status: .paid(success: false), uuid: "1"),
|
||||
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(amount: 2), uuid: "2"),
|
||||
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(amount: 3), status: .paid(success: true), uuid: "3"),
|
||||
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(amount: 4), uuid: "4"),
|
||||
TransactionStateMockHelper(date: 1651039404, amount: Zatoshi(amount: 5), uuid: "5")
|
||||
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(amount: 1), status: .paid(success: true), uuid: "1"),
|
||||
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(amount: 2), status: .pending, uuid: "2"),
|
||||
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(amount: 3), status: .received, uuid: "3"),
|
||||
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(amount: 4), status: .failed, uuid: "4")
|
||||
]
|
||||
|
||||
let walletEvents: [WalletEvent] = transactionsHelper.map {
|
||||
let transaction = TransactionState.placeholder(
|
||||
var transaction = TransactionState.placeholder(
|
||||
amount: $0.amount,
|
||||
fee: Zatoshi(amount: 10),
|
||||
shielded: $0.shielded,
|
||||
|
@ -28,6 +27,8 @@ class HomeSnapshotTests: XCTestCase {
|
|||
timestamp: $0.date,
|
||||
uuid: $0.uuid
|
||||
)
|
||||
transaction.zAddress = "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po"
|
||||
|
||||
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||
}
|
||||
|
||||
|
@ -50,73 +51,6 @@ class HomeSnapshotTests: XCTestCase {
|
|||
)
|
||||
|
||||
// landing home screen
|
||||
addAttachments(
|
||||
name: "\(#function)_initial",
|
||||
HomeView(store: store)
|
||||
)
|
||||
|
||||
// all transactions
|
||||
ViewStore(store).send(.updateDrawer(.full))
|
||||
addAttachments(
|
||||
name: "\(#function)_fullWalletEvents",
|
||||
HomeView(store: store)
|
||||
)
|
||||
}
|
||||
|
||||
func testWalletEventDetailSnapshot() throws {
|
||||
let transaction = TransactionState(
|
||||
memo:
|
||||
"""
|
||||
Testing some long memo so I can see many lines of text \
|
||||
instead of just one. This can take some time and I'm \
|
||||
bored to write all this stuff.
|
||||
""",
|
||||
minedHeight: 1_875_256,
|
||||
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
||||
fee: Zatoshi(amount: 1_000_000),
|
||||
id: "ff3927e1f83df9b1b0dc75540ddc59ee435eecebae914d2e6dfe8576fbedc9a8",
|
||||
status: .paid(success: true),
|
||||
timestamp: 1234567,
|
||||
zecAmount: Zatoshi(amount: 25_000_000)
|
||||
)
|
||||
|
||||
let walletEvent = WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||
|
||||
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
||||
let store = HomeStore(
|
||||
initialState: .init(
|
||||
drawerOverlay: .partial,
|
||||
profileState: .placeholder,
|
||||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: [walletEvent])),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
),
|
||||
reducer: .default,
|
||||
environment: .demo
|
||||
)
|
||||
|
||||
// wallet event detail
|
||||
let testEnvironment = WalletEventsFlowEnvironment(
|
||||
pasteboard: .test,
|
||||
scheduler: DispatchQueue.test.eraseToAnyScheduler(),
|
||||
SDKSynchronizer: TestWrappedSDKSynchronizer(),
|
||||
zcashSDKEnvironment: .testnet
|
||||
)
|
||||
|
||||
ViewStore(store).send(.walletEvents(.updateRoute(.showWalletEvent(walletEvent))))
|
||||
let walletEventsStore = WalletEventsFlowStore(
|
||||
initialState: .placeHolder,
|
||||
reducer: .default,
|
||||
environment: testEnvironment
|
||||
)
|
||||
|
||||
addAttachments(
|
||||
name: "\(#function)_WalletEventDetail",
|
||||
TransactionDetailView(transaction: transaction, viewStore: ViewStore(walletEventsStore))
|
||||
)
|
||||
addAttachments(HomeView(store: store))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,59 @@ import XCTest
|
|||
@testable import secant_testnet
|
||||
import ComposableArchitecture
|
||||
|
||||
// swiftlint:disable type_body_length
|
||||
class WalletEventsSnapshotTests: XCTestCase {
|
||||
func testFullWalletEventsSnapshot() throws {
|
||||
let transactionsHelper: [TransactionStateMockHelper] = [
|
||||
TransactionStateMockHelper(date: 1651039202, amount: Zatoshi(amount: 1), status: .paid(success: true), uuid: "1"),
|
||||
TransactionStateMockHelper(date: 1651039101, amount: Zatoshi(amount: 2), status: .pending, uuid: "2"),
|
||||
TransactionStateMockHelper(date: 1651039000, amount: Zatoshi(amount: 3), status: .received, uuid: "3"),
|
||||
TransactionStateMockHelper(date: 1651039505, amount: Zatoshi(amount: 4), status: .failed, uuid: "4")
|
||||
]
|
||||
|
||||
let walletEvents: [WalletEvent] = transactionsHelper.map {
|
||||
var transaction = TransactionState.placeholder(
|
||||
amount: $0.amount,
|
||||
fee: Zatoshi(amount: 10),
|
||||
shielded: $0.shielded,
|
||||
status: $0.status,
|
||||
timestamp: $0.date,
|
||||
uuid: $0.uuid
|
||||
)
|
||||
transaction.zAddress = "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po"
|
||||
|
||||
return WalletEvent(id: transaction.id, state: .send(transaction), timestamp: transaction.timestamp)
|
||||
}
|
||||
|
||||
let balance = Balance(verified: 12_345_000, total: 12_345_000)
|
||||
|
||||
let store = HomeStore(
|
||||
initialState: .init(
|
||||
drawerOverlay: .partial,
|
||||
profileState: .placeholder,
|
||||
requestState: .placeholder,
|
||||
sendState: .placeholder,
|
||||
scanState: .placeholder,
|
||||
synchronizerStatusSnapshot: .default,
|
||||
totalBalance: Zatoshi(amount: balance.total),
|
||||
walletEventsState: .init(walletEvents: IdentifiedArrayOf(uniqueElements: walletEvents)),
|
||||
verifiedBalance: Zatoshi(amount: balance.verified)
|
||||
),
|
||||
reducer: .default,
|
||||
environment: .demo
|
||||
)
|
||||
|
||||
// landing home screen
|
||||
addAttachments(
|
||||
name: "\(#function)_initial",
|
||||
HomeView(store: store)
|
||||
)
|
||||
|
||||
// all transactions
|
||||
ViewStore(store).send(.updateDrawer(.full))
|
||||
addAttachments(HomeView(store: store))
|
||||
}
|
||||
|
||||
func testWalletEventDetailSnapshot_sent() throws {
|
||||
let transaction = TransactionState(
|
||||
memo:
|
||||
|
|
Loading…
Reference in New Issue