// // TCALoggerReducer.swift // Zashi // // Created by Lukáš Korba on 23.01.2023. // import ComposableArchitecture import ZcashLightClientKit extension Reducer { @inlinable public func logging( _ logger: ReducerLogger? = .tcaLogger ) -> LogChangesReducer { LogChangesReducer(base: self, logger: logger) } } public struct ReducerLogger { private let _logChange: (_ receivedAction: Action, _ oldState: State, _ newState: State) -> Void public init( logChange: @escaping (_ receivedAction: Action, _ oldState: State, _ newState: State) -> Void ) { self._logChange = logChange } public func logChange(receivedAction: Action, oldState: State, newState: State) { self._logChange(receivedAction, oldState, newState) } } extension ReducerLogger { public static var tcaLogger: Self { Self { receivedAction, oldState, newState in var target = "" target.write("received action:\n") CustomDump.customDump(receivedAction, to: &target, indent: 2) target.write("\n") target.write(diff(oldState, newState).map { "\($0)\n" } ?? " (No state changes)\n") OSLogger.live.tcaDebug("\(target)") } } } public struct LogChangesReducer: Reducer { @usableFromInline let base: Base @usableFromInline let logger: ReducerLogger? @usableFromInline init(base: Base, logger: ReducerLogger?) { self.base = base self.logger = logger } @inlinable public func reduce( into state: inout Base.State, action: Base.Action ) -> Effect { guard let logger else { return self.base.reduce(into: &state, action: action) } let oldState = state let effects = self.base.reduce(into: &state, action: action) return effects.merge( with: .run { [newState = state] _ in logger.logChange(receivedAction: action, oldState: oldState, newState: newState) } ) } }