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

Adds Kotlin Sink, makeActionSink, makeEventSink. #537

Merged
merged 1 commit into from Aug 21, 2019
Merged

Commits on Aug 21, 2019

  1. Adds Kotlin Sink, makeActionSink, makeEventSink.

    This PR introduces:
    
     * a Kotlin `Sink` class matching Swift's
     * `RenderContext.makeActionSink` matching Swift's `makeSink(ofActionType)`
     * `RenderContext.makeEventSink` matching Swift's `makeSink(ofEventType)`
    
    and deprecates:
    
     * `WorkflowAction.enterState`
     * `WorkflowAction.emitOutput`
     * `WorkflowAction.modifyState`
     * `RenderContext.onEvent`
     * `EventHandler`
    
    Kotlin apps are now able to make custom WorkflowAction class hierarchies in
    the style common in Swift apps. This is made possible by the new
    `WorkflowAction.apply` method, analagous to the same method in Swift.
    Where the Swift version has an `inout StateT` function argument,
    Kotlin's is called against a `Mutator<StateT>` receiver.
    
    This allows us to implement action types like the following, where the null
    returns indicate that no output is to be emitted.
    
    ```
      sealed class Action : WorkflowAction<Movement, Nothing> {
        class StartMoving(private val direction: Direction) : Action() {
          override fun Mutator<Movement>.apply(): Nothing? {
            state += direction
            return null
          }
        }
    
        class StopMoving(private val direction: Direction) : Action() {
          override fun Mutator<Movement>.apply(): Nothing? {
            state -= direction
            return null
          }
        }
      }
    ```
    
    The convention is to declare these `Action` types inside workflows, instead of
    `Event` type trees in rendering classes. And instead of creating `EventHandler`
    instances to be used by renderings, we create `Sink` instances:
    
    ```
      override fun render(
        input: TakeTurnsInput,
        state: Turn,
        context: RenderContext<Turn, CompletedGame>
      ): GamePlayScreen {
        val sink = context.makeActionSink<Action>()
    
        return GamePlayScreen(
            playerInfo = input.playerInfo,
            gameState = state,
            onQuit = { sink.send(Quit) },
            onClick = { row, col -> sink.send(TakeSquare(row, col)) }
        )
      }
    ```
    rjrjr committed Aug 21, 2019
    Copy the full SHA
    5f3cb7b View commit details
    Browse the repository at this point in the history