Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
03855a7
compose-jb `1.10.0-alpha03`
stagg Oct 30, 2025
0936ef8
shared element changes
stagg Oct 30, 2025
4db0e3d
use the common `@Preview`
stagg Oct 30, 2025
37701b8
Add `navigationevent`
stagg Oct 30, 2025
48ff104
Make deprecated `BackHandler` work for now
stagg Oct 30, 2025
e9eb275
baseline
stagg Oct 30, 2025
198fd5c
lock files
stagg Oct 30, 2025
b1307cc
Merge branch 'main' into j-compose-110
stagg Oct 31, 2025
da56fd8
lifecycle-jb `2.10.0-alpha03`
stagg Oct 31, 2025
b5d0d6c
Use `withCompositionLocal`
stagg Oct 31, 2025
11828ef
Use `scheduleFrameEndCallback`
stagg Oct 31, 2025
bbeb297
Fix retained values getting dropped early
stagg Oct 31, 2025
ced266f
baseline
stagg Oct 31, 2025
fd4d32a
Update to compose multi-platform 1.10.0-beta01
stagg Nov 4, 2025
f921e81
Specify dependencies via version catalog
stagg Nov 4, 2025
578fa25
Merge branch 'main' into j-compose-110
stagg Nov 4, 2025
14a6e9c
Hot reload is part of the main plugin now
stagg Nov 5, 2025
5335413
Merge branch 'main' into j-compose-110
stagg Nov 6, 2025
181e23e
cleanup hot reload
stagg Nov 7, 2025
af603e6
Revert "Make deprecated `BackHandler` work for now"
stagg Nov 7, 2025
ea02fe9
Use navigation event
stagg Nov 7, 2025
b46d202
baseline
stagg Nov 7, 2025
d3b9eeb
Merge branch 'main' into j-compose-110
stagg Nov 13, 2025
30202cc
roll these back to stable releases
stagg Nov 14, 2025
6c11bb8
corrected material version
stagg Nov 17, 2025
cc9fc4d
Merge branch 'main' into j-compose-110
stagg Nov 21, 2025
25e02c0
1.10.0-beta02
stagg Nov 21, 2025
a6bbed5
Merge remote-tracking branch 'origin/main' into j-compose-110
stagg Nov 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions backstack/dependencies/androidReleaseRuntimeClasspath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ androidx.collection:collection
androidx.compose.runtime:runtime-android
androidx.compose.runtime:runtime-annotation-android
androidx.compose.runtime:runtime-annotation
androidx.compose.runtime:runtime-retain-android
androidx.compose.runtime:runtime-retain
androidx.compose.runtime:runtime-saveable-android
androidx.compose.runtime:runtime-saveable
androidx.compose.runtime:runtime
Expand All @@ -32,12 +34,17 @@ androidx.core:core-ktx
androidx.core:core-viewtree
androidx.core:core
androidx.customview:customview-poolingcontainer
androidx.documentfile:documentfile
androidx.dynamicanimation:dynamicanimation
androidx.emoji2:emoji2
androidx.graphics:graphics-path
androidx.interpolator:interpolator
androidx.legacy:legacy-support-core-utils
androidx.lifecycle:lifecycle-common-jvm
androidx.lifecycle:lifecycle-common
androidx.lifecycle:lifecycle-livedata-core-ktx
androidx.lifecycle:lifecycle-livedata-core
androidx.lifecycle:lifecycle-livedata
androidx.lifecycle:lifecycle-process
androidx.lifecycle:lifecycle-runtime-android
androidx.lifecycle:lifecycle-runtime-compose-android
Expand All @@ -50,6 +57,9 @@ androidx.lifecycle:lifecycle-viewmodel-ktx
androidx.lifecycle:lifecycle-viewmodel-savedstate-android
androidx.lifecycle:lifecycle-viewmodel-savedstate
androidx.lifecycle:lifecycle-viewmodel
androidx.loader:loader
androidx.localbroadcastmanager:localbroadcastmanager
androidx.print:print
androidx.profileinstaller:profileinstaller
androidx.savedstate:savedstate-android
androidx.savedstate:savedstate-compose-android
Expand All @@ -58,7 +68,11 @@ androidx.savedstate:savedstate-ktx
androidx.savedstate:savedstate
androidx.startup:startup-runtime
androidx.tracing:tracing
androidx.transition:transition
androidx.versionedparcelable:versionedparcelable
androidx.window:window-core-android
androidx.window:window-core
androidx.window:window
com.google.guava:listenablefuture
org.jetbrains.androidx.lifecycle:lifecycle-common
org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose
Expand Down
4 changes: 4 additions & 0 deletions backstack/dependencies/jvmRuntimeClasspath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ androidx.collection:collection
androidx.compose.runtime:runtime-annotation-jvm
androidx.compose.runtime:runtime-annotation
androidx.compose.runtime:runtime-desktop
androidx.compose.runtime:runtime-retain-desktop
androidx.compose.runtime:runtime-retain
androidx.compose.runtime:runtime-saveable-desktop
androidx.compose.runtime:runtime-saveable
androidx.compose.runtime:runtime
Expand All @@ -19,6 +21,8 @@ androidx.lifecycle:lifecycle-viewmodel-desktop
androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop
androidx.lifecycle:lifecycle-viewmodel-savedstate
androidx.lifecycle:lifecycle-viewmodel
androidx.navigationevent:navigationevent-desktop
androidx.navigationevent:navigationevent
androidx.savedstate:savedstate-compose-desktop
androidx.savedstate:savedstate-compose
androidx.savedstate:savedstate-desktop
Expand Down
4 changes: 1 addition & 3 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ plugins {
alias(libs.plugins.baselineprofile) apply false
alias(libs.plugins.emulatorWtf) apply false
alias(libs.plugins.binaryCompatibilityValidator)
alias(libs.plugins.compose.hotReload) apply false
}

