diff --git a/redwood-treehouse-guest/src/commonMain/kotlin/app/cash/redwood/treehouse/treehouseCompose.kt b/redwood-treehouse-guest/src/commonMain/kotlin/app/cash/redwood/treehouse/treehouseCompose.kt
index fd8c0f70e8..6362452ebc 100644
--- a/redwood-treehouse-guest/src/commonMain/kotlin/app/cash/redwood/treehouse/treehouseCompose.kt
+++ b/redwood-treehouse-guest/src/commonMain/kotlin/app/cash/redwood/treehouse/treehouseCompose.kt
@@ -27,6 +27,7 @@ import app.cash.redwood.ui.OnBackPressedDispatcher
import app.cash.redwood.ui.UiConfiguration
import app.cash.zipline.ZiplineScope
import app.cash.zipline.ZiplineScoped
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.plus
@@ -135,15 +136,21 @@ private fun ZiplineTreehouseUi.Host.asOnBackPressedDispatcher() = object : OnBac
}
private fun OnBackPressedCallback.asService() = object : OnBackPressedCallbackService {
- override var isEnabled: Boolean
- get() = this@asService.isEnabled
- set(value) {
- this@asService.isEnabled = value
+ override val isEnabled = MutableStateFlow(this@asService.isEnabled)
+
+ init {
+ enabledChangedCallback = {
+ isEnabled.value = this@asService.isEnabled
}
+ }
override fun handleOnBackPressed() {
this@asService.handleOnBackPressed()
}
+
+ override fun close() {
+ enabledChangedCallback = null
+ }
}
private object NullOnBackPressedDispatcherService : OnBackPressedDispatcherService {
diff --git a/redwood-treehouse-host-composeui/src/androidMain/kotlin/app/cash/redwood/treehouse/composeui/TreehouseContent.android.kt b/redwood-treehouse-host-composeui/src/androidMain/kotlin/app/cash/redwood/treehouse/composeui/TreehouseContent.android.kt
index f97857b813..0447918aca 100644
--- a/redwood-treehouse-host-composeui/src/androidMain/kotlin/app/cash/redwood/treehouse/composeui/TreehouseContent.android.kt
+++ b/redwood-treehouse-host-composeui/src/androidMain/kotlin/app/cash/redwood/treehouse/composeui/TreehouseContent.android.kt
@@ -30,9 +30,13 @@ internal actual fun platformOnBackPressedDispatcher(): RedwoodOnBackPressedDispa
object : RedwoodOnBackPressedDispatcher {
override fun addCallback(onBackPressedCallback: RedwoodOnBackPressedCallback): Cancellable {
val androidOnBackPressedCallback = onBackPressedCallback.toAndroid()
+ onBackPressedCallback.enabledChangedCallback = {
+ androidOnBackPressedCallback.isEnabled = onBackPressedCallback.isEnabled
+ }
delegate.addCallback(androidOnBackPressedCallback)
return object : Cancellable {
override fun cancel() {
+ onBackPressedCallback.enabledChangedCallback = null
androidOnBackPressedCallback.remove()
}
}
diff --git a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt
index 5b53a080c6..d3426461f7 100644
--- a/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt
+++ b/redwood-treehouse-host/src/commonMain/kotlin/app/cash/redwood/treehouse/TreehouseAppContent.kt
@@ -35,6 +35,7 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.job
import kotlinx.coroutines.launch
+import kotlinx.coroutines.suspendCancellableCoroutine
private class State(
val viewState: ViewState,
@@ -457,20 +458,29 @@ private class ViewContentCodeBinding(
onBackPressedCallbackService: OnBackPressedCallbackService,
): CancellableService {
dispatchers.checkZipline()
- val cancellable = onBackPressedDispatcher.addCallback(
- object : OnBackPressedCallback(onBackPressedCallbackService.isEnabled) {
+ val cancellableJob = bindingScope.launch(dispatchers.zipline) {
+ val onBackPressedCallback = object : OnBackPressedCallback(onBackPressedCallbackService.isEnabled.value) {
override fun handleOnBackPressed() {
bindingScope.launch(dispatchers.zipline) {
onBackPressedCallbackService.handleOnBackPressed()
}
}
- },
- )
+ }
+ val cancellable = onBackPressedDispatcher.addCallback(onBackPressedCallback)
+ launch {
+ onBackPressedCallbackService.isEnabled.collect {
+ onBackPressedCallback.isEnabled = it
+ }
+ }
+ suspendCancellableCoroutine { continuation ->
+ continuation.invokeOnCancellation { cancellable.cancel() }
+ }
+ }
return object : CancellableService {
override fun cancel() {
dispatchers.checkZipline()
- cancellable.cancel()
+ cancellableJob.cancel()
}
override fun close() {
diff --git a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeZiplineTreehouseUi.kt b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeZiplineTreehouseUi.kt
index 1374f87895..d30a1dd968 100644
--- a/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeZiplineTreehouseUi.kt
+++ b/redwood-treehouse-host/src/commonTest/kotlin/app/cash/redwood/treehouse/FakeZiplineTreehouseUi.kt
@@ -24,6 +24,7 @@ import app.cash.redwood.protocol.PropertyChange
import app.cash.redwood.protocol.PropertyTag
import app.cash.redwood.protocol.WidgetTag
import app.cash.redwood.ui.UiConfiguration
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.serialization.json.JsonPrimitive
@@ -62,7 +63,7 @@ class FakeZiplineTreehouseUi(
fun addBackHandler(isEnabled: Boolean): CancellableService {
val result = host.addOnBackPressedCallback(object : OnBackPressedCallbackService {
- override var isEnabled = isEnabled
+ override var isEnabled = MutableStateFlow(isEnabled)
override fun handleOnBackPressed() {
eventLog += "$name.onBackPressed()"
diff --git a/redwood-treehouse/api/zipline-api.toml b/redwood-treehouse/api/zipline-api.toml
index 8e26976876..f7a206b5aa 100644
--- a/redwood-treehouse/api/zipline-api.toml
+++ b/redwood-treehouse/api/zipline-api.toml
@@ -69,8 +69,8 @@ functions = [
# fun handleOnBackPressed(): kotlin.Unit
"NjIN59uX",
- # var isEnabled: kotlin.Boolean
- "yKh+yo1c",
+ # val isEnabled: kotlinx.coroutines.flow.StateFlow
+ "TAJYS/cz",
]
[app.cash.redwood.treehouse.OnBackPressedDispatcherService]
diff --git a/redwood-treehouse/src/commonMain/kotlin/app/cash/redwood/treehouse/OnBackPressedCallbackService.kt b/redwood-treehouse/src/commonMain/kotlin/app/cash/redwood/treehouse/OnBackPressedCallbackService.kt
index a29dd52b76..d802917de2 100644
--- a/redwood-treehouse/src/commonMain/kotlin/app/cash/redwood/treehouse/OnBackPressedCallbackService.kt
+++ b/redwood-treehouse/src/commonMain/kotlin/app/cash/redwood/treehouse/OnBackPressedCallbackService.kt
@@ -18,11 +18,12 @@ package app.cash.redwood.treehouse
import app.cash.redwood.ui.OnBackPressedCallback
import app.cash.zipline.ZiplineService
import kotlin.native.ObjCName
+import kotlinx.coroutines.flow.StateFlow
/** Redwood's [OnBackPressedCallback] but implementing [ZiplineService]. */
@ObjCName("OnBackPressedCallbackService", exact = true)
public interface OnBackPressedCallbackService : ZiplineService {
- public var isEnabled: Boolean
+ public val isEnabled: StateFlow
public fun handleOnBackPressed()
}