From 6d289e939d8e317ffd74ea6bfef94ffe6b0734a0 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 14 Jan 2024 04:16:59 -0300 Subject: [PATCH] feat: compose pop result support --- .../routing/compose/ComposeRoutingExt.kt | 22 ++++++++++- .../compose/ComposeRoutingPopResult.kt | 11 ++++++ .../routing/compose/ComposeRoutingTest.kt | 37 +++++++++++++++++++ 3 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 compose/common/src/dev/programadorthi/routing/compose/ComposeRoutingPopResult.kt diff --git a/compose/common/src/dev/programadorthi/routing/compose/ComposeRoutingExt.kt b/compose/common/src/dev/programadorthi/routing/compose/ComposeRoutingExt.kt index c9fc493..b0f5aff 100644 --- a/compose/common/src/dev/programadorthi/routing/compose/ComposeRoutingExt.kt +++ b/compose/common/src/dev/programadorthi/routing/compose/ComposeRoutingExt.kt @@ -1,10 +1,28 @@ package dev.programadorthi.routing.compose +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.ProvidableCompositionLocal +import androidx.compose.runtime.staticCompositionLocalOf import dev.programadorthi.routing.core.Routing +public val LocalPopResult: ProvidableCompositionLocal = + staticCompositionLocalOf { null } + public fun Routing.canPop(): Boolean = contentList.size > 1 -public fun Routing.pop() { +public fun Routing.pop(result: Any? = null) { contentList.removeLastOrNull() - // TODO: add support to send result + if (result == null) return + + val lastIndex = contentList.lastIndex + if (lastIndex < 0) return + + val lastContent = contentList[lastIndex] + val popResult = ComposeRoutingPopResult(content = result) + + contentList[lastIndex] = { + CompositionLocalProvider(LocalPopResult provides popResult) { + lastContent() + } + } } diff --git a/compose/common/src/dev/programadorthi/routing/compose/ComposeRoutingPopResult.kt b/compose/common/src/dev/programadorthi/routing/compose/ComposeRoutingPopResult.kt new file mode 100644 index 0000000..df692fb --- /dev/null +++ b/compose/common/src/dev/programadorthi/routing/compose/ComposeRoutingPopResult.kt @@ -0,0 +1,11 @@ +package dev.programadorthi.routing.compose + +/** + * Add support to a previous [androidx.compose.runtime.Composable] get the popped result + */ +@Suppress("UNCHECKED_CAST") +public class ComposeRoutingPopResult internal constructor( + internal val content: Any? = null, +) { + public fun result(): T? = content as? T +} diff --git a/compose/common/test/dev/programadorthi/routing/compose/ComposeRoutingTest.kt b/compose/common/test/dev/programadorthi/routing/compose/ComposeRoutingTest.kt index e7bad5c..68b7100 100644 --- a/compose/common/test/dev/programadorthi/routing/compose/ComposeRoutingTest.kt +++ b/compose/common/test/dev/programadorthi/routing/compose/ComposeRoutingTest.kt @@ -320,4 +320,41 @@ internal class ComposeRoutingTest { // THEN assertEquals(3, composedCounter) } + + @Test + fun shouldPopAComposableWithResult() = + runComposeTest { coroutineContext, composition, clock -> + // GIVEN + var poppedMessage: String? = null + + val routing = + routing(parentCoroutineContext = coroutineContext) { + composable(path = "/push") { + poppedMessage = LocalPopResult.current?.result() + } + } + + composition.setContent { + Routing( + routing = routing, + initial = {}, + ) + } + + // WHEN + routing.push(path = "/push") + advanceTimeBy(99) // Ask for routing + clock.sendFrame(0L) // Ask for recomposition + + routing.push(path = "/push") + advanceTimeBy(99) // Ask for routing + clock.sendFrame(0L) // Ask for recomposition + + routing.pop(result = "This is the popped message") + advanceTimeBy(99) // Ask for routing + clock.sendFrame(0L) // Ask for recomposition + + // THEN + assertEquals("This is the popped message", poppedMessage) + } }