val ktfmtVersion = libs.versions.ktfmt.get()
Expand Down Expand Up @@ -124,11 +123,10 @@ allprojects {
}

val jvmTargetVersion = libs.versions.jvmTarget
val publishedJvmTargetVersion = libs.versions.publishedJvmTarget

subprojects {
val isPublished = project.hasProperty("POM_ARTIFACT_ID")
val jvmTargetProject = if (isPublished) publishedJvmTargetVersion else jvmTargetVersion
val jvmTargetProject = jvmTargetVersion

pluginManager.withPlugin("java") {
configure<JavaPluginExtension> {
Expand Down
2 changes: 1 addition & 1 deletion circuit-foundation/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ kotlin {
api(projects.circuitRuntimePresenter)
api(projects.circuitRuntimeUi)
api(projects.circuitSharedElements)
implementation(libs.compose.ui.backhandler)
implementation(libs.compose.navigationevent)
}
}
androidMain { dependencies { implementation(libs.androidx.activity.compose) } }
Expand Down
17 changes: 15 additions & 2 deletions circuit-foundation/dependencies/androidReleaseRuntimeClasspath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ androidx.compose.foundation:foundation
androidx.compose.runtime:runtime-android
androidx.compose.runtime:runtime-annotation-android
androidx.compose.runtime:runtime-annotation
androidx.compose.runtime:runtime-retain-android
androidx.compose.runtime:runtime-retain
androidx.compose.runtime:runtime-saveable-android
androidx.compose.runtime:runtime-saveable
androidx.compose.runtime:runtime
Expand All @@ -41,12 +43,17 @@ androidx.core:core-ktx
androidx.core:core-viewtree
androidx.core:core
androidx.customview:customview-poolingcontainer
androidx.documentfile:documentfile
androidx.dynamicanimation:dynamicanimation
androidx.emoji2:emoji2
androidx.graphics:graphics-path
androidx.interpolator:interpolator
androidx.legacy:legacy-support-core-utils
androidx.lifecycle:lifecycle-common-jvm
androidx.lifecycle:lifecycle-common
androidx.lifecycle:lifecycle-livedata-core-ktx
androidx.lifecycle:lifecycle-livedata-core
androidx.lifecycle:lifecycle-livedata
androidx.lifecycle:lifecycle-process
androidx.lifecycle:lifecycle-runtime-android
androidx.lifecycle:lifecycle-runtime-compose-android
Expand All @@ -61,10 +68,13 @@ androidx.lifecycle:lifecycle-viewmodel-ktx
androidx.lifecycle:lifecycle-viewmodel-savedstate-android
androidx.lifecycle:lifecycle-viewmodel-savedstate
androidx.lifecycle:lifecycle-viewmodel
androidx.loader:loader
androidx.localbroadcastmanager:localbroadcastmanager
androidx.navigationevent:navigationevent-android
androidx.navigationevent:navigationevent-compose-android
androidx.navigationevent:navigationevent-compose
androidx.navigationevent:navigationevent
androidx.print:print
androidx.profileinstaller:profileinstaller
androidx.savedstate:savedstate-android
androidx.savedstate:savedstate-compose-android
Expand All @@ -73,14 +83,19 @@ androidx.savedstate:savedstate-ktx
androidx.savedstate:savedstate
androidx.startup:startup-runtime
androidx.tracing:tracing
androidx.transition:transition
androidx.versionedparcelable:versionedparcelable
androidx.window:window-core-android
androidx.window:window-core
androidx.window:window
com.google.guava:listenablefuture
org.jetbrains.androidx.lifecycle:lifecycle-common
org.jetbrains.androidx.lifecycle:lifecycle-runtime-compose
org.jetbrains.androidx.lifecycle:lifecycle-runtime
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel
org.jetbrains.androidx.navigationevent:navigationevent-compose
org.jetbrains.androidx.savedstate:savedstate-compose
org.jetbrains.androidx.savedstate:savedstate
org.jetbrains.compose.animation:animation-core
Expand All @@ -91,8 +106,6 @@ org.jetbrains.compose.foundation:foundation-layout
org.jetbrains.compose.foundation:foundation
org.jetbrains.compose.runtime:runtime-saveable
org.jetbrains.compose.runtime:runtime
org.jetbrains.compose.ui:ui-backhandler-android
org.jetbrains.compose.ui:ui-backhandler
org.jetbrains.compose.ui:ui-geometry
org.jetbrains.compose.ui:ui-graphics
org.jetbrains.compose.ui:ui-text
Expand Down
6 changes: 6 additions & 0 deletions circuit-foundation/dependencies/jvmRuntimeClasspath.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ androidx.collection:collection
androidx.compose.runtime:runtime-annotation-jvm
androidx.compose.runtime:runtime-annotation
androidx.compose.runtime:runtime-desktop
androidx.compose.runtime:runtime-retain-desktop
androidx.compose.runtime:runtime-retain
androidx.compose.runtime:runtime-saveable-desktop
androidx.compose.runtime:runtime-saveable
androidx.compose.runtime:runtime
Expand All @@ -19,6 +21,8 @@ androidx.lifecycle:lifecycle-viewmodel-desktop
androidx.lifecycle:lifecycle-viewmodel-savedstate-desktop
androidx.lifecycle:lifecycle-viewmodel-savedstate
androidx.lifecycle:lifecycle-viewmodel
androidx.navigationevent:navigationevent-desktop
androidx.navigationevent:navigationevent
androidx.savedstate:savedstate-compose-desktop
androidx.savedstate:savedstate-compose
androidx.savedstate:savedstate-desktop
Expand All @@ -31,6 +35,8 @@ org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose-desktop
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-compose
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel-savedstate
org.jetbrains.androidx.lifecycle:lifecycle-viewmodel
org.jetbrains.androidx.navigationevent:navigationevent-compose-desktop
org.jetbrains.androidx.navigationevent:navigationevent-compose
org.jetbrains.androidx.savedstate:savedstate-compose-desktop
org.jetbrains.androidx.savedstate:savedstate-compose
org.jetbrains.androidx.savedstate:savedstate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,17 @@ import androidx.activity.ComponentActivity
import androidx.activity.OnBackPressedCallback
import androidx.activity.compose.LocalOnBackPressedDispatcherOwner
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.backhandler.BackHandler
import androidx.compose.ui.test.assertTextEquals
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.navigationevent.NavigationEventInfo
import androidx.navigationevent.compose.NavigationBackHandler
import androidx.navigationevent.compose.rememberNavigationEventState
import com.slack.circuit.backstack.rememberSaveableBackStack
import com.slack.circuit.internal.test.TestContentTags.TAG_GO_NEXT
import com.slack.circuit.internal.test.TestContentTags.TAG_LABEL
Expand Down Expand Up @@ -76,11 +81,13 @@ class NavigatorBackHandlerTest {
@Test
fun nestedAndroidNavigatorRootPopBackHandler() {
val circuit = createTestCircuit(rememberType = TestCountPresenter.RememberType.Standard)
var outerBackCount = 0
var outerBackCount by mutableStateOf(0)
lateinit var navigator: Navigator
composeTestRule.setContent {
CircuitCompositionLocals(circuit) {
BackHandler(enabled = true) { outerBackCount++ }
NavigationBackHandler(state = rememberNavigationEventState(NavigationEventInfo.None)) {
outerBackCount++
}
val backStack = rememberSaveableBackStack(TestScreen.ScreenA)
navigator = rememberCircuitNavigator(backStack = backStack)
NavigableCircuitContent(navigator = navigator, backStack = backStack)
Expand All @@ -104,11 +111,13 @@ class NavigatorBackHandlerTest {
@Test
fun nestedAndroidNavigatorRootDispatchedBackHandler() {
val circuit = createTestCircuit(rememberType = TestCountPresenter.RememberType.Standard)
var outerBackCount = 0
var outerBackCount by mutableStateOf(0)
lateinit var navigator: Navigator
composeTestRule.setContent {
CircuitCompositionLocals(circuit) {
BackHandler(enabled = true) { outerBackCount++ }
NavigationBackHandler(state = rememberNavigationEventState(NavigationEventInfo.None)) {
outerBackCount++
}
val backStack = rememberSaveableBackStack(TestScreen.ScreenA)
navigator = rememberCircuitNavigator(backStack = backStack)
NavigableCircuitContent(navigator = navigator, backStack = backStack)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.ProvidableCompositionLocal
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.Stable
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.currentCompositeKeyHashCode
Expand Down Expand Up @@ -445,9 +446,8 @@ public class ContentProviderState<R : Record>(
private fun <R : Record> createRecordContent(onActive: () -> Unit, onDispose: () -> Unit) =
movableContentOf<R, ContentProviderState<R>> { record, contentProviderState ->
with(contentProviderState) {
val lifecycle =
remember { MutableRecordLifecycle() }
.apply { isActive = lastNavigator.backStack.topRecord == record }
val lifecycle = remember { MutableRecordLifecycle() }
SideEffect { lifecycle.isActive = lastNavigator.backStack.topRecord == record }
saveableStateHolder.SaveableStateProvider(record.registryKey) {
// Provides a RetainedStateRegistry that is maintained independently for each record while
// the record exists in the back stack.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshots.Snapshot
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.backhandler.BackHandler
import androidx.navigationevent.NavigationEventInfo
import androidx.navigationevent.compose.NavigationBackHandler
import androidx.navigationevent.compose.rememberNavigationEventState
import com.slack.circuit.backstack.BackStack
import com.slack.circuit.backstack.BackStack.Record
import com.slack.circuit.backstack.isAtRoot
Expand Down Expand Up @@ -43,7 +45,7 @@ public fun rememberCircuitNavigator(

/**
* Returns a new [Navigator] for navigating within [CircuitContents][CircuitContent] while also
* handling back events with a [BackHandler].
* handling back events with a [NavigationBackHandler].
*
* @param backStack The backing [BackStack] to navigate.
* @param onRootPop Invoked when the backstack is at root (size 1) and the user presses the back
Expand Down Expand Up @@ -74,9 +76,10 @@ public fun rememberCircuitNavigator(
}
var hasPendingRootPop by remember(hasScreenChanged) { mutableStateOf(false) }
var enableRootBackHandler by remember(hasScreenChanged) { mutableStateOf(true) }
BackHandler(
enabled = enableBackHandler && enableRootBackHandler && backStack.size > 1,
onBack = {
NavigationBackHandler(
state = rememberNavigationEventState(NavigationEventInfo.None),
isBackEnabled = enableBackHandler && enableRootBackHandler && backStack.size > 1,
onBackCompleted = {
// We need to unload this BackHandler from the composition before the root pop is triggered so
// any outer back handler will get called. So delay calling pop until after the next
// composition.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.key
import androidx.compose.runtime.remember
import com.slack.circuit.foundation.internal.withCompositionLocalProvider
import androidx.compose.runtime.withCompositionLocal
import com.slack.circuit.retained.CanRetainChecker
import com.slack.circuit.retained.LocalRetainedStateRegistry
import com.slack.circuit.retained.RetainedStateRegistry
Expand Down Expand Up @@ -40,24 +40,19 @@ private class RetainedStateHolderImpl(private var canRetainChecker: CanRetainChe

@Composable
override fun <T> RetainedStateProvider(key: String, content: @Composable (() -> T)): T {
return withCompositionLocalProvider(LocalRetainedStateRegistry provides registry) {
return withCompositionLocal(LocalRetainedStateRegistry provides registry) {
key(key) {
val entryCanRetainChecker = remember { EntryCanRetainChecker() }
val childRegistry =
rememberRetainedStateRegistry(key = key, canRetainChecker = entryCanRetainChecker)
withCompositionLocalProvider(
LocalRetainedStateRegistry provides childRegistry,
content = content,
)
.also {
DisposableEffect(Unit) {
entryCheckers[key] = entryCanRetainChecker
onDispose {
registry.saveValue(key)
entryCheckers -= key
}
}
DisposableEffect(Unit) {
entryCheckers[key] = entryCanRetainChecker
onDispose {
registry.saveValue(key)
entryCheckers -= key
}
}
withCompositionLocal(LocalRetainedStateRegistry provides childRegistry, content = content)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import androidx.compose.runtime.saveable.LocalSaveableStateRegistry
import androidx.compose.runtime.saveable.SaveableStateRegistry
import androidx.compose.runtime.saveable.Saver
import androidx.compose.runtime.saveable.rememberSaveable
import com.slack.circuit.foundation.internal.withCompositionLocalProvider
import androidx.compose.runtime.withCompositionLocal

/**
* This is a copy of [androidx.compose.runtime.saveable.SaveableStateHolder], tweaked so that
Expand Down Expand Up @@ -53,7 +53,7 @@ private class SaveableStateHolderImpl(
}

val result =
withCompositionLocalProvider(
withCompositionLocal(
LocalSaveableStateRegistry provides registryHolder.registry,
content = content,
)
Expand Down
Loading