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:
Lukas Korba 2024-06-21 10:29:16 +02:00 committed by GitHub
commit 1375c75267
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 329 additions and 324 deletions

View File

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

View File

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

View File

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

View File

@ -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
WithPerceptionTracking {
TransactionRowView( TransactionRowView(
viewStore: viewStore, store: store,
transaction: transaction, transaction: transaction,
tokenName: tokenName, tokenName: tokenName,
isLatestTransaction: viewStore.isLatestTransaction(id: transaction.id) 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
]
)
}
}

View File

@ -11,25 +11,26 @@ 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 {
WithPerceptionTracking {
if let memoTexts = messages { if let memoTexts = messages {
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
Text(memoTexts.count == 1 Text(memoTexts.count == 1
@ -65,7 +66,7 @@ struct MessageView: View {
: .left : .left
) )
TapToCopyTransactionDataView(viewStore: viewStore, data: memoTexts[index].redacted) TapToCopyTransactionDataView(store: store, data: memoTexts[index].redacted)
} }
.padding(.bottom, 20) .padding(.bottom, 20)
} }
@ -78,18 +79,19 @@ 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
) )

View File

@ -11,17 +11,18 @@ 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 {
WithPerceptionTracking {
Button { Button {
viewStore.send(.copyToPastboard(data)) store.send(.copyToPastboard(data))
} label: { } label: {
HStack { HStack {
Asset.Assets.copy.image Asset.Assets.copy.image
@ -38,10 +39,11 @@ struct TapToCopyTransactionDataView: View {
.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
) )
} }

View File

@ -12,21 +12,22 @@ 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 {
WithPerceptionTracking {
VStack(spacing: 0) { VStack(spacing: 0) {
Divider() Divider()
.padding(.horizontal, 30) .padding(.horizontal, 30)
@ -59,7 +60,7 @@ struct TransactionHeaderView: View {
.padding(.horizontal, 60) .padding(.horizontal, 60)
.padding(.bottom, 5) .padding(.bottom, 5)
TapToCopyTransactionDataView(viewStore: viewStore, data: transaction.address.redacted) TapToCopyTransactionDataView(store: store, data: transaction.address.redacted)
.padding(.horizontal, 60) .padding(.horizontal, 60)
.padding(.bottom, 20) .padding(.bottom, 20)
} }
@ -73,6 +74,7 @@ struct TransactionHeaderView: View {
} }
.padding(.bottom, 30) .padding(.bottom, 30)
} }
}
@ViewBuilder private func iconImage() -> some View { @ViewBuilder private func iconImage() -> some View {
HStack { HStack {
@ -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)

View File

@ -11,22 +11,23 @@ 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 {
WithPerceptionTracking {
VStack(alignment: .leading, spacing: 0) { VStack(alignment: .leading, spacing: 0) {
if !transaction.isIdExpanded { if !transaction.isIdExpanded {
HStack { HStack {
Text(L10n.TransactionList.transactionId) Text(L10n.TransactionList.transactionId)
Button { Button {
viewStore.send(.transactionIdExpandRequested(transaction.id)) store.send(.transactionIdExpandRequested(transaction.id))
} label: { } label: {
Text(transaction.id) Text(transaction.id)
.lineLimit(1) .lineLimit(1)
@ -52,7 +53,7 @@ struct TransactionIdView: View {
} }
.padding(.bottom, 10) .padding(.bottom, 10)
TapToCopyTransactionDataView(viewStore: viewStore, data: transaction.id.redacted) TapToCopyTransactionDataView(store: store, data: transaction.id.redacted)
.padding(.bottom, 20) .padding(.bottom, 20)
} }
} }
@ -60,13 +61,14 @@ struct TransactionIdView: View {
.foregroundColor(Asset.Colors.shade47.color) .foregroundColor(Asset.Colors.shade47.color)
} }
} }
}
#Preview { #Preview {
var transaction = TransactionState.placeholder() var transaction = TransactionState.placeholder()
transaction.isIdExpanded = true transaction.isIdExpanded = true
return TransactionIdView( return TransactionIdView(
viewStore: ViewStore(.placeholder, observe: { $0 }), store: .placeholder,
transaction: transaction transaction: transaction
) )
} }

View File

@ -13,36 +13,37 @@ 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 {
WithPerceptionTracking {
Button { Button {
viewStore.send(.transactionExpandRequested(transaction.id), animation: .default) store.send(.transactionExpandRequested(transaction.id), animation: .default)
} label: { } label: {
if transaction.isExpanded { if transaction.isExpanded {
TransactionHeaderView( TransactionHeaderView(
viewStore: viewStore, store: store,
transaction: transaction, transaction: transaction,
isLatestTransaction: isLatestTransaction isLatestTransaction: isLatestTransaction
) )
} else { } else {
TransactionHeaderView( TransactionHeaderView(
viewStore: viewStore, store: store,
transaction: transaction, transaction: transaction,
isLatestTransaction: isLatestTransaction isLatestTransaction: isLatestTransaction
) )
@ -53,7 +54,7 @@ public struct TransactionRowView: View {
Group { Group {
if !transaction.isTransparentRecipient { if !transaction.isTransparentRecipient {
MessageView( MessageView(
viewStore: viewStore, store: store,
messages: transaction.textMemos, messages: transaction.textMemos,
isSpending: transaction.isSpending, isSpending: transaction.isSpending,
isFailed: transaction.status == .failed isFailed: transaction.status == .failed
@ -61,7 +62,7 @@ public struct TransactionRowView: View {
} }
TransactionIdView( TransactionIdView(
viewStore: viewStore, store: store,
transaction: transaction transaction: transaction
) )
@ -71,7 +72,7 @@ public struct TransactionRowView: View {
} }
Button { Button {
viewStore.send(.transactionCollapseRequested(transaction.id), animation: .default) store.send(.transactionCollapseRequested(transaction.id), animation: .default)
} label: { } label: {
CollapseTransactionView() CollapseTransactionView()
.padding(.vertical, 20) .padding(.vertical, 20)
@ -81,11 +82,12 @@ 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"
) )

View File

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

View File

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