Skip to content

Commit

Permalink
Merge pull request #32 from StevenLambion/features/call-ActionDispatc…
Browse files Browse the repository at this point in the history
…her-as-function

Make ActionDispatcher Callable.
  • Loading branch information
StevenLambion authored Feb 8, 2020
2 parents 9b03dff + ed22980 commit 09139f1
Show file tree
Hide file tree
Showing 17 changed files with 79 additions and 294 deletions.
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

0 comments on commit 09139f1

Please sign in to comment.