Releases: respawn-app/FlowMVI
Releases · respawn-app/FlowMVI
3.0.0 🚀
🧨 Breaking changes
🚨 Behavior change - the number of subscribers that onSubscribe
receives has been changed from previous to current. I.e. onSubscribe
will now get a number bigger by one. Please manually check each usage of onSubscribe
in the project right after you update. 🚨
- Compile-time error:
JobManager
is now a generic class, which means expressionval jobs = manageJobs()
requires a type argument now. To fix, simply provide the return type expicitly:val jobs: JobManager<Jobs> = manageJobs()
- Removed deprecated
android-compose
artifact. You can now just usecompose
which is multiplatform. - Merged android-view and android artifacts - please remove
android-view
- Store will now check if it has been launched before it is subscribed to. This will result in an exception if not. Opt-out of this behavior using
allowIdleSubscriptions = true
. This check will not be run whendebuggable = false
- Verify each method of store plugin builder is only called once. The plugin builder will now throw if you attempt to invoke a given callback multiple times. For example,
onStart { } ; onStart { }
will now throw
🚀 New Features
- Compose and lifecycle support is now multiplatform! With
androidx.lifecycle
being multiplatform, the library automatically uses system lifecycle to subscribe to the store.- However, if you are using a navigation library with a custom lifecycle support, such as Decompose, you can pass the lifecycle as a composition local (using the essenty integration) or manually as a function parameter.
- Remote Debugging! A new module family
debugger-*
allows to debug your stores remotely, with a dedicated app provided for Linux, MacOS, Windows. - Essenty Integration! Two new modules:
essenty
andessenty-compose
provide integration with Decompose and Essenty libraries, including lifecycle, retained instances and saved state. Essenty setup explained in docs - Wasm and JS support for all modules.
saveStatePlugin
will persist the state to local storage on browser targets by default - New flag
atomicStateUpdates
in store builders allows disabling serialization / atomicity of state transactions if that is not needed, improving performance.true
by default - Stores now have
StoreLogger
parameter which- can be overridden and decorated
- is available in the store's code and plugins
- fully multiplatform and automatic
You can set or remove the store logger using theconfigure
block. If a value is not set, then ifdebuggable
is true, a platform logger will be used, and iffalse
, no-op logger will.
- Added a new "queue" property for Undo/Redo to observe changes to the queue
- Implemented a new multiplatform sample app for Wasm, Android, Desktop and iOS to showcase main features, integration with decompose, DI setup and lifecycle setup.
savedStatePlugin
now provides logging informationserializeState
plugin now has a default Json instance provided. Using it is recommended if your json instance is not lenient enough to ignore schema changes.- Library performance was optimized to reduce object allocation, lambda creation and function indirection. With k2, lambdas which are extensively used in the library should become more performant. Also optimizations were made to the subscription lifecycle handling to make it faster & more reliable.
- Implemented a new Lazy Plugin DSL where plugin will now have access to the store configuration that installs it and that will be built at the store creation time, not at the property instantiation time.
- This Lazy DSL replaces the old
lazyPlugin
function. - Convert an existing plugin into a lazy one to get access to the config by calling
LazyPlugin { config -> }
- Create a lazy plugin using
lazyPlugin
builder function and use theconfig
property StoreConfiguration
is now also available fromPipelineContext
, so you can invoke logging calls and determine if the store is debuggable
- This Lazy DSL replaces the old
🐞 Bug fixes
- Fixed file name for
serializeState
function using store name instead of actual name - Fix
Saver
s handling cancellation exceptions - Added a missing overload of Time Travel that would create and return the object for the user
- Store will now not print logs when the state has not changed (stayed the same)
- Fixed race with concurrent subscriptions to the store where job was relaunched too many times
- Fixed store builder allowing to install 0 plugins
- Synchronize disallowRestart plugin operations
- Ensured subscription events are always sent and processed. This should fix rare bugs where the number of subscribers was quickly conflated to the same value sometimes.
- Fixed issues where store configuration was accessible and changeable from plugins and from callbacks. This will now not compile instead of silently failing.
- Disallowed nested plugin callback invocation e.g.
onStart { onStart { } }
📚 Docs
- Project Icon, banner, and star history
- Documentation on prebuilt plugins
- Docs on lazy plugins
- Docs for store configuration parameters
- Docs on remote debugger setup
- Expanded FAQ
- Docs for essenty integration
⭐️ Deprecations
- Deprecated
parentStorePlugin
in favor of a simplestore.collect
suspending function. It's much more flexible and allows to merge the incoming state with other data sources - Deprecated
platformLoggingPlugin
,nativeLoggingPlugin
,consoleLoggingPlugin
,logcatLoggingPlugin
as a defaultloggingPlugin
now uses store logger by default - Deprecated parameters of
savedStatePlugin
which were accepting a file and a directory, because on wasm targets local storage is used. A new overload that takes apath
is now used. - New
configure { }
block DSL replaced the old store configuration properties. You can no longer access store configuration in the store builder. This change was made to ensure users do not access store configuration before it's actually created, because while the store is being built, the configuration may change. This will also prevent users from changing the store configuration inside the plugins, which makes no sense as the configuration is not valid anymore. - Many default parameters were removed from multiple plugins because those parameters are now obtained from the Store configuration using Lazy Plugin DSL. This includes logger, debugger, save state and some other plugins. Only non-mandatory parameters were removed. You can safely remove them as well.
Changes since 2.5.0-alpha12
Features
- un-deprecate overloads of
subscribe
where the lifecycle is not provided explicitly - deprecate
useState
and rename toupdateStateImmediate
with auto-replace - change the return value of
onSubscribe
to return the new subscriber count - Kotlin 2.0, compose 1.6.10
- allow overriding name and logger for the logging plugin
- update docs for v3.0
Bug fixes
- Bring back stateProvider under a deprecation message to reduce migration complexity
- Bring back removed logging plugin as it was removed too early
- Bring back removed nameByType temporarily to reduce migration complexity
2.5.0-alpha12
Breaking Changes
- Verify each method of store plugin builder is only called once, reduce lambda allocations. The plugin builder will now throw if you attempt to invoke a given callback multiple times. For example,
onStart { } ; onStart { }
- Disallowed nested invocation of plugin builder callbacks. Previously it was possible to call
onStart { onStart { } }
. Now such usages will fail at compilation time because the second invocation will never be executed.
New Features
- Add lazy thread-safety mode to lazy store builder functions
- Make
UnrecoverableException
open - Warn about possible component context leak when using essenty DSL.
- Implement StateKeeper integration for essenty. You can now invoke
keepState
orinstall(keepStatePlugin())
to persist the state using EssentyStateKeeper
- Implement subscription DSL for components in the essenty integration. You can now subscribe in the components.
- Add dsl to create retained stores using container factory
Docs:
- Update decompose sample feature to follow the new essenty api
Bug Fixes
- fix await subscribers condition for completing the wait period
- fix storeBuilder vararg plugin installation order
Other
- Change sample code theme to Atom One
2.5.0-alpha11
Breaking Changes
- New
configure { }
block DSL replaced the old store configuration properties. You can no longer access store configuration in the store builder. This change was made to ensure users do not access store configuration before it's actually created, because while the store is being built, the configuration may change. Old properties were deprecated. This will also prevent users from changing the store configuration inside the plugins, which makes no sense as the configuration will not change at this point. - JobManager plugin will now accept generic parameters. Your code won't compile if you previously did not provide those. Please declare the type explicitly:
val jobs: JobManager<String> = manageJobs()
- #51: Store will now check if it has been launched before it is subscribed to. This will result in an exception if not. Opt-out of this behavior using
allowIdleSubscriptions = true
. This check will not be run whendebuggable = false
- Many default parameters were removed from multiple plugins because those parameters are now obtained from the Store configuration using Lazy Plugin DSL. This includes logger, debugger, save state and some other plugins. Only non-mandatory parameters were removed. You can safely remove them as well.
- Removed deprecated:
consoleLogging
,parentStore
,savedState
,nativeLogging
,androidLogging
plugins
New Features
- Implemented a new Lazy Plugin DSL where plugin will now have access to the store configuration that installs it and that will be built at the store creation time, not at the property instantiation time. This Lazy DSL replaces the old
lazyPlugin
function.- Convert an existing plugin into a lazy one to get access to the config by calling
LazyPlugin { config -> }
- Create a lazy plugin using
lazyPlugin
and use the config property
- Convert an existing plugin into a lazy one to get access to the config by calling
- Ensured subscription events are always sent and processed. This should fix rare bugs where the number of subscribers was quickly conflated to the same value sometimes.
- Added automatic logging to plugin test dsl
- Added StoreConfiguration to pipeline context
- Do not require name for the store in Essenty DSL
- Added return value to AwaitSubscribers plugin - it will now return the
SubscriberManager
- Implemented two-pane layout for sample app
- Sample app will now be uploaded for desktop with GH Actions
Bug Fixes
- Store will now not print logs when the state has not changed (stayed the same)
- Fixed race with concurrent subscriptions to the store where job was relaunched too many times
- Fixed store builder allowing to install 0 plugins
- Use generic iterable for composite plugin
- Fixed bug report template layout
- Fixed some outdated documentation
- Use immediate dispatcher on native store
- Store Builder plugins are now thread-safe when creating
- Synchronize disallowRestart plugin operations
- Add queue size parameter to time travel plugin
Docs
- Updated docs for v3.0, adding lazy plugin and configure block sections
- Split documentation into better sections with dedicated pages for android, compose
- Added lazy plugin explanation to docs
- Added documentation on prebuilt plugins, explaining how, when and for what to use them
Other
- Inline reentrant lock calls
- Add some more inlines to state update functions
- Provide coroutine scope to plugin test dsl
- Fixed flaky tests, add tests for while subscribed plugin
- Internal cleanup of store code
- Added toString to plugin test scope
- Made store configuration a public class
- Compose Multiplatform 1.6.10-beta02
2.5.0-alpha08
- Fixed saved state module for wasm and js targets not being able to persist the state. Browser targets do not support saving state to files, so the plugin will save the state to local storage instead.
- Added
LoggingSaver
that logs save and restore operations to a StoreLogger - Added logging to default saved state plugin
- Replaced old dsl for serializeState with one that takes a path directly to support non-file saving. Previous dsl is available on non-browser targets, but deprecated in favor of the simpler approach above
- Added a default Json instance as an argument to the
serializeState
plugin so that clients can omit providing their own Json. The default instance is lenient to reduce number of failed restorations when the schema changes. - Cleanup of automatic naming logic for some plugins to avoid issues when code is obfuscated.
- Default file name for state is now the serial name of the class being saved for serializeState
- Added ability to select code in the sample app
- Fixed sample app layout issues
- Deployed wasm sample app to the website
2.5.0-alpha07
- Implemented a new multiplatform sample app for wasm and Android (upcoming desktop and iOS) to showcase main features, integration with decompose, DI setup and lifecycle setup.
- Added a new "queue" property for Undo/Redo to observe changes to the queue
2.5.0-alpha06
- Fix essenty-compose depending on androidx libraries
- Kotlin 1.9.23
- Compose 1.5.10, jetbrains compose 1.6.1
2.5.0-alpha05
- Remember store lifecycle instances to prevent unnecessary recompositions where the value of the lifecycle changes.
2.5.0-alpha04
- Another attempt at fixing Android module aar publication
- Fixed an issue where store would resubscribe on each state change due to
SubscriberLifecycle
not implementing hashcode/equals - Updated readme
Full Changelog: 2.5.0-alpha03...2.5.0-alpha04
2.5.0-alpha03
- Fixed
android-*
artifact publication. The previous version did not contain proper jars for those artifacts - Removed deprecated
android-compose
artifact. You can now just usecompose
- Merged
android-view
andandroid
artifacts - Remove some unnecessary dependencies from
compose
artifact
Full Changelog: 2.5.0-alpha02...2.5.0-alpha03
2.5.0-alpha02
New Features:
- Remote Debugging! A new module family
debugger-*
allows to debug your stores remotely, with a dedicated app provided for Linux, MacOS, Windows. Also, the debugger app is implemented usingFlowMVI
and can be used as a sample app. Debugger setup explained in docs. - Essenty Integration! Two new modules:
essenty
andessenty-compose
provide integration with Decompose and Essenty libraries. Essenty setup explained in docs - New Lifecycle Implementation for store subscription in Compose. The Compose module now provides an interface
SubscriberLifecycle
that has to be provided to thesubscribe
function to subscribe to the store. It also allows integration with Platform lifecycle (when it is made multiplatform) and Essenty lifecycle. - Refactoring of StoreLogging allowed to provide a more robust logging code on all supported platforms. You can now provide your own
StoreLogger
implementation or use the platform one as before. - Wasm support for core, test and compose modules! Also enables missing
js
support for compose module. - Compose 1.6.3
- New flag
atomicStateUpdates
in store builders allows disabling serialization / atomicity of state updates if that is not needed, improving performance.true
by default - Project Icon, banner, and star history
- New overload of
store.subscribe()
that does not require a scope ( awith()
call)
Bug Fixes:
- Fixed file name for
serializeState
function using store name - Fix
Saver
s handling cancellation exceptions - Added a missing overload of
timeTravel
that would create and return the object for the user
Breaking Changes:
- Compose's
subscribe
function now requires the consumer to pass a lifecycle to it as a parameter on all platforms where lifecycle is not supported to prevent the user from mistakenly subscribing to the store without using a properlifecycle
. Lifecycle implementations can be custom, provided via a composition local, or used from an integration module. To maintain a previous behavior on non-Android platforms, pass aDefaultLifecycle
as a parameter to thesubscribe
function. Android users don't have this breaking change. - Store implementations now require a hashcode/equals contract
- When store has actions disabled, it will now throw an
UnrecoverableException
to fail faster and avoid recover plugins - Deprecated
parentStorePlugin
in favor of a simplestore.collect
suspending function. It's much more flexible and allows to merge the incoming state with other data sources - Deprecated
platformLoggingPlugin
as a defaultloggingPlugin
now uses a platform logger by default
What's Changed
- 2.5.0 by @Nek-12 in #40
- 2.5.0-alpha02 by @Nek-12 in #41
Full Changelog: 2.4.1...2.5.0-alpha02