2022-06-23 02:05:34 -07:00
|
|
|
import ComposableArchitecture
|
|
|
|
import SwiftUI
|
2022-06-30 04:59:03 -07:00
|
|
|
import ZcashLightClientKit
|
2022-06-23 02:05:34 -07:00
|
|
|
|
2022-11-04 23:14:44 -07:00
|
|
|
typealias WalletEventsFlowStore = Store<WalletEventsFlowReducer.State, WalletEventsFlowReducer.Action>
|
|
|
|
typealias WalletEventsFlowViewStore = ViewStore<WalletEventsFlowReducer.State, WalletEventsFlowReducer.Action>
|
2022-06-23 02:05:34 -07:00
|
|
|
|
2022-11-04 23:14:44 -07:00
|
|
|
struct WalletEventsFlowReducer: ReducerProtocol {
|
|
|
|
private enum CancelId {}
|
2022-06-23 02:05:34 -07:00
|
|
|
|
2022-11-04 23:14:44 -07:00
|
|
|
struct State: Equatable {
|
2022-12-01 06:31:30 -08:00
|
|
|
enum Destination: Equatable {
|
2022-11-04 23:14:44 -07:00
|
|
|
case latest
|
|
|
|
case all
|
|
|
|
case showWalletEvent(WalletEvent)
|
|
|
|
}
|
2022-06-23 02:05:34 -07:00
|
|
|
|
2022-12-01 06:31:30 -08:00
|
|
|
var destination: Destination?
|
2022-06-23 02:05:34 -07:00
|
|
|
|
2023-02-13 09:13:42 -08:00
|
|
|
@BindingState var alert: AlertState<WalletEventsFlowReducer.Action>?
|
2022-11-04 23:14:44 -07:00
|
|
|
var latestMinedHeight: BlockHeight?
|
2023-02-22 05:50:59 -08:00
|
|
|
var isScrollable = true
|
2022-11-04 23:14:44 -07:00
|
|
|
var requiredTransactionConfirmations = 0
|
|
|
|
var walletEvents = IdentifiedArrayOf<WalletEvent>.placeholder
|
|
|
|
var selectedWalletEvent: WalletEvent?
|
|
|
|
}
|
2022-06-23 02:05:34 -07:00
|
|
|
|
2022-11-04 23:14:44 -07:00
|
|
|
enum Action: Equatable {
|
2023-02-13 11:32:50 -08:00
|
|
|
case copyToPastboard(RedactableString)
|
2022-11-04 23:14:44 -07:00
|
|
|
case dismissAlert
|
|
|
|
case onAppear
|
|
|
|
case onDisappear
|
|
|
|
case openBlockExplorer(URL?)
|
2022-12-01 06:31:30 -08:00
|
|
|
case updateDestination(WalletEventsFlowReducer.State.Destination?)
|
2023-02-13 11:32:50 -08:00
|
|
|
case replyTo(RedactableString)
|
2022-11-17 03:25:55 -08:00
|
|
|
case synchronizerStateChanged(SDKSynchronizerState)
|
2022-11-04 23:14:44 -07:00
|
|
|
case updateWalletEvents([WalletEvent])
|
|
|
|
case warnBeforeLeavingApp(URL?)
|
|
|
|
}
|
|
|
|
|
|
|
|
@Dependency(\.mainQueue) var mainQueue
|
2022-11-14 10:36:51 -08:00
|
|
|
@Dependency(\.pasteboard) var pasteboard
|
2022-11-04 23:14:44 -07:00
|
|
|
@Dependency(\.sdkSynchronizer) var sdkSynchronizer
|
|
|
|
@Dependency(\.zcashSDKEnvironment) var zcashSDKEnvironment
|
2023-03-07 13:18:17 -08:00
|
|
|
|
2022-11-04 23:14:44 -07:00
|
|
|
// swiftlint:disable:next cyclomatic_complexity
|
|
|
|
func reduce(into state: inout State, action: Action) -> ComposableArchitecture.EffectTask<Action> {
|
2022-06-23 02:05:34 -07:00
|
|
|
switch action {
|
|
|
|
case .onAppear:
|
2022-11-04 23:14:44 -07:00
|
|
|
state.requiredTransactionConfirmations = zcashSDKEnvironment.requiredTransactionConfirmations
|
|
|
|
return sdkSynchronizer.stateChanged
|
|
|
|
.map(WalletEventsFlowReducer.Action.synchronizerStateChanged)
|
2022-06-23 02:05:34 -07:00
|
|
|
.eraseToEffect()
|
2022-11-04 23:14:44 -07:00
|
|
|
.cancellable(id: CancelId.self, cancelInFlight: true)
|
2022-06-23 02:05:34 -07:00
|
|
|
|
|
|
|
case .onDisappear:
|
2023-02-13 09:13:42 -08:00
|
|
|
return .cancel(id: CancelId.self)
|
2022-06-23 02:05:34 -07:00
|
|
|
|
|
|
|
case .synchronizerStateChanged(.synced):
|
2022-11-04 23:14:44 -07:00
|
|
|
if let latestMinedHeight = sdkSynchronizer.synchronizer?.latestScannedHeight {
|
2022-06-30 04:59:03 -07:00
|
|
|
state.latestMinedHeight = latestMinedHeight
|
|
|
|
}
|
2023-02-22 05:50:59 -08:00
|
|
|
return sdkSynchronizer.getAllTransactions()
|
2022-11-04 23:14:44 -07:00
|
|
|
.receive(on: mainQueue)
|
|
|
|
.map(WalletEventsFlowReducer.Action.updateWalletEvents)
|
2022-06-23 02:05:34 -07:00
|
|
|
.eraseToEffect()
|
|
|
|
|
2022-11-04 23:14:44 -07:00
|
|
|
case .synchronizerStateChanged:
|
2022-06-23 02:05:34 -07:00
|
|
|
return .none
|
|
|
|
|
|
|
|
case .updateWalletEvents(let walletEvents):
|
|
|
|
let sortedWalletEvents = walletEvents
|
|
|
|
.sorted(by: { lhs, rhs in
|
2023-02-06 00:38:34 -08:00
|
|
|
guard let lhsTimestamp = lhs.timestamp, let rhsTimestamp = rhs.timestamp else {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return lhsTimestamp > rhsTimestamp
|
2022-06-23 02:05:34 -07:00
|
|
|
})
|
|
|
|
state.walletEvents = IdentifiedArrayOf(uniqueElements: sortedWalletEvents)
|
|
|
|
return .none
|
|
|
|
|
2022-12-01 06:31:30 -08:00
|
|
|
case .updateDestination(.showWalletEvent(let walletEvent)):
|
2022-07-08 11:27:18 -07:00
|
|
|
state.selectedWalletEvent = walletEvent
|
2022-12-01 06:31:30 -08:00
|
|
|
state.destination = .showWalletEvent(walletEvent)
|
2022-07-08 11:27:18 -07:00
|
|
|
return .none
|
|
|
|
|
2022-12-01 06:31:30 -08:00
|
|
|
case .updateDestination(let destination):
|
|
|
|
state.destination = destination
|
|
|
|
if destination == nil {
|
2022-07-08 11:27:18 -07:00
|
|
|
state.selectedWalletEvent = nil
|
|
|
|
}
|
2022-06-23 02:05:34 -07:00
|
|
|
return .none
|
2022-06-28 00:38:08 -07:00
|
|
|
|
|
|
|
case .copyToPastboard(let value):
|
2022-11-04 23:14:44 -07:00
|
|
|
pasteboard.setString(value)
|
2022-06-28 00:38:08 -07:00
|
|
|
return .none
|
|
|
|
|
2022-11-04 23:14:44 -07:00
|
|
|
case .replyTo:
|
2022-06-28 00:38:08 -07:00
|
|
|
return .none
|
2022-09-22 12:20:46 -07:00
|
|
|
|
|
|
|
case .dismissAlert:
|
|
|
|
state.alert = nil
|
|
|
|
return .none
|
|
|
|
|
|
|
|
case .warnBeforeLeavingApp(let blockExplorerURL):
|
|
|
|
state.alert = AlertState(
|
2023-03-07 13:18:17 -08:00
|
|
|
title: TextState(L10n.WalletEvent.Alert.LeavingApp.title),
|
|
|
|
message: TextState(L10n.WalletEvent.Alert.LeavingApp.message),
|
2022-09-22 12:20:46 -07:00
|
|
|
primaryButton: .cancel(
|
2023-03-07 13:18:17 -08:00
|
|
|
TextState(L10n.WalletEvent.Alert.LeavingApp.Button.nevermind),
|
2022-09-22 12:20:46 -07:00
|
|
|
action: .send(.dismissAlert)
|
|
|
|
),
|
|
|
|
secondaryButton: .default(
|
2023-03-07 13:18:17 -08:00
|
|
|
TextState(L10n.WalletEvent.Alert.LeavingApp.Button.seeOnline),
|
2022-09-22 12:20:46 -07:00
|
|
|
action: .send(.openBlockExplorer(blockExplorerURL))
|
|
|
|
)
|
|
|
|
)
|
|
|
|
return .none
|
|
|
|
|
|
|
|
case .openBlockExplorer(let blockExplorerURL):
|
|
|
|
state.alert = nil
|
|
|
|
if let url = blockExplorerURL {
|
|
|
|
UIApplication.shared.open(url, options: [:], completionHandler: nil)
|
|
|
|
}
|
|
|
|
return .none
|
2022-06-23 02:05:34 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - ViewStore
|
|
|
|
|
|
|
|
extension WalletEventsFlowViewStore {
|
2022-12-01 06:31:30 -08:00
|
|
|
private typealias Destination = WalletEventsFlowReducer.State.Destination
|
2022-06-23 02:05:34 -07:00
|
|
|
|
2022-07-08 11:27:18 -07:00
|
|
|
func bindingForSelectedWalletEvent(_ walletEvent: WalletEvent?) -> Binding<Bool> {
|
2022-06-23 02:05:34 -07:00
|
|
|
self.binding(
|
2022-07-08 11:27:18 -07:00
|
|
|
get: {
|
2023-03-06 06:14:18 -08:00
|
|
|
guard let walletEvent else {
|
2022-07-08 11:27:18 -07:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2022-12-01 06:31:30 -08:00
|
|
|
return $0.destination.map(/WalletEventsFlowReducer.State.Destination.showWalletEvent) == walletEvent
|
2022-07-08 11:27:18 -07:00
|
|
|
},
|
2022-06-23 02:05:34 -07:00
|
|
|
send: { isActive in
|
2023-03-06 06:14:18 -08:00
|
|
|
guard let walletEvent else {
|
2022-12-01 06:31:30 -08:00
|
|
|
return WalletEventsFlowReducer.Action.updateDestination(nil)
|
2022-07-08 11:27:18 -07:00
|
|
|
}
|
|
|
|
|
2022-12-07 05:47:42 -08:00
|
|
|
return WalletEventsFlowReducer.Action.updateDestination(
|
|
|
|
isActive ? WalletEventsFlowReducer.State.Destination.showWalletEvent(walletEvent) : nil
|
|
|
|
)
|
2022-06-23 02:05:34 -07:00
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: Placeholders
|
|
|
|
|
|
|
|
extension TransactionState {
|
|
|
|
static var placeholder: Self {
|
|
|
|
.init(
|
2022-07-08 11:27:18 -07:00
|
|
|
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
2022-07-19 11:56:46 -07:00
|
|
|
fee: Zatoshi(10),
|
2022-06-23 02:05:34 -07:00
|
|
|
id: "2",
|
|
|
|
status: .paid(success: true),
|
|
|
|
timestamp: 1234567,
|
2022-07-19 11:56:46 -07:00
|
|
|
zecAmount: Zatoshi(123_000_000)
|
2022-07-08 11:27:18 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
static func statePlaceholder(_ status: Status) -> Self {
|
|
|
|
.init(
|
|
|
|
zAddress: "t1gXqfSSQt6WfpwyuCU3Wi7sSVZ66DYQ3Po",
|
2022-07-19 11:56:46 -07:00
|
|
|
fee: Zatoshi(10),
|
2022-07-08 11:27:18 -07:00
|
|
|
id: "2",
|
|
|
|
status: status,
|
|
|
|
timestamp: 1234567,
|
2022-07-19 11:56:46 -07:00
|
|
|
zecAmount: Zatoshi(123_000_000)
|
2022-06-23 02:05:34 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-04 23:14:44 -07:00
|
|
|
extension WalletEventsFlowReducer.State {
|
2022-06-23 02:05:34 -07:00
|
|
|
static var placeHolder: Self {
|
|
|
|
.init(walletEvents: .placeholder)
|
|
|
|
}
|
|
|
|
|
|
|
|
static var emptyPlaceHolder: Self {
|
|
|
|
.init(walletEvents: [])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension WalletEventsFlowStore {
|
2022-11-04 23:14:44 -07:00
|
|
|
static var placeholder: Store<WalletEventsFlowReducer.State, WalletEventsFlowReducer.Action> {
|
2022-06-23 02:05:34 -07:00
|
|
|
return Store(
|
|
|
|
initialState: .placeHolder,
|
2022-11-04 23:14:44 -07:00
|
|
|
reducer: WalletEventsFlowReducer()
|
|
|
|
.dependency(\.zcashSDKEnvironment, .testnet)
|
2022-06-23 02:05:34 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension IdentifiedArrayOf where Element == TransactionState {
|
|
|
|
static var placeholder: IdentifiedArrayOf<TransactionState> {
|
|
|
|
return .init(
|
|
|
|
uniqueElements: (0..<30).map {
|
|
|
|
TransactionState(
|
2022-07-19 11:56:46 -07:00
|
|
|
fee: Zatoshi(10),
|
2022-06-23 02:05:34 -07:00
|
|
|
id: String($0),
|
|
|
|
status: .paid(success: true),
|
|
|
|
timestamp: 1234567,
|
2022-07-19 11:56:46 -07:00
|
|
|
zecAmount: Zatoshi(25)
|
2022-06-23 02:05:34 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|