Skip to content

Releases: freeletics/FlowRedux

1.2.2

21 Jun 09:39
0f53708
Compare
Choose a tag to compare
  • Added wasmJs target.
  • Potentially fix a crash for onEnterStateMachine where an action could be dispatched
    to the sub state machine during cancellation.
  • Updated to Kotlin 2.0.0.
  • Updated to Coroutines 1.8.1.

1.2.1

07 Jan 13:50
1.2.1
25cfde1
Compare
Choose a tag to compare
  • Fix deadlock when using ExecutionPolicy.ORDERED.
  • Reduce allocations in rememberStateAndDispatch. Thanks to @hoc081098 for the contribution.
  • Updated to Kotlin 1.9.22.

1.2.0

28 Jul 12:16
a6546b4
Compare
Choose a tag to compare

DSL additions

  • Added new condition block that allows specifying additional condition for a state. The block
    supports all the same methods that inState supports.
    spec {
      inState<MyState> {
        // general onEnter/onAction/... methods
    
        condition({ state -> state.value == "condition" }) { 
          // onEnter/onAction/... methods that will only be triggered when the condition is true
        }
      }
    }
  • Added new untilIdentityChanges block. This allows to give a state object an identity
    like an id and will re-trigger anything running in that block whenever the identity changes.
    spec {
      inState<MyState> {
        // general onEnter/onAction/... methods
    
        untilIdentityChanges({ state -> state.searchQuery }) { 
          // triggered whenever `searchQuery` changes
          onEnterEffect { state ->
            sendAnalyticsEvent(state.searchQuery)
          }
          
          // whenever `searchQuery` changes the collection is stopped and a new flow is built and collected
          collectWhileInState({ state -> loadSearchResults(state.searchQuery )}) { result, state ->
            // update state based on result
          }
        }
      }
    }

Internal re-write

  • The internals of FlowRedux have been completely rewritten and simplified. The library behavior
    is now much more consistent and predictable.
  • Cancellation of a running block like collectWhileInState is now guaranteed to happen before
    anything in the new state starts.

Other changes

  • The collectWhileInState method that has a lambda parameter to build the collected Flow.
    now receives S instead of Flow<S> as its parameter.
  • The compose artifact now a multiplatform library with support for all platform supported
    by compose-multiplatform.

Deprecations

  • inState with additionalIsInState has been deprecated in favor of the condition block.
  • inStateWithCondition has been deprecated in favor of the condition block.

1.1.0

12 May 10:36
8537f85
Compare
Choose a tag to compare

  • Updated to Kotlin 1.8.21 and Coroutines 1.7.0.
  • Added support for Kotlin/JS
  • Added support for all tier 1, 2 and 3 Kotlin/Native targets
  • Removed the @FlowPreview opt in annotation, @ExperimentalCoroutinesApi is still required.
  • The sub state machine DSL methods now take StateMachine instead of FlowReduxStateMachine as parameter.
    This allows using different kinds of state machines together with FlowRedux which might ease migrating
    a state machine to FlowRedux.
  • A few methods which already had reified overloads are now hidden from auto complete (this change is binary
    compatible).
  • Fixed race condition when using sub state machines that could cause a crash when an action is dispatched
    shortly after the sub state machine starts.

1.0.2

15 Nov 09:02
Compare
Choose a tag to compare

What's Changed

  • Support optional values in the actionMapper of sub state machines. When the mapper returns null the action won't be forwarded which removes the need to either handle all actions in the sub state machine or introduce a no op action.

1.0.1

04 Nov 13:49
Compare
Choose a tag to compare
  • Dependency updates

1.0.0

06 Jul 15:28
Compare
Choose a tag to compare
  • Remove deprecated ChangeState and other (deprecated friends) #318
  • Restructure, update and extend docs #324
  • Add DSL marker in #330

0.13.0

13 Jun 15:43
Compare
Choose a tag to compare

New State object

Previously all the methods in the DSL had a stateSnapshot: YourStateClass parameter, which represented the state machine's current state at the time the DSL method was called. For all non effect methods this parameter is now replaces by a state parameter that looks like this state: State<YourStateClass>. The new State class has a snapshot allowing access to the same value that you received before. It also has .mutate { } (returns the same type as the current state, usually used with copy), .override { } (to transition to another state subclass) and .noChange { } methods to create the ChangeState objects. So instead of doing MutateState { ... } you should now do state.mutate { ... }.

This has a few advantages:

  • State knows about the InputState type so it's not possible anymore to accidentally create MutateState instances with the wrong input type, this is now enforced by the type system, before it would have crashed at runtime
  • it's also not necessary anymore to specify the type parameters for mutate state, the generics are inferred

Lambdas in the DSL

We now recommend to use lambdas instead of method references in the flow redux DSL (e.g. on<ButtonClicked> { action, state -> transitionToSomeState(action, state) } over on(::buttonClicked/on(::transitionToSomeState)) because:

  • Parameters of the reference are required to be there but the compiler warns when they are unused, in a lambda you can just use _ and remove the parameter from the method.
  • The function name should describe what it does (doSomething) but in practice we usually see it being named after the action (e.g. on(::buttonClicked)). The assumption is that if you have on<ButtonClicked> { ... } you are less inclined to call the method buttonClicked as well.
  • An addition to the above is that if you do on(::doSomething) you lose the information of when it happens while on<ButtonClicked> { transitionToSomeState(it) } would make getting an overview easier. Of course you can combine both in your function name but that leads to long/weird names. For example onButtonClickedTransitionToSomeState is long and would then result in on(::on...) while leaving out the on from the method name reads weirdly when looking at just the function.
  • Method references don't work well when the method has a dependency. In practice the function is just put into the state machine class which means it's not testable on its own anymore. While we introduced functional interfaces in [#189].(#189) to make this easier, they are also a lot more verbose. If you just call a method from the lambda you can pass additional parameters to it and it keeps the syntax more aligned.
  • In some circumstances (not sure when it happens) the IDE can't really auto complete the referenced function when you're writing ::...

Other changes

  • Renamed stateMachine DSL method to onEnterStartStateMachine
  • initialStateSupplier is now called whenever the state collection starts #282
  • The initial state in the compose integration is now null #282
  • Don't swallow ClassCastExceptions from the handler #289
  • The state machine will now throw an exception when state is collecting more than once at the same time #308
  • ChangeState.reduce is now public for testing purposes #309

0.12.0

21 Mar 19:00
cafdce4
Compare
Choose a tag to compare

What's Changed

Breaking changes:

  • Removed dsl artifact (and gradle module).FlowReduxStateMachine and all DSL stuff now lives inside flowredux artifact. Change your maven coordintaes from com.freeletics.flowredux:dsl:0.11.0 to com.freeletics.flowredux:flowredux:0.12.0. Package names renamed the same so no breaking change at code level. This is just a breaking change at artifact and packaging level.
  • Removes Logger as we don't need it by @sockeqwe in #273

Fix:

New Contributors

Full Changelog: 0.11.0...0.12.0

0.11.0

23 Nov 17:55
Compare
Choose a tag to compare

New

  • Convenience artefact to work with jetpack compose: FlowReduxStateMachine.rememberStateAndDispatch() #236
val stateMachine = MyFlowReduxStateMachine()

@Composable
fun MyUi(){
  val (state, dispatch) = stateMachine.rememberStateAndDispatch()
  ...
}
  • Overload for sub-statemachine #237