Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ActionDispatcher Callable. #32

Merged
merged 7 commits into from
Feb 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
on: [push, pull_request]
on:
push:
branches:
- 'master'
pull_request:
branches:
- '**'
name: build
jobs:
validate:
Expand Down
23 changes: 18 additions & 5 deletions Sources/SwiftDux/Action/ActionDispatcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Foundation

/// A closure that dispatches an action.
///
/// - Parameter action: Dispatches the given state synchronously.
/// - Parameter action: Dispatches the given action synchronously.
public typealias SendAction = (Action) -> Void

/// A closure that can return a new action from a previous one. If no action is returned,
Expand All @@ -23,10 +23,23 @@ public protocol ActionDispatcher {
/// Create a new `ActionDispatcher` that acts as a proxy for the current one.
///
/// Actions can be modified by both the new proxy and the original dispatcher it was created from.
/// - Parameters
/// - modifyAction: An optional closure to modify the action before it continues up stream.
/// - sentAction: Called directly after an action was sent up stream.
/// - Parameter modifyAction: An optional closure to modify the action before it continues up stream.
/// - Returns: a new action dispatcher.
func proxy(modifyAction: ActionModifier?, sentAction: SendAction?) -> ActionDispatcher
func proxy(modifyAction: ActionModifier?) -> ActionDispatcher
}

