Skip to content

Commit

Permalink
Change usages of PassthroughSubject to private and create read-only p…
Browse files Browse the repository at this point in the history
…ublishers to provide their outputs
  • Loading branch information
Qata committed Jul 5, 2021
1 parent 8402a3f commit e4ba428
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 25 deletions.
68 changes: 45 additions & 23 deletions Sources/RecombinePackage/Store/BaseStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,19 @@ public class BaseStore<State: Equatable, RawAction, RefinedAction>: StoreProtoco
public typealias SubState = State
public typealias SubRefinedAction = RefinedAction
public typealias Action = ActionStrata<RawAction, RefinedAction>
public typealias ActionsAndState = ([RefinedAction], (previous: State, current: State))
@Published
public private(set) var state: State
public var statePublisher: Published<State>.Publisher { $state }
public var underlying: BaseStore<State, RawAction, RefinedAction> { self }
public let stateLens: (State) -> State = { $0 }
public let rawActions = PassthroughSubject<RawAction, Never>()
public let preMiddlewareRefinedActions = PassthroughSubject<[RefinedAction], Never>()
public let postMiddlewareRefinedActions = PassthroughSubject<[RefinedAction], Never>()
public let allStateUpdates = PassthroughSubject<State, Never>()
public let actionsPairedWithState = PassthroughSubject<([RefinedAction], (previous: State, current: State)), Never>()
public let actionPromotion: (RefinedAction) -> RefinedAction = { $0 }
public var actions: AnyPublisher<Action, Never> {
Publishers.Merge(
rawActions.map(Action.raw),
postMiddlewareRefinedActions.flatMap(\.publisher).map(Action.refined)
)
.eraseToAnyPublisher()
}

private let _rawActions = PassthroughSubject<RawAction, Never>()
private let _preMiddlewareRefinedActions = PassthroughSubject<[RefinedAction], Never>()
private let _postMiddlewareRefinedActions = PassthroughSubject<[RefinedAction], Never>()
private let _allStateUpdates = PassthroughSubject<State, Never>()
private let _actionsPairedWithState = PassthroughSubject<ActionsAndState, Never>()
private var cancellables = Set<AnyCancellable>()

public init<S: Scheduler, R: Reducer>(
Expand All @@ -34,7 +28,7 @@ public class BaseStore<State: Equatable, RawAction, RefinedAction>: StoreProtoco
) where R.State == State, R.Action == RefinedAction {
self.state = state

rawActions.flatMap { [weak self] action in
_rawActions.flatMap { [weak self] action in
self.publisher().flatMap {
thunk.transform($0.$state.first(), action)
}
Expand All @@ -50,17 +44,17 @@ public class BaseStore<State: Equatable, RawAction, RefinedAction>: StoreProtoco
.store(in: &cancellables)

Publishers.Zip(
postMiddlewareRefinedActions,
allStateUpdates
_postMiddlewareRefinedActions,
_allStateUpdates
.prepend(state)
.scan([]) { acc, item in .init((acc + [item]).suffix(2)) }
.filter { $0.count == 2 }
.map { ($0[0], $0[1]) }
)
.sink(receiveValue: actionsPairedWithState.send)
.sink(receiveValue: _actionsPairedWithState.send)
.store(in: &cancellables)

preMiddlewareRefinedActions
_preMiddlewareRefinedActions
.flatMap { [weak self] actions in
self.publisher()
.flatMap { $0.$state.first() }
Expand All @@ -72,34 +66,62 @@ public class BaseStore<State: Equatable, RawAction, RefinedAction>: StoreProtoco
}
}
.sink(receiveValue: { [weak self] actions in
self?.postMiddlewareRefinedActions.send(actions)
self?._postMiddlewareRefinedActions.send(actions)
})
.store(in: &cancellables)

postMiddlewareRefinedActions
_postMiddlewareRefinedActions
.scan(state) { state, actions in
actions.reduce(state, reducer.reduce)
}
.receive(on: scheduler)
.sink { [weak self] state in
guard let self = self else { return }
self.allStateUpdates.send(state)
self._allStateUpdates.send(state)
if self.state != state {
self.state = state
}
}
.store(in: &cancellables)
}

public var actions: AnyPublisher<Action, Never> {
Publishers.Merge(
_rawActions.map(Action.raw),
_postMiddlewareRefinedActions.flatMap(\.publisher).map(Action.refined)
)
.eraseToAnyPublisher()
}

open var rawActions: AnyPublisher<RawAction, Never> {
_rawActions.eraseToAnyPublisher()
}

open var preMiddlewareRefinedActions: AnyPublisher<[RefinedAction], Never> {
_preMiddlewareRefinedActions.eraseToAnyPublisher()
}

open var postMiddlewareRefinedActions: AnyPublisher<[RefinedAction], Never> {
_postMiddlewareRefinedActions.eraseToAnyPublisher()
}

open var allStateUpdates: AnyPublisher<State, Never> {
_allStateUpdates.eraseToAnyPublisher()
}

open var actionsPairedWithState: AnyPublisher<ActionsAndState, Never> {
_actionsPairedWithState.eraseToAnyPublisher()
}

open func dispatch<S: Sequence>(refined actions: S) where S.Element == RefinedAction {
preMiddlewareRefinedActions.send(.init(actions))
_preMiddlewareRefinedActions.send(.init(actions))
}

open func dispatch<S: Sequence>(raw actions: S) where S.Element == RawAction {
actions.forEach(rawActions.send)
actions.forEach(_rawActions.send)
}

open func injectBypassingMiddleware<S: Sequence>(actions: S) where S.Element == RefinedAction {
postMiddlewareRefinedActions.send(.init(actions))
_postMiddlewareRefinedActions.send(.init(actions))
}
}
9 changes: 7 additions & 2 deletions Sources/RecombinePackage/Store/LensedStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ public class LensedStore<BaseState: Equatable, SubState: Equatable, RawAction, B
public var statePublisher: Published<SubState>.Publisher { $state }
public let underlying: BaseStore<BaseState, RawAction, BaseRefinedAction>
public let stateLens: (BaseState) -> SubState
public let actions = PassthroughSubject<[SubRefinedAction], Never>()
public let actionPromotion: (SubRefinedAction) -> BaseRefinedAction

private let _actions = PassthroughSubject<[SubRefinedAction], Never>()
private var cancellables = Set<AnyCancellable>()

public required init(store: StoreType, lensing lens: @escaping (BaseState) -> SubState, actionPromotion: @escaping (SubRefinedAction) -> BaseRefinedAction) {
Expand All @@ -25,8 +26,12 @@ public class LensedStore<BaseState: Equatable, SubState: Equatable, RawAction, B
.store(in: &cancellables)
}

open var actions: AnyPublisher<[SubRefinedAction], Never> {
_actions.eraseToAnyPublisher()
}

open func dispatch<S: Sequence>(refined actions: S) where S.Element == SubRefinedAction {
self.actions.send(.init(actions))
_actions.send(.init(actions))
underlying.dispatch(refined: actions.map(actionPromotion))
}

Expand Down

0 comments on commit e4ba428

Please sign in to comment.