Merge pull request #1307 from LukasKorba/1305-Upgrade-TransactionListReducer-to-the-latest-TCA
[#1305] Upgrade TransactionListReducer to the latest TCA
This commit is contained in:
commit
1375c75267
|
@ -25,7 +25,7 @@ public struct Home {
|
||||||
public var scanState: Scan.State
|
public var scanState: Scan.State
|
||||||
public var syncProgressState: SyncProgress.State
|
public var syncProgressState: SyncProgress.State
|
||||||
public var walletConfig: WalletConfig
|
public var walletConfig: WalletConfig
|
||||||
public var transactionListState: TransactionListReducer.State
|
public var transactionListState: TransactionList.State
|
||||||
public var walletBalancesState: WalletBalances.State
|
public var walletBalancesState: WalletBalances.State
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
|
@ -33,7 +33,7 @@ public struct Home {
|
||||||
migratingDatabase: Bool = true,
|
migratingDatabase: Bool = true,
|
||||||
scanState: Scan.State,
|
scanState: Scan.State,
|
||||||
syncProgressState: SyncProgress.State,
|
syncProgressState: SyncProgress.State,
|
||||||
transactionListState: TransactionListReducer.State,
|
transactionListState: TransactionList.State,
|
||||||
walletBalancesState: WalletBalances.State,
|
walletBalancesState: WalletBalances.State,
|
||||||
walletConfig: WalletConfig
|
walletConfig: WalletConfig
|
||||||
) {
|
) {
|
||||||
|
@ -60,7 +60,7 @@ public struct Home {
|
||||||
case syncFailed(ZcashError)
|
case syncFailed(ZcashError)
|
||||||
case syncProgress(SyncProgress.Action)
|
case syncProgress(SyncProgress.Action)
|
||||||
case updateTransactionList([TransactionState])
|
case updateTransactionList([TransactionState])
|
||||||
case transactionList(TransactionListReducer.Action)
|
case transactionList(TransactionList.Action)
|
||||||
case walletBalances(WalletBalances.Action)
|
case walletBalances(WalletBalances.Action)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ public struct Home {
|
||||||
|
|
||||||
public var body: some Reducer<State, Action> {
|
public var body: some Reducer<State, Action> {
|
||||||
Scope(state: \.transactionListState, action: /Action.transactionList) {
|
Scope(state: \.transactionListState, action: /Action.transactionList) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope(state: \.syncProgressState, action: /Action.syncProgress) {
|
Scope(state: \.syncProgressState, action: /Action.syncProgress) {
|
||||||
|
|
|
@ -13,13 +13,13 @@ public struct SandboxReducer: Reducer {
|
||||||
case recoveryPhraseDisplay
|
case recoveryPhraseDisplay
|
||||||
case scan
|
case scan
|
||||||
}
|
}
|
||||||
public var transactionListState: TransactionListReducer.State
|
public var transactionListState: TransactionList.State
|
||||||
public var destination: Destination?
|
public var destination: Destination?
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum Action: Equatable {
|
public enum Action: Equatable {
|
||||||
case updateDestination(SandboxReducer.State.Destination?)
|
case updateDestination(SandboxReducer.State.Destination?)
|
||||||
case transactionList(TransactionListReducer.Action)
|
case transactionList(TransactionList.Action)
|
||||||
case reset
|
case reset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ public struct SandboxReducer: Reducer {
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
case let .transactionList(transactionListAction):
|
case let .transactionList(transactionListAction):
|
||||||
return TransactionListReducer()
|
return TransactionList()
|
||||||
.reduce(into: &state.transactionListState, action: transactionListAction)
|
.reduce(into: &state.transactionListState, action: transactionListAction)
|
||||||
.map(SandboxReducer.Action.transactionList)
|
.map(SandboxReducer.Action.transactionList)
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public struct SandboxReducer: Reducer {
|
||||||
// MARK: - Store
|
// MARK: - Store
|
||||||
|
|
||||||
extension SandboxStore {
|
extension SandboxStore {
|
||||||
func historyStore() -> TransactionListStore {
|
func historyStore() -> StoreOf<TransactionList> {
|
||||||
self.scope(
|
self.scope(
|
||||||
state: \.transactionListState,
|
state: \.transactionListState,
|
||||||
action: SandboxReducer.Action.transactionList
|
action: SandboxReducer.Action.transactionList
|
||||||
|
|
|
@ -9,19 +9,18 @@ import SDKSynchronizer
|
||||||
import ReadTransactionsStorage
|
import ReadTransactionsStorage
|
||||||
import ZcashSDKEnvironment
|
import ZcashSDKEnvironment
|
||||||
|
|
||||||
public typealias TransactionListStore = Store<TransactionListReducer.State, TransactionListReducer.Action>
|
@Reducer
|
||||||
public typealias TransactionListViewStore = ViewStore<TransactionListReducer.State, TransactionListReducer.Action>
|
public struct TransactionList {
|
||||||
|
|
||||||
public struct TransactionListReducer: Reducer {
|
|
||||||
private let CancelStateId = UUID()
|
private let CancelStateId = UUID()
|
||||||
private let CancelEventId = UUID()
|
private let CancelEventId = UUID()
|
||||||
|
|
||||||
|
@ObservableState
|
||||||
public struct State: Equatable {
|
public struct State: Equatable {
|
||||||
public var latestMinedHeight: BlockHeight?
|
public var latestMinedHeight: BlockHeight?
|
||||||
public var requiredTransactionConfirmations = 0
|
public var requiredTransactionConfirmations = 0
|
||||||
public var latestTransactionList: [TransactionState] = []
|
public var latestTransactionList: [TransactionState] = []
|
||||||
public var transactionList: IdentifiedArrayOf<TransactionState>
|
public var transactionList: IdentifiedArrayOf<TransactionState>
|
||||||
public var latestTranassctionId = ""
|
public var latestTransactionId = ""
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
latestMinedHeight: BlockHeight? = nil,
|
latestMinedHeight: BlockHeight? = nil,
|
||||||
|
@ -68,7 +67,7 @@ public struct TransactionListReducer: Reducer {
|
||||||
.publisher {
|
.publisher {
|
||||||
sdkSynchronizer.stateStream()
|
sdkSynchronizer.stateStream()
|
||||||
.throttle(for: .seconds(0.2), scheduler: mainQueue, latest: true)
|
.throttle(for: .seconds(0.2), scheduler: mainQueue, latest: true)
|
||||||
.map { TransactionListReducer.Action.synchronizerStateChanged($0.syncStatus) }
|
.map { TransactionList.Action.synchronizerStateChanged($0.syncStatus) }
|
||||||
}
|
}
|
||||||
.cancellable(id: CancelStateId, cancelInFlight: true),
|
.cancellable(id: CancelStateId, cancelInFlight: true),
|
||||||
.publisher {
|
.publisher {
|
||||||
|
@ -76,7 +75,7 @@ public struct TransactionListReducer: Reducer {
|
||||||
.throttle(for: .seconds(0.2), scheduler: mainQueue, latest: true)
|
.throttle(for: .seconds(0.2), scheduler: mainQueue, latest: true)
|
||||||
.compactMap {
|
.compactMap {
|
||||||
if case SynchronizerEvent.foundTransactions = $0 {
|
if case SynchronizerEvent.foundTransactions = $0 {
|
||||||
return TransactionListReducer.Action.foundTransactions
|
return TransactionList.Action.foundTransactions
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -156,7 +155,7 @@ public struct TransactionListReducer: Reducer {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.transactionList = IdentifiedArrayOf(uniqueElements: sortedTransactionList)
|
state.transactionList = IdentifiedArrayOf(uniqueElements: sortedTransactionList)
|
||||||
state.latestTranassctionId = state.transactionList.first?.id ?? ""
|
state.latestTransactionId = state.transactionList.first?.id ?? ""
|
||||||
|
|
||||||
return .none
|
return .none
|
||||||
|
|
||||||
|
@ -247,59 +246,3 @@ public struct TransactionListReducer: Reducer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: ViewStore
|
|
||||||
|
|
||||||
extension TransactionListViewStore {
|
|
||||||
func isLatestTransaction(id: String) -> Bool {
|
|
||||||
state.latestTranassctionId == id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: Placeholders
|
|
||||||
|
|
||||||
extension TransactionListReducer.State {
|
|
||||||
public static var placeholder: Self {
|
|
||||||
.init(transactionList: .mocked)
|
|
||||||
}
|
|
||||||
|
|
||||||
public static var initial: Self {
|
|
||||||
.init(transactionList: [])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension TransactionListStore {
|
|
||||||
public static var placeholder: Store<TransactionListReducer.State, TransactionListReducer.Action> {
|
|
||||||
Store(
|
|
||||||
initialState: .placeholder
|
|
||||||
) {
|
|
||||||
TransactionListReducer()
|
|
||||||
.dependency(\.zcashSDKEnvironment, .testnet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension IdentifiedArrayOf where Element == TransactionState {
|
|
||||||
public static var placeholder: IdentifiedArrayOf<TransactionState> {
|
|
||||||
.init(
|
|
||||||
uniqueElements: (0..<30).map {
|
|
||||||
TransactionState(
|
|
||||||
fee: Zatoshi(10),
|
|
||||||
id: String($0),
|
|
||||||
status: .paid,
|
|
||||||
timestamp: 1234567,
|
|
||||||
zecAmount: Zatoshi(25)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
public static var mocked: IdentifiedArrayOf<TransactionState> {
|
|
||||||
.init(
|
|
||||||
uniqueElements: [
|
|
||||||
TransactionState.mockedSent,
|
|
||||||
TransactionState.mockedReceived
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -2,20 +2,22 @@ import SwiftUI
|
||||||
import ComposableArchitecture
|
import ComposableArchitecture
|
||||||
import Generated
|
import Generated
|
||||||
import UIComponents
|
import UIComponents
|
||||||
|
import Models
|
||||||
|
import ZcashLightClientKit
|
||||||
|
|
||||||
public struct TransactionListView: View {
|
public struct TransactionListView: View {
|
||||||
let store: TransactionListStore
|
let store: StoreOf<TransactionList>
|
||||||
let tokenName: String
|
let tokenName: String
|
||||||
|
|
||||||
public init(store: TransactionListStore, tokenName: String) {
|
public init(store: StoreOf<TransactionList>, tokenName: String) {
|
||||||
self.store = store
|
self.store = store
|
||||||
self.tokenName = tokenName
|
self.tokenName = tokenName
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
WithViewStore(store, observe: { $0 }) { viewStore in
|
WithPerceptionTracking {
|
||||||
List {
|
List {
|
||||||
if viewStore.transactionList.isEmpty {
|
if store.transactionList.isEmpty {
|
||||||
Text(L10n.TransactionList.noTransactions)
|
Text(L10n.TransactionList.noTransactions)
|
||||||
.font(.custom(FontFamily.Inter.bold.name, size: 13))
|
.font(.custom(FontFamily.Inter.bold.name, size: 13))
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
|
@ -24,24 +26,26 @@ public struct TransactionListView: View {
|
||||||
.listRowSeparator(.hidden)
|
.listRowSeparator(.hidden)
|
||||||
.padding(.top, 30)
|
.padding(.top, 30)
|
||||||
} else {
|
} else {
|
||||||
ForEach(viewStore.transactionList) { transaction in
|
ForEach(store.transactionList) { transaction in
|
||||||
TransactionRowView(
|
WithPerceptionTracking {
|
||||||
viewStore: viewStore,
|
TransactionRowView(
|
||||||
transaction: transaction,
|
store: store,
|
||||||
tokenName: tokenName,
|
transaction: transaction,
|
||||||
isLatestTransaction: viewStore.isLatestTransaction(id: transaction.id)
|
tokenName: tokenName,
|
||||||
)
|
isLatestTransaction: store.latestTransactionId == transaction.id
|
||||||
.listRowInsets(EdgeInsets())
|
)
|
||||||
|
.listRowInsets(EdgeInsets())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.listRowBackground(Asset.Colors.shade97.color)
|
.listRowBackground(Asset.Colors.shade97.color)
|
||||||
.listRowSeparator(.hidden)
|
.listRowSeparator(.hidden)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.disabled(viewStore.transactionList.isEmpty)
|
.disabled(store.transactionList.isEmpty)
|
||||||
.background(Asset.Colors.shade97.color)
|
.background(Asset.Colors.shade97.color)
|
||||||
.listStyle(.plain)
|
.listStyle(.plain)
|
||||||
.onAppear { viewStore.send(.onAppear) }
|
.onAppear { store.send(.onAppear) }
|
||||||
.onDisappear(perform: { viewStore.send(.onDisappear) })
|
.onDisappear(perform: { store.send(.onDisappear) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,3 +58,51 @@ public struct TransactionListView: View {
|
||||||
.preferredColorScheme(.light)
|
.preferredColorScheme(.light)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: Placeholders
|
||||||
|
|
||||||
|
extension TransactionList.State {
|
||||||
|
public static var placeholder: Self {
|
||||||
|
.init(transactionList: .mocked)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var initial: Self {
|
||||||
|
.init(transactionList: [])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension StoreOf<TransactionList> {
|
||||||
|
public static var placeholder: Store<TransactionList.State, TransactionList.Action> {
|
||||||
|
Store(
|
||||||
|
initialState: .placeholder
|
||||||
|
) {
|
||||||
|
TransactionList()
|
||||||
|
.dependency(\.zcashSDKEnvironment, .testnet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension IdentifiedArrayOf where Element == TransactionState {
|
||||||
|
public static var placeholder: IdentifiedArrayOf<TransactionState> {
|
||||||
|
.init(
|
||||||
|
uniqueElements: (0..<30).map {
|
||||||
|
TransactionState(
|
||||||
|
fee: Zatoshi(10),
|
||||||
|
id: String($0),
|
||||||
|
status: .paid,
|
||||||
|
timestamp: 1234567,
|
||||||
|
zecAmount: Zatoshi(25)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var mocked: IdentifiedArrayOf<TransactionState> {
|
||||||
|
.init(
|
||||||
|
uniqueElements: [
|
||||||
|
TransactionState.mockedSent,
|
||||||
|
TransactionState.mockedReceived
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,70 +11,72 @@ import ComposableArchitecture
|
||||||
import Generated
|
import Generated
|
||||||
|
|
||||||
struct MessageView: View {
|
struct MessageView: View {
|
||||||
let viewStore: TransactionListViewStore
|
let store: StoreOf<TransactionList>
|
||||||
|
|
||||||
let messages: [String]?
|
let messages: [String]?
|
||||||
let isSpending: Bool
|
let isSpending: Bool
|
||||||
let isFailed: Bool
|
let isFailed: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
viewStore: TransactionListViewStore,
|
store: StoreOf<TransactionList>,
|
||||||
messages: [String]?,
|
messages: [String]?,
|
||||||
isSpending: Bool,
|
isSpending: Bool,
|
||||||
isFailed: Bool = false
|
isFailed: Bool = false
|
||||||
) {
|
) {
|
||||||
self.viewStore = viewStore
|
self.store = store
|
||||||
self.messages = messages
|
self.messages = messages
|
||||||
self.isSpending = isSpending
|
self.isSpending = isSpending
|
||||||
self.isFailed = isFailed
|
self.isFailed = isFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if let memoTexts = messages {
|
WithPerceptionTracking {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
if let memoTexts = messages {
|
||||||
Text(memoTexts.count == 1
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
? L10n.TransactionList.messageTitle
|
Text(memoTexts.count == 1
|
||||||
: L10n.TransactionList.messageTitlePlural
|
? L10n.TransactionList.messageTitle
|
||||||
)
|
: L10n.TransactionList.messageTitlePlural
|
||||||
.font(.custom(FontFamily.Inter.medium.name, size: 13))
|
|
||||||
.padding(.bottom, 8)
|
|
||||||
|
|
||||||
ForEach(0..<memoTexts.count, id: \.self) { index in
|
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
|
||||||
Color.clear.frame(height: 0)
|
|
||||||
|
|
||||||
Text(memoTexts[index])
|
|
||||||
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
|
||||||
.foregroundColor(
|
|
||||||
isFailed ?
|
|
||||||
Asset.Colors.error.color
|
|
||||||
: Asset.Colors.primary.color
|
|
||||||
)
|
|
||||||
.conditionalStrikethrough(isFailed)
|
|
||||||
.padding()
|
|
||||||
}
|
|
||||||
.messageShape(
|
|
||||||
filled: !isSpending
|
|
||||||
? Asset.Colors.messageBcgReceived.color
|
|
||||||
: nil,
|
|
||||||
border: isSpending
|
|
||||||
? Asset.Colors.primary.color
|
|
||||||
: nil,
|
|
||||||
orientation: !isSpending
|
|
||||||
? .right
|
|
||||||
: .left
|
|
||||||
)
|
)
|
||||||
|
.font(.custom(FontFamily.Inter.medium.name, size: 13))
|
||||||
|
.padding(.bottom, 8)
|
||||||
|
|
||||||
TapToCopyTransactionDataView(viewStore: viewStore, data: memoTexts[index].redacted)
|
ForEach(0..<memoTexts.count, id: \.self) { index in
|
||||||
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
|
Color.clear.frame(height: 0)
|
||||||
|
|
||||||
|
Text(memoTexts[index])
|
||||||
|
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
||||||
|
.foregroundColor(
|
||||||
|
isFailed ?
|
||||||
|
Asset.Colors.error.color
|
||||||
|
: Asset.Colors.primary.color
|
||||||
|
)
|
||||||
|
.conditionalStrikethrough(isFailed)
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.messageShape(
|
||||||
|
filled: !isSpending
|
||||||
|
? Asset.Colors.messageBcgReceived.color
|
||||||
|
: nil,
|
||||||
|
border: isSpending
|
||||||
|
? Asset.Colors.primary.color
|
||||||
|
: nil,
|
||||||
|
orientation: !isSpending
|
||||||
|
? .right
|
||||||
|
: .left
|
||||||
|
)
|
||||||
|
|
||||||
|
TapToCopyTransactionDataView(store: store, data: memoTexts[index].redacted)
|
||||||
|
}
|
||||||
|
.padding(.bottom, 20)
|
||||||
}
|
}
|
||||||
.padding(.bottom, 20)
|
.padding(.bottom, 7)
|
||||||
|
.padding(.vertical, 10)
|
||||||
|
} else {
|
||||||
|
Text(L10n.TransactionList.noMessageIncluded)
|
||||||
|
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
||||||
|
.foregroundColor(Asset.Colors.primary.color)
|
||||||
}
|
}
|
||||||
.padding(.bottom, 7)
|
|
||||||
.padding(.vertical, 10)
|
|
||||||
} else {
|
|
||||||
Text(L10n.TransactionList.noMessageIncluded)
|
|
||||||
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
|
||||||
.foregroundColor(Asset.Colors.primary.color)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -82,14 +84,14 @@ struct MessageView: View {
|
||||||
#Preview {
|
#Preview {
|
||||||
VStack(alignment: .leading) {
|
VStack(alignment: .leading) {
|
||||||
MessageView(
|
MessageView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
messages: ["Test"],
|
messages: ["Test"],
|
||||||
isSpending: true
|
isSpending: true
|
||||||
)
|
)
|
||||||
.padding(.bottom, 50)
|
.padding(.bottom, 50)
|
||||||
|
|
||||||
MessageView(
|
MessageView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
messages: ["Test"],
|
messages: ["Test"],
|
||||||
isSpending: true,
|
isSpending: true,
|
||||||
isFailed: true
|
isFailed: true
|
||||||
|
@ -97,13 +99,13 @@ struct MessageView: View {
|
||||||
.padding(.bottom, 50)
|
.padding(.bottom, 50)
|
||||||
|
|
||||||
MessageView(
|
MessageView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
messages: ["Test"],
|
messages: ["Test"],
|
||||||
isSpending: false
|
isSpending: false
|
||||||
)
|
)
|
||||||
|
|
||||||
MessageView(
|
MessageView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
messages: nil,
|
messages: nil,
|
||||||
isSpending: false
|
isSpending: false
|
||||||
)
|
)
|
||||||
|
|
|
@ -11,37 +11,39 @@ import Generated
|
||||||
import Utils
|
import Utils
|
||||||
|
|
||||||
struct TapToCopyTransactionDataView: View {
|
struct TapToCopyTransactionDataView: View {
|
||||||
let viewStore: TransactionListViewStore
|
let store: StoreOf<TransactionList>
|
||||||
let data: RedactableString
|
let data: RedactableString
|
||||||
|
|
||||||
public init(viewStore: TransactionListViewStore, data: RedactableString) {
|
public init(store: StoreOf<TransactionList>, data: RedactableString) {
|
||||||
self.viewStore = viewStore
|
self.store = store
|
||||||
self.data = data
|
self.data = data
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
Button {
|
WithPerceptionTracking {
|
||||||
viewStore.send(.copyToPastboard(data))
|
Button {
|
||||||
} label: {
|
store.send(.copyToPastboard(data))
|
||||||
HStack {
|
} label: {
|
||||||
Asset.Assets.copy.image
|
HStack {
|
||||||
.renderingMode(.template)
|
Asset.Assets.copy.image
|
||||||
.resizable()
|
.renderingMode(.template)
|
||||||
.frame(width: 11, height: 11)
|
.resizable()
|
||||||
.foregroundColor(Asset.Colors.primary.color)
|
.frame(width: 11, height: 11)
|
||||||
|
.foregroundColor(Asset.Colors.primary.color)
|
||||||
Text(L10n.General.tapToCopy)
|
|
||||||
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
Text(L10n.General.tapToCopy)
|
||||||
.foregroundColor(Asset.Colors.shade47.color)
|
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
||||||
|
.foregroundColor(Asset.Colors.shade47.color)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.buttonStyle(.borderless)
|
||||||
}
|
}
|
||||||
.buttonStyle(.borderless)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#Preview {
|
#Preview {
|
||||||
TapToCopyTransactionDataView(
|
TapToCopyTransactionDataView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
data: "something to copy".redacted
|
data: "something to copy".redacted
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,66 +12,68 @@ import Models
|
||||||
import UIComponents
|
import UIComponents
|
||||||
|
|
||||||
struct TransactionHeaderView: View {
|
struct TransactionHeaderView: View {
|
||||||
let viewStore: TransactionListViewStore
|
let store: StoreOf<TransactionList>
|
||||||
let transaction: TransactionState
|
let transaction: TransactionState
|
||||||
let isLatestTransaction: Bool
|
let isLatestTransaction: Bool
|
||||||
|
|
||||||
init(
|
init(
|
||||||
viewStore: TransactionListViewStore,
|
store: StoreOf<TransactionList>,
|
||||||
transaction: TransactionState,
|
transaction: TransactionState,
|
||||||
isLatestTransaction: Bool = false
|
isLatestTransaction: Bool = false
|
||||||
) {
|
) {
|
||||||
self.viewStore = viewStore
|
self.store = store
|
||||||
self.transaction = transaction
|
self.transaction = transaction
|
||||||
self.isLatestTransaction = isLatestTransaction
|
self.isLatestTransaction = isLatestTransaction
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(spacing: 0) {
|
WithPerceptionTracking {
|
||||||
Divider()
|
VStack(spacing: 0) {
|
||||||
.padding(.horizontal, 30)
|
Divider()
|
||||||
.padding(.bottom, 30)
|
.padding(.horizontal, 30)
|
||||||
.opacity(isLatestTransaction ? 0.0 : 1.0)
|
.padding(.bottom, 30)
|
||||||
|
.opacity(isLatestTransaction ? 0.0 : 1.0)
|
||||||
HStack {
|
|
||||||
VStack(alignment: .leading, spacing: 5) {
|
HStack {
|
||||||
HStack(spacing: 0) {
|
VStack(alignment: .leading, spacing: 5) {
|
||||||
iconImage()
|
HStack(spacing: 0) {
|
||||||
|
iconImage()
|
||||||
titleText()
|
|
||||||
|
titleText()
|
||||||
addressArea()
|
|
||||||
|
addressArea()
|
||||||
Spacer(minLength: 60)
|
|
||||||
|
Spacer(minLength: 60)
|
||||||
balanceView()
|
|
||||||
}
|
balanceView()
|
||||||
.padding(.trailing, 30)
|
|
||||||
|
|
||||||
if transaction.zAddress != nil && transaction.isAddressExpanded {
|
|
||||||
HStack {
|
|
||||||
Text(transaction.address)
|
|
||||||
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
|
||||||
.foregroundColor(Asset.Colors.primary.color)
|
|
||||||
|
|
||||||
Spacer(minLength: 100)
|
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 60)
|
.padding(.trailing, 30)
|
||||||
.padding(.bottom, 5)
|
|
||||||
|
|
||||||
TapToCopyTransactionDataView(viewStore: viewStore, data: transaction.address.redacted)
|
if transaction.zAddress != nil && transaction.isAddressExpanded {
|
||||||
|
HStack {
|
||||||
|
Text(transaction.address)
|
||||||
|
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
||||||
|
.foregroundColor(Asset.Colors.primary.color)
|
||||||
|
|
||||||
|
Spacer(minLength: 100)
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 60)
|
||||||
|
.padding(.bottom, 5)
|
||||||
|
|
||||||
|
TapToCopyTransactionDataView(store: store, data: transaction.address.redacted)
|
||||||
|
.padding(.horizontal, 60)
|
||||||
|
.padding(.bottom, 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text("\(transaction.dateString ?? "")")
|
||||||
|
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
||||||
|
.foregroundColor(Asset.Colors.shade47.color)
|
||||||
.padding(.horizontal, 60)
|
.padding(.horizontal, 60)
|
||||||
.padding(.bottom, 20)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text("\(transaction.dateString ?? "")")
|
|
||||||
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
|
||||||
.foregroundColor(Asset.Colors.shade47.color)
|
|
||||||
.padding(.horizontal, 60)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.padding(.bottom, 30)
|
||||||
}
|
}
|
||||||
.padding(.bottom, 30)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ViewBuilder private func iconImage() -> some View {
|
@ViewBuilder private func iconImage() -> some View {
|
||||||
|
@ -105,7 +107,7 @@ struct TransactionHeaderView: View {
|
||||||
.foregroundColor(Asset.Colors.primary.color)
|
.foregroundColor(Asset.Colors.primary.color)
|
||||||
} else if !transaction.isAddressExpanded {
|
} else if !transaction.isAddressExpanded {
|
||||||
Button {
|
Button {
|
||||||
viewStore.send(.transactionAddressExpandRequested(transaction.id))
|
store.send(.transactionAddressExpandRequested(transaction.id))
|
||||||
} label: {
|
} label: {
|
||||||
Text(transaction.address)
|
Text(transaction.address)
|
||||||
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
||||||
|
@ -165,37 +167,37 @@ extension TransactionHeaderView {
|
||||||
#Preview {
|
#Preview {
|
||||||
VStack(spacing: 0) {
|
VStack(spacing: 0) {
|
||||||
TransactionHeaderView(
|
TransactionHeaderView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: .mockedFailed
|
transaction: .mockedFailed
|
||||||
)
|
)
|
||||||
.listRowSeparator(.hidden)
|
.listRowSeparator(.hidden)
|
||||||
|
|
||||||
TransactionHeaderView(
|
TransactionHeaderView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: .mockedFailedReceive
|
transaction: .mockedFailedReceive
|
||||||
)
|
)
|
||||||
.listRowSeparator(.hidden)
|
.listRowSeparator(.hidden)
|
||||||
|
|
||||||
TransactionHeaderView(
|
TransactionHeaderView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: .mockedSent
|
transaction: .mockedSent
|
||||||
)
|
)
|
||||||
.listRowSeparator(.hidden)
|
.listRowSeparator(.hidden)
|
||||||
|
|
||||||
TransactionHeaderView(
|
TransactionHeaderView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: .mockedReceived
|
transaction: .mockedReceived
|
||||||
)
|
)
|
||||||
.listRowSeparator(.hidden)
|
.listRowSeparator(.hidden)
|
||||||
|
|
||||||
TransactionHeaderView(
|
TransactionHeaderView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: .mockedSending
|
transaction: .mockedSending
|
||||||
)
|
)
|
||||||
.listRowSeparator(.hidden)
|
.listRowSeparator(.hidden)
|
||||||
|
|
||||||
TransactionHeaderView(
|
TransactionHeaderView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: .mockedReceiving
|
transaction: .mockedReceiving
|
||||||
)
|
)
|
||||||
.listRowSeparator(.hidden)
|
.listRowSeparator(.hidden)
|
||||||
|
|
|
@ -11,53 +11,55 @@ import Generated
|
||||||
import Models
|
import Models
|
||||||
|
|
||||||
struct TransactionIdView: View {
|
struct TransactionIdView: View {
|
||||||
let viewStore: TransactionListViewStore
|
let store: StoreOf<TransactionList>
|
||||||
let transaction: TransactionState
|
let transaction: TransactionState
|
||||||
|
|
||||||
public init(viewStore: TransactionListViewStore, transaction: TransactionState) {
|
public init(store: StoreOf<TransactionList>, transaction: TransactionState) {
|
||||||
self.viewStore = viewStore
|
self.store = store
|
||||||
self.transaction = transaction
|
self.transaction = transaction
|
||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
WithPerceptionTracking {
|
||||||
if !transaction.isIdExpanded {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
HStack {
|
if !transaction.isIdExpanded {
|
||||||
Text(L10n.TransactionList.transactionId)
|
HStack {
|
||||||
|
Text(L10n.TransactionList.transactionId)
|
||||||
Button {
|
|
||||||
viewStore.send(.transactionIdExpandRequested(transaction.id))
|
Button {
|
||||||
} label: {
|
store.send(.transactionIdExpandRequested(transaction.id))
|
||||||
Text(transaction.id)
|
} label: {
|
||||||
.lineLimit(1)
|
Text(transaction.id)
|
||||||
.truncationMode(.middle)
|
.lineLimit(1)
|
||||||
|
.truncationMode(.middle)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(minLength: 50)
|
||||||
}
|
}
|
||||||
|
.padding(.vertical, 20)
|
||||||
|
}
|
||||||
|
|
||||||
|
if transaction.isIdExpanded {
|
||||||
|
Text(L10n.TransactionList.transactionId)
|
||||||
|
.padding(.top, 20)
|
||||||
|
.padding(.bottom, 4)
|
||||||
|
|
||||||
Spacer(minLength: 50)
|
HStack {
|
||||||
|
Text(transaction.id)
|
||||||
|
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
||||||
|
.foregroundColor(Asset.Colors.primary.color)
|
||||||
|
|
||||||
|
Spacer(minLength: 100)
|
||||||
|
}
|
||||||
|
.padding(.bottom, 10)
|
||||||
|
|
||||||
|
TapToCopyTransactionDataView(store: store, data: transaction.id.redacted)
|
||||||
|
.padding(.bottom, 20)
|
||||||
}
|
}
|
||||||
.padding(.vertical, 20)
|
|
||||||
}
|
|
||||||
|
|
||||||
if transaction.isIdExpanded {
|
|
||||||
Text(L10n.TransactionList.transactionId)
|
|
||||||
.padding(.top, 20)
|
|
||||||
.padding(.bottom, 4)
|
|
||||||
|
|
||||||
HStack {
|
|
||||||
Text(transaction.id)
|
|
||||||
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
|
||||||
.foregroundColor(Asset.Colors.primary.color)
|
|
||||||
|
|
||||||
Spacer(minLength: 100)
|
|
||||||
}
|
|
||||||
.padding(.bottom, 10)
|
|
||||||
|
|
||||||
TapToCopyTransactionDataView(viewStore: viewStore, data: transaction.id.redacted)
|
|
||||||
.padding(.bottom, 20)
|
|
||||||
}
|
}
|
||||||
|
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
||||||
|
.foregroundColor(Asset.Colors.shade47.color)
|
||||||
}
|
}
|
||||||
.font(.custom(FontFamily.Inter.regular.name, size: 13))
|
|
||||||
.foregroundColor(Asset.Colors.shade47.color)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ struct TransactionIdView: View {
|
||||||
transaction.isIdExpanded = true
|
transaction.isIdExpanded = true
|
||||||
|
|
||||||
return TransactionIdView(
|
return TransactionIdView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: transaction
|
transaction: transaction
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,71 +13,73 @@ import Generated
|
||||||
import UIComponents
|
import UIComponents
|
||||||
|
|
||||||
public struct TransactionRowView: View {
|
public struct TransactionRowView: View {
|
||||||
let viewStore: TransactionListViewStore
|
let store: StoreOf<TransactionList>
|
||||||
let transaction: TransactionState
|
let transaction: TransactionState
|
||||||
let tokenName: String
|
let tokenName: String
|
||||||
let isLatestTransaction: Bool
|
let isLatestTransaction: Bool
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
viewStore: TransactionListViewStore,
|
store: StoreOf<TransactionList>,
|
||||||
transaction: TransactionState,
|
transaction: TransactionState,
|
||||||
tokenName: String,
|
tokenName: String,
|
||||||
isLatestTransaction: Bool = false
|
isLatestTransaction: Bool = false
|
||||||
) {
|
) {
|
||||||
self.viewStore = viewStore
|
self.store = store
|
||||||
self.transaction = transaction
|
self.transaction = transaction
|
||||||
self.tokenName = tokenName
|
self.tokenName = tokenName
|
||||||
self.isLatestTransaction = isLatestTransaction
|
self.isLatestTransaction = isLatestTransaction
|
||||||
}
|
}
|
||||||
|
|
||||||
public var body: some View {
|
public var body: some View {
|
||||||
Button {
|
WithPerceptionTracking {
|
||||||
viewStore.send(.transactionExpandRequested(transaction.id), animation: .default)
|
Button {
|
||||||
} label: {
|
store.send(.transactionExpandRequested(transaction.id), animation: .default)
|
||||||
if transaction.isExpanded {
|
} label: {
|
||||||
TransactionHeaderView(
|
if transaction.isExpanded {
|
||||||
viewStore: viewStore,
|
TransactionHeaderView(
|
||||||
transaction: transaction,
|
store: store,
|
||||||
isLatestTransaction: isLatestTransaction
|
transaction: transaction,
|
||||||
)
|
isLatestTransaction: isLatestTransaction
|
||||||
} else {
|
)
|
||||||
TransactionHeaderView(
|
} else {
|
||||||
viewStore: viewStore,
|
TransactionHeaderView(
|
||||||
transaction: transaction,
|
store: store,
|
||||||
isLatestTransaction: isLatestTransaction
|
transaction: transaction,
|
||||||
)
|
isLatestTransaction: isLatestTransaction
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if transaction.isExpanded {
|
|
||||||
Group {
|
|
||||||
if !transaction.isTransparentRecipient {
|
|
||||||
MessageView(
|
|
||||||
viewStore: viewStore,
|
|
||||||
messages: transaction.textMemos,
|
|
||||||
isSpending: transaction.isSpending,
|
|
||||||
isFailed: transaction.status == .failed
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
TransactionIdView(
|
|
||||||
viewStore: viewStore,
|
|
||||||
transaction: transaction
|
|
||||||
)
|
|
||||||
|
|
||||||
if transaction.isSpending {
|
|
||||||
TransactionFeeView(fee: transaction.fee ?? .zero)
|
|
||||||
.padding(.vertical, 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
Button {
|
|
||||||
viewStore.send(.transactionCollapseRequested(transaction.id), animation: .default)
|
|
||||||
} label: {
|
|
||||||
CollapseTransactionView()
|
|
||||||
.padding(.vertical, 20)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 60)
|
|
||||||
|
if transaction.isExpanded {
|
||||||
|
Group {
|
||||||
|
if !transaction.isTransparentRecipient {
|
||||||
|
MessageView(
|
||||||
|
store: store,
|
||||||
|
messages: transaction.textMemos,
|
||||||
|
isSpending: transaction.isSpending,
|
||||||
|
isFailed: transaction.status == .failed
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionIdView(
|
||||||
|
store: store,
|
||||||
|
transaction: transaction
|
||||||
|
)
|
||||||
|
|
||||||
|
if transaction.isSpending {
|
||||||
|
TransactionFeeView(fee: transaction.fee ?? .zero)
|
||||||
|
.padding(.vertical, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
store.send(.transactionCollapseRequested(transaction.id), animation: .default)
|
||||||
|
} label: {
|
||||||
|
CollapseTransactionView()
|
||||||
|
.padding(.vertical, 20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal, 60)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +87,7 @@ public struct TransactionRowView: View {
|
||||||
#Preview {
|
#Preview {
|
||||||
List {
|
List {
|
||||||
TransactionRowView(
|
TransactionRowView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: .mockedFailed,
|
transaction: .mockedFailed,
|
||||||
tokenName: "ZEC"
|
tokenName: "ZEC"
|
||||||
)
|
)
|
||||||
|
@ -93,7 +95,7 @@ public struct TransactionRowView: View {
|
||||||
.listRowInsets(EdgeInsets())
|
.listRowInsets(EdgeInsets())
|
||||||
|
|
||||||
TransactionRowView(
|
TransactionRowView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: .mockedReceived,
|
transaction: .mockedReceived,
|
||||||
tokenName: "ZEC"
|
tokenName: "ZEC"
|
||||||
)
|
)
|
||||||
|
@ -101,7 +103,7 @@ public struct TransactionRowView: View {
|
||||||
.listRowInsets(EdgeInsets())
|
.listRowInsets(EdgeInsets())
|
||||||
|
|
||||||
TransactionRowView(
|
TransactionRowView(
|
||||||
viewStore: ViewStore(.placeholder, observe: { $0 }),
|
store: .placeholder,
|
||||||
transaction: .mockedSent,
|
transaction: .mockedSent,
|
||||||
tokenName: "ZEC"
|
tokenName: "ZEC"
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,10 +15,10 @@ import Home
|
||||||
|
|
||||||
class TransactionListSnapshotTests: XCTestCase {
|
class TransactionListSnapshotTests: XCTestCase {
|
||||||
func testFullTransactionListSnapshot() throws {
|
func testFullTransactionListSnapshot() throws {
|
||||||
let store = TransactionListStore(
|
let store = StoreOf<TransactionList>(
|
||||||
initialState: .placeholder
|
initialState: .placeholder
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
.dependency(\.sdkSynchronizer, .mock)
|
.dependency(\.sdkSynchronizer, .mock)
|
||||||
.dependency(\.mainQueue, .immediate)
|
.dependency(\.mainQueue, .immediate)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,11 +17,11 @@ import TransactionList
|
||||||
class TransactionListTests: XCTestCase {
|
class TransactionListTests: XCTestCase {
|
||||||
func testSynchronizerSubscription() async throws {
|
func testSynchronizerSubscription() async throws {
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: []
|
transactionList: []
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.sdkSynchronizer = .mocked()
|
store.dependencies.sdkSynchronizer = .mocked()
|
||||||
|
@ -76,11 +76,11 @@ class TransactionListTests: XCTestCase {
|
||||||
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: identifiedTransactionList
|
transactionList: identifiedTransactionList
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.mainQueue = .immediate
|
store.dependencies.mainQueue = .immediate
|
||||||
|
@ -104,7 +104,7 @@ class TransactionListTests: XCTestCase {
|
||||||
|
|
||||||
state.transactionList = receivedTransactionList
|
state.transactionList = receivedTransactionList
|
||||||
state.latestTransactionList = transactionList
|
state.latestTransactionList = transactionList
|
||||||
state.latestTranassctionId = "aa11"
|
state.latestTransactionId = "aa11"
|
||||||
}
|
}
|
||||||
|
|
||||||
await store.finish()
|
await store.finish()
|
||||||
|
@ -143,12 +143,12 @@ class TransactionListTests: XCTestCase {
|
||||||
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
latestTransactionList: transactionList,
|
latestTransactionList: transactionList,
|
||||||
transactionList: identifiedTransactionList
|
transactionList: identifiedTransactionList
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.mainQueue = .immediate
|
store.dependencies.mainQueue = .immediate
|
||||||
|
@ -168,11 +168,11 @@ class TransactionListTests: XCTestCase {
|
||||||
let testPasteboard = PasteboardClient.testPasteboard
|
let testPasteboard = PasteboardClient.testPasteboard
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: []
|
transactionList: []
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.pasteboard = testPasteboard
|
store.dependencies.pasteboard = testPasteboard
|
||||||
|
@ -210,11 +210,11 @@ class TransactionListTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: [transaction]
|
transactionList: [transaction]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.readTransactionsStorage = .noOp
|
store.dependencies.readTransactionsStorage = .noOp
|
||||||
|
@ -243,11 +243,11 @@ class TransactionListTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: [transaction]
|
transactionList: [transaction]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.readTransactionsStorage = .noOp
|
store.dependencies.readTransactionsStorage = .noOp
|
||||||
|
@ -277,11 +277,11 @@ class TransactionListTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: [transaction]
|
transactionList: [transaction]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.readTransactionsStorage = .noOp
|
store.dependencies.readTransactionsStorage = .noOp
|
||||||
|
@ -312,11 +312,11 @@ class TransactionListTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: [transaction]
|
transactionList: [transaction]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.readTransactionsStorage = .noOp
|
store.dependencies.readTransactionsStorage = .noOp
|
||||||
|
@ -346,11 +346,11 @@ class TransactionListTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: [transaction]
|
transactionList: [transaction]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.readTransactionsStorage = .noOp
|
store.dependencies.readTransactionsStorage = .noOp
|
||||||
|
@ -380,11 +380,11 @@ class TransactionListTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: [transaction]
|
transactionList: [transaction]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.readTransactionsStorage = .noOp
|
store.dependencies.readTransactionsStorage = .noOp
|
||||||
|
@ -414,11 +414,11 @@ class TransactionListTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: [transaction]
|
transactionList: [transaction]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.readTransactionsStorage = .noOp
|
store.dependencies.readTransactionsStorage = .noOp
|
||||||
|
@ -448,11 +448,11 @@ class TransactionListTests: XCTestCase {
|
||||||
)
|
)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: [transaction]
|
transactionList: [transaction]
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.readTransactionsStorage = .noOp
|
store.dependencies.readTransactionsStorage = .noOp
|
||||||
|
@ -488,11 +488,11 @@ class TransactionListTests: XCTestCase {
|
||||||
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: identifiedTransactionList
|
transactionList: identifiedTransactionList
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.mainQueue = .immediate
|
store.dependencies.mainQueue = .immediate
|
||||||
|
@ -509,7 +509,7 @@ class TransactionListTests: XCTestCase {
|
||||||
await store.receive(.updateTransactionList(transactionList)) { state in
|
await store.receive(.updateTransactionList(transactionList)) { state in
|
||||||
state.transactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
state.transactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
||||||
state.latestTransactionList = transactionList
|
state.latestTransactionList = transactionList
|
||||||
state.latestTranassctionId = id
|
state.latestTransactionId = id
|
||||||
|
|
||||||
XCTAssertTrue(state.transactionList[0].isUnread)
|
XCTAssertTrue(state.transactionList[0].isUnread)
|
||||||
}
|
}
|
||||||
|
@ -541,11 +541,11 @@ class TransactionListTests: XCTestCase {
|
||||||
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: identifiedTransactionList
|
transactionList: identifiedTransactionList
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.mainQueue = .immediate
|
store.dependencies.mainQueue = .immediate
|
||||||
|
@ -563,7 +563,7 @@ class TransactionListTests: XCTestCase {
|
||||||
await store.receive(.updateTransactionList(transactionList)) { state in
|
await store.receive(.updateTransactionList(transactionList)) { state in
|
||||||
state.transactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
state.transactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
||||||
state.latestTransactionList = transactionList
|
state.latestTransactionList = transactionList
|
||||||
state.latestTranassctionId = id
|
state.latestTransactionId = id
|
||||||
state.transactionList[0].isMarkedAsRead = true
|
state.transactionList[0].isMarkedAsRead = true
|
||||||
|
|
||||||
XCTAssertFalse(state.transactionList[0].isUnread)
|
XCTAssertFalse(state.transactionList[0].isUnread)
|
||||||
|
@ -596,11 +596,11 @@ class TransactionListTests: XCTestCase {
|
||||||
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
let identifiedTransactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
||||||
|
|
||||||
let store = TestStore(
|
let store = TestStore(
|
||||||
initialState: TransactionListReducer.State(
|
initialState: TransactionList.State(
|
||||||
transactionList: identifiedTransactionList
|
transactionList: identifiedTransactionList
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
TransactionListReducer()
|
TransactionList()
|
||||||
}
|
}
|
||||||
|
|
||||||
store.dependencies.mainQueue = .immediate
|
store.dependencies.mainQueue = .immediate
|
||||||
|
@ -618,7 +618,7 @@ class TransactionListTests: XCTestCase {
|
||||||
await store.receive(.updateTransactionList(transactionList)) { state in
|
await store.receive(.updateTransactionList(transactionList)) { state in
|
||||||
state.transactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
state.transactionList = IdentifiedArrayOf(uniqueElements: transactionList)
|
||||||
state.latestTransactionList = transactionList
|
state.latestTransactionList = transactionList
|
||||||
state.latestTranassctionId = id
|
state.latestTransactionId = id
|
||||||
state.transactionList[0].isMarkedAsRead = true
|
state.transactionList[0].isMarkedAsRead = true
|
||||||
|
|
||||||
XCTAssertFalse(state.transactionList[0].isUnread)
|
XCTAssertFalse(state.transactionList[0].isUnread)
|
||||||
|
|
Loading…
Reference in New Issue