extension ActionDispatcher {

/// Sends an action to a reducer to mutate the state of the application.
/// - Parameter action: An action to dispatch to the store.
public func callAsFunction(_ action: Action) {
send(action)
}

/// Send an action that returns a cancellable object.
/// - Parameter action: The action
/// - Returns: A cancellable to cancel the action.
public func sendAsCancellable(_ action: CancellableAction) -> AnyCancellable {
action.sendAsCancellable(self)
}
}
8 changes: 2 additions & 6 deletions Sources/SwiftDux/Action/ActionPlan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ public struct ActionPlan<State>: CancellableAction where State: StateType {
///
/// - Parameter send: The send function that dispatches an action.
/// - Returns: AnyCancellable to cancel the action plan.
public func sendAsCancellable(_ send: SendAction) -> Cancellable {
public func sendAsCancellable(_ send: ActionDispatcher) -> AnyCancellable {
var publisherCancellable: AnyCancellable? = nil
send(
ActionPlan<State> { store, completed in
Expand All @@ -132,11 +132,7 @@ public struct ActionPlan<State>: CancellableAction where State: StateType {
return publisherCancellable
}
)

return AnyCancellable {
publisherCancellable?.cancel()
publisherCancellable = nil
}
return AnyCancellable { [publisherCancellable] in publisherCancellable?.cancel() }
}

/// Dispatches another action plan after this one has completed. This allows
Expand Down
19 changes: 5 additions & 14 deletions Sources/SwiftDux/Action/ActionSubscriber.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ final public class ActionSubscriber: Subscriber {

public typealias ReceivedCompletion = () -> Void

private let sendAction: SendAction
private let actionDispatcher: ActionDispatcher
private let receivedCompletion: ReceivedCompletion?
private var subscription: Subscription? = nil {
willSet {
Expand All @@ -15,8 +15,8 @@ final public class ActionSubscriber: Subscriber {
}
}

internal init(sendAction: @escaping SendAction, receivedCompletion: ReceivedCompletion?) {
self.sendAction = sendAction
internal init(actionDispatcher: ActionDispatcher, receivedCompletion: ReceivedCompletion?) {
self.actionDispatcher = actionDispatcher
self.receivedCompletion = receivedCompletion
}

Expand All @@ -26,7 +26,7 @@ final public class ActionSubscriber: Subscriber {
}

public func receive(_ input: Action) -> Subscribers.Demand {
sendAction(input)
actionDispatcher(input)
return .max(1)
}

Expand All @@ -49,17 +49,8 @@ extension Publisher where Output == Action, Failure == Never {
/// - receivedCompletion: An optional block called when the publisher completes.
/// - Returns: A cancellable to unsubscribe.
public func send(to actionDispatcher: ActionDispatcher, receivedCompletion: ActionSubscriber.ReceivedCompletion? = nil) -> AnyCancellable {
self.send(to: actionDispatcher.send, receivedCompletion: receivedCompletion)
}

/// Subscribe to a publisher of actions, and send the results to an action dispatcher.
/// - Parameters:
/// - sendAction: A block that dispatches actions..
/// - receivedCompletion: An optional block called when the publisher completes.
/// - Returns: A cancellable to unsubscribe.
public func send(to sendAction: @escaping SendAction, receivedCompletion: ActionSubscriber.ReceivedCompletion? = nil) -> AnyCancellable {
let subscriber = ActionSubscriber(
sendAction: sendAction,
actionDispatcher: actionDispatcher,
receivedCompletion: receivedCompletion
)
self.subscribe(subscriber)
Expand Down
3 changes: 1 addition & 2 deletions Sources/SwiftDux/Action/CancellableAction.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,5 @@ public protocol CancellableAction: Action {
///
/// - Parameter send: The send function that dispatches an action.
/// - Returns: AnyCancellable to cancel the action plan.
func sendAsCancellable(_ send: SendAction) -> Cancellable

func sendAsCancellable(_ send: ActionDispatcher) -> AnyCancellable
}
29 changes: 0 additions & 29 deletions Sources/SwiftDux/Action/ModifiedAction.swift

This file was deleted.

57 changes: 7 additions & 50 deletions Sources/SwiftDux/Store/Store.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,23 +48,16 @@ public final class Store<State> where State: StateType {

extension Store: ActionDispatcher {

// swift-format-disable: UseLetInEveryBoundCaseVariable

/// Sends an action to the store to mutate its state.
/// - Parameter action: The action to mutate the state.
public func send(_ action: Action) {
switch action {
case let action as ActionPlan<State>:
if let action = action as? ActionPlan<State> {
send(actionPlan: action)
case let modifiedAction as ModifiedAction:
send(modifiedAction: modifiedAction)
default:
} else {
reduceAction(action)
}
}

// swift-format-enable: UseLetInEveryBoundCaseVariable

/// Handles the sending of normal action plans.
private func send(actionPlan: ActionPlan<State>) {
var cancellable: AnyCancellable? = nil
Expand All @@ -81,50 +74,14 @@ extension Store: ActionDispatcher {
didChangeSubject.send(actionPlan)
}

private func send(modifiedAction: ModifiedAction) {
send(modifiedAction.action)
modifiedAction.previousActions.forEach { self.didChangeSubject.send($0) }
}

/// Create a new `ActionDispatcher` that acts as a proxy between the action sender and the store. It optionally allows actions to be
/// modified or tracked.
/// - Parameters
/// - modifyAction: An optional closure to modify the action before it continues up stream.
/// - sentAction: Called directly after an action was sent up stream.
/// - Parameter modifyAction: An optional closure to modify the action before it continues up stream.
/// - Returns: a new action dispatcher.
public func proxy(modifyAction: ActionModifier? = nil, sentAction: ((Action) -> Void)? = nil) -> ActionDispatcher {
StoreActionDispatcher(
upstream: self,
modifyAction: modifyAction,
sentAction: sentAction
public func proxy(modifyAction: ActionModifier? = nil) -> ActionDispatcher {
StoreProxy<State>(
store: self,
modifyAction: modifyAction
)
}

}

extension Publisher where Output == Action, Failure == Never {

/// Subscribe to a publisher of actions, and send the results to a store.
/// - Parameters:
/// - store: A store proxy
/// - receivedCompletion: An optional block called when the publisher completes.
/// - Returns: A cancellable to unsubscribe.
public func send<State>(to store: Store<State>, receivedCompletion: ActionSubscriber.ReceivedCompletion? = nil) -> AnyCancellable
where State: StateType {
self.send(to: store, receivedCompletion: receivedCompletion)
}

/// Subscribe to a publisher of actions, and send the results to a store.
/// - Parameters:
/// - store: A store proxy
/// - receivedCompletion: An optional block called when the publisher completes.
/// - Returns: A cancellable to unsubscribe.
public func send<State>(to store: StoreProxy<State>, receivedCompletion: ActionSubscriber.ReceivedCompletion? = nil) -> AnyCancellable
where State: StateType {
let cancellable = self.send(to: store.send, receivedCompletion: receivedCompletion)
return AnyCancellable { [cancellable] in
cancellable.cancel()
store.done()
}
}
}
108 changes: 0 additions & 108 deletions Sources/SwiftDux/Store/StoreActionDispatcher.swift

This file was deleted.

Loading