Skip to content

Releases: slackhq/circuit

0.22.1

28 May 23:14
Compare
Choose a tag to compare
  • Fix: Fix rememberRetained implicitly requiring LocalContext where it used to no-op

What's Changed

  • Bump rexml from 3.2.6 to 3.2.8 by @dependabot in #1435
  • Update dependency app.cash.molecule:molecule-runtime to v2 by @slack-oss-bot in #1437
  • Short circuit rememberRetained if the LocalRetainedStateRegistry isn't set by @stagg in #1438

Full Changelog: 0.22.0...0.22.1

0.22.0

28 May 16:21
Compare
Choose a tag to compare
  • Update to Kotlin 2.0.0.
  • Update to KSP 2.0.0-1.0.21.
  • Update Compose Multiplatform to 1.6.10.
  • Switch to the compose compiler shipped with Kotlin.

This release is otherwise identical to 0.21.0, just updated to Kotlin 2.0.

What's Changed

Full Changelog: 0.21.0...0.22.0

0.21.1

28 May 23:13
Compare
Choose a tag to compare
  • Fix: Fix rememberRetained implicitly requiring LocalContext where it used to no-op (#1438)

What's Changed

  • Short circuit rememberRetained if the LocalRetainedStateRegistry isn't set by @stagg in #1438

Full Changelog: 0.21.0...0.21.1

0.21.0

28 May 04:11
Compare
Choose a tag to compare
  • New: Add WASM targets.
  • New: Add FakeNavigator functions to check for the lack of pop/resetRoot events.
  • New: Add FakeNavigator constructor param to add additional screens to the backstack.
  • New: Add support for static UIs. In some cases, a UI may not need a presenter to compute or manage its state. Examples of this include UIs that are stateless or can derive their state from a single static input or an input [Screen]'s properties. In these cases, make your screen implement the StaticScreen interface. When a StaticScreen is used, Circuit will internally allow the UI to run on its own and won't connect it to a presenter if no presenter is provided.
  • New: Add RecordLifecycle and LocalRecordLifecycle composition local, allowing UIs and presenters to observe when they are 'active'. Currently, a record is considered 'active' when it is the top record on the back stack.
  • New: Add a rememberRetainedSaveable variant that participates in both RetainedStateRegistry and SaveableStateRegistry restoration, allowing layered state persistence.
    • The logic is the following upon rememberRetainedSaveable entering composition:
      • consume from both RetainedStateRegistry and SaveableStateRegistry, if available
      • if the retained value is available, use that
      • otherwise, if the saveable restored value is available, use that
      • otherwise, re-initialize the value
    • There is also an overload of rememberRetained that explicitly requires a Saver parameter.
  • Behaviour Change: Presenters are now 'paused' when inactive and replay their last emitted CircuitUiState when they are not active. Presenters can opt-out of this behavior by implementing NonPausablePresenter.
  • Behaviour Change: NavigatorImpl.goTo no longer navigates if the Screen is equal to Navigator.peek().
  • Behaviour Change: Presenter.present is now annotated with @ComposableTarget("presenter"). This helps prevent use of Compose UI in the presentation logic as the compiler will emit a warning if you do. Note this does not appear in the IDE, so it's recommended to use allWarningsAsErrors to fail the build on this event.
  • Behaviour Change: Guard against Navigator.goTo() calls to the same current screen.
  • Change: Navigator.goTo now returns a Bool indicating navigation success.
  • Change: Move iOS GestureNavigationDecoration impl to commonMain and rename to CupertinoGestureNavigationDecoration.
  • Change: Target jvmTarget 1.8 in core libraries.
  • Fix: Fix saveable state being restored when using reset root navigation events.
  • Deprecation: FakeNavigator.assertIsEmpty and expectNoEvents (use the specific event type methods instead)
  • Mark Presenter.Factory as @Stable.
  • Mark Ui.Factory as @Stable.
  • Mark CircuitContext as @Stable.
  • Mark EventListener as @Stable.
  • Mark EventListener.Factory as @Stable.
  • [samples] Improve interop sample significantly.
  • Update Kotlin to 1.9.24.
  • Update KSP to 1.9.24-2.0.20.
  • Update compose-compiler to 1.5.14.
  • Update KotlinPoet to 1.17.0.
  • Update androidx.lifecycle to 2.8.0.
  • Update Molecule to 1.4.3.
  • Update androidx.annotation to 1.8.0.
  • Update kotlinx.coroutines to 1.8.1.
  • Update Compose Multiplatform to 1.6.2.
  • Update Compose UI to 1.6.7.
  • Update Compose Runtime to 1.6.7.
  • Update Compose Animation to 1.6.7.
  • Update Compose Material to 1.6.7.
  • Update androidx.core to 1.13.1.
  • Update androidx.activity to 1.9.0.
  • Update dagger to 2.51.1.
  • Update uuid to 0.8.4.

Special thanks to @chrisbanes, @alexvanyo, @eboudrant, @edenman, and @JustinBis for contributing to this release!

What's Changed

Read more

0.20.0

18 Mar 18:44
Compare
Choose a tag to compare
  • New: Enable RememberObserver to work with rememberRetained.
  • New: Add Navigator.popRoot(). extension (#1274)
  • Behavior change: Add a key to CircuitContent to keep Ui and Presenter consistent. We already did this for presenters, this just makes it consistent for both.
  • [circuitx-android] Implement ToastEffect.
  • Fix: Fix rememberImpressionNavigator() not delegating PopResult.
  • Fix: Navigator - Pass PopResult to onRootPop().
  • Fix: Check canRetainCheck when saving RetainedStateRegistry.
  • Enhancement: Improve error messaging when using assisted inject.
  • Force com.google.guava:listenablefuture to 1.0 to avoid conflicts with Guava.
  • Update compose-compiler to 1.5.10.1.
  • Update coroutines to 1.8.0.
  • Update to Compose Multiplatform 1.6.1.
  • Update Android compose dependencies to 1.6.3.
  • Update molecule to 1.4.1.
  • Update dagger to 2.51.
  • Update turbine to 1.1.0.
  • Update uuid to 0.8.3.
  • Update kotlin to 1.9.23.
  • Update KSP to 1.9.23-1.0.19.

Special thanks to @chrisbanes, @aschulz90, and @alexvanyo for contributing to this release!

What's Changed

New Contributors

Full Changelog: 0.19.1...0.20.0

0.19.1

12 Feb 18:55
Compare
Choose a tag to compare

This is a small bug fix release focused SaveableBackStack consistency and FakeNavigator API improvements.

  • Fix FakeNavigator.awaitNextScreen() not suspending.
  • Fix FakeNavigator.resetRoot() not returning the actual popped screens.
  • Make Navigator.peekBackStack() and Navigator.resetRoot() return ImmutableList.
  • Make BackStack.popUntil() return the ImmutableList of the popped records.
  • Support FakeNavigator.peekBackStack() return the ImmutableList of the popped records.
  • Strongly pop events and resetRoot events in FakeNavigator. This should offer much more information about the events.
  • Use a real BackStack instance in FakeNavigator + allow for specifying a user-provided instance.
  • Require an initial root screen to construct FakeNavigator unless using a custom BackStack.
    • Note this slightly changes semantics, as now the root screen will not be recorded as the first goTo event.
  • Require an initial root screen (or list of screens) for rememberSaveableBackStack().
  • Expose a top-level non-composable Navigator() factory function.

What's Changed

Full Changelog: 0.19.0...0.19.1

0.19.0

09 Feb 17:18
Compare
Choose a tag to compare

What's Changed

Navigation with results

This release introduces support for inter-screen navigation results. This is useful for scenarios where you want to pass data back to the previous screen after a navigation event, such as when a user selects an item from a list and you want to pass the selected item back to the previous screen.

var photoUrl by remember { mutableStateOf<String?>(null) }
val takePhotoNavigator = rememberAnsweringNavigator<TakePhotoScreen.Result>(navigator) { result ->
  photoUrl = result.url
}

// Elsewhere
takePhotoNavigator.goTo(TakePhotoScreen)

// In TakePhotoScreen.kt
data object TakePhotoScreen : Screen {
  @Parcelize
  data class Result(val url: String) : PopResult
}

class TakePhotoPresenter {
  @Composable fun present(): State {
    // ...
    navigator.pop(result = TakePhotoScreen.Result(newFilters))
  }
}

See the new section in the navigation docs for more details, as well as updates to the Overlays docs that help explain when to use an Overlay vs navigating to a Screen with a result.

Support for multiple back stacks

This release introduces support for saving/restoring navigation state on root resets (aka multi back stack). This is useful for scenarios where you want to reset the back stack to a new root but still want to retain the previous back stack's state, such as an app UI that has a persistent bottom navigation bar with different back stacks for each tab.

This works by adding two new optional saveState and restoreState parameters to Navigator.resetRoot().

navigator.resetRoot(HomeNavTab1, saveState = true, restoreState = true)
// User navigates to a details screen
navigator.push(EntityDetails(id = foo))
// Later, user clicks on a bottom navigation item
navigator.resetRoot(HomeNavTab2, saveState = true, restoreState = true)
// Later, user switches back to the first navigation item
navigator.resetRoot(HomeNavTab1, saveState = true, restoreState = true)
// The existing back stack is restored, and EntityDetails(id = foo) will be top of
// the back stack

There are times when saving and restoring the back stack may not be appropriate, so use this feature only when it makes sense. A common example where it probably does not make sense is launching screens which define a UX flow which has a defined completion, such as onboarding.

New Tutorial!

On top of Circuit's existing docs, we've added a new tutorial to help you get started with Circuit. It's a step-by-step guide that walks you through building a simple inbox app using Circuit, intended to serve as a sort of small code lab that one could do in 1-2 hours. Check it out here.

Overlay Improvements

  • New: Promote AlertDialogOverlay, BasicAlertDialogOverlay, and BasicDialogOverlay to circuitx-overlay.
  • New: Add OverlayEffect to circuit-overlay. This offers a simple composable effect to show an overlay and await a result.
    OverlayEffect(state) { host ->
      val result = host.show(AlertDialogOverlay(...))
      // Do something with the result
    }
  • Add OverlayState and LocalOverlayState to circuit-overlay. This allows you to check the current overlay state (UNAVAILABLE, HIDDEN, or SHOWING).
  • Mark OverlayHost as @ReadOnlyOverlayApi to indicate that it's not intended for direct implementation by consumers.
  • Mark Overlay as @Stable.

Misc

  • Make NavEvent.screen public.
  • Change Navigator.popUntil to be exclusive.
  • Add Navigator.peek() to peek the top screen of the back stack.
  • Add Navigator.peekBackStack() to peek the top screen of the back stack.
  • Align spelling of back stack parameters across all APIs to backStack.
  • Refreshed iOS Counter sample using SPM and SKIE.
  • Convert STAR sample to KMP. Starting with Android and Desktop.
  • Fix baseline profiles packaging. Due to a bug in the baseline profile plugin, we were not packaging the baseline profiles in the artifacts. This is now fixed.
  • Mark BackStack.Record as @Stable.
  • Fix an infinite loop in the onRootPop of the Android rememberCircuitNavigator.
  • Update the default decoration to better match the android 34 transitions.
  • Update androidx.lifecycle to 2.7.0.
  • Update to compose multiplatform to 1.5.12.
  • Update to compose to 1.6.1.
  • Update to compose-bom to 2024.02.00.
  • Update compose-compiler to 1.5.9.
  • Update AtomicFu to 0.23.2.
  • Update Anvil to 2.4.9.
  • Update KotlinPoet to 1.16.0.
  • Compile against KSP 1.9.22-1.0.17.

Special thanks to @milis92, @ChrisBanes, and @vulpeszerda for contributing to this release!

New Contributors

Full Changelog: 0.18.2...0.19.0

0.18.2

05 Jan 20:52
Compare
Choose a tag to compare
  • Fix: Fix lifetime of Records' ViewModelStores. This fully fixes #1065.
  • Update Molecule to 1.3.2.
  • Update Jetbrains' compose-compiler to 1.5.7.1.

Special thanks to @dandc87 for contributing to this release!

What's Changed

Full Changelog: 0.18.1...0.18.2

0.18.1

01 Jan 18:34
Compare
Choose a tag to compare

Happy new year!

  • Fix: Fix popped Record's ProvidedValues lifetime. See #1065 for more details.
  • Fix: Fix GestureNavDecoration dropping saveable/retained state on back gestures. See #1089 for more details.

Special thanks to @chrisbanes and @dandc87 for contributing to this release!

What's Changed

  • Update dependency pymdown-extensions to v10.7 by @slack-oss-bot in #1087
  • Fix popped Record's ProvidedValues lifetime by @dandc87 in #1086
  • Merge copies of TestCountPresenter / Ui / Content to new shared module by @chrisbanes in #1088
  • Fix GestureNavDecoration dropping saveable/retained state on back gestures by @chrisbanes in #1089

New Contributors

Full Changelog: 0.18.0...0.18.1

0.18.0

29 Dec 20:52
Compare
Choose a tag to compare
  • New: Support animating an overlay out after returning a result with AnimatedOverlay.
  • Fix: Fix dropping back stack retained state on Android Activity rotations.
  • Enhancement: Add ability to customize ModalBottomSheet appearance in BottomSheetOverlay.
  • Update Kotlin to 1.9.22.
  • Update KSP to 1.9.22-1.0.16.
  • Update Dagger to 2.50.
  • Update kotlinx-collections-immutable to 0.3.7.
  • Update AndroidX Activity to 1.8.2.

Special thanks to @chrisbanes, @chriswiesner, and @bryanstern for contributing to this release!

What's Changed

New Contributors

Full Changelog: 0.17.1...0.18.0