From 60eb43fde7201b76bd465bda1297fcd50049c89d Mon Sep 17 00:00:00 2001 From: andreykovalev Date: Mon, 2 Oct 2023 11:43:52 +0100 Subject: [PATCH] Mention breaking change in the CHANGELOG.md and allow to add keys to PermanentNavModel later --- CHANGELOG.md | 2 +- .../appyx/core/node/PermanentChildTest.kt | 7 +++++ .../appyx/core/composable/PermanentChild.kt | 26 ++++++++++++------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a956fcef..aec6143e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Pending changes -- [#606](https://github.com/bumble-tech/appyx/pull/606) – **Fixed**: Do not create permanentNavModel inside ParentNode. Provide it via constructor to ParentNode +- [#606](https://github.com/bumble-tech/appyx/pull/606) – **Breaking change**: Do not create permanentNavModel inside ParentNode. Provide it via constructor to ParentNode --- diff --git a/libraries/core/src/androidTest/kotlin/com/bumble/appyx/core/node/PermanentChildTest.kt b/libraries/core/src/androidTest/kotlin/com/bumble/appyx/core/node/PermanentChildTest.kt index b9997e791..de13158bb 100644 --- a/libraries/core/src/androidTest/kotlin/com/bumble/appyx/core/node/PermanentChildTest.kt +++ b/libraries/core/src/androidTest/kotlin/com/bumble/appyx/core/node/PermanentChildTest.kt @@ -38,6 +38,13 @@ class PermanentChildTest { rule.onNode(hasTestTag(TestParentNode.NavTarget::class.java.name)).assertExists() } + @Test + fun `WHEN_permanent_model_does_not_contain_relevant_nav_key_THEN_permanent_child_is_not_rendered`() { + rule.start() + + rule.onNode(hasTestTag(TestParentNode.NavTarget::class.java.name)).assertDoesNotExist() + } + @Test fun `WHEN_visibility_switched_THEN_permanent_child_is_reused`() { createPermanentNavModelWithNavKey() diff --git a/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/PermanentChild.kt b/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/PermanentChild.kt index a572ef6ed..0b809f23a 100644 --- a/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/PermanentChild.kt +++ b/libraries/core/src/main/kotlin/com/bumble/appyx/core/composable/PermanentChild.kt @@ -1,11 +1,16 @@ package com.bumble.appyx.core.composable import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import com.bumble.appyx.core.mapState import com.bumble.appyx.core.navigation.model.permanent.PermanentNavModel import com.bumble.appyx.core.node.Node import com.bumble.appyx.core.node.ParentNode +import kotlinx.coroutines.flow.SharingStarted @Composable fun ParentNode.PermanentChild( @@ -13,19 +18,22 @@ fun ParentNode.PermanentChild( navTarget: NavTarget, decorator: @Composable (child: ChildRenderer) -> Unit ) { - val child = remember(navTarget, permanentNavModel) { + val scope = rememberCoroutineScope() + val child by remember(navTarget, permanentNavModel) { permanentNavModel .elements - .value - .find { it.key.navTarget == navTarget } - ?.let { childOrCreate(it.key) } - ?: throw IllegalStateException( - "No child found for $navTarget in $permanentNavModel. " + - "Add $navTarget to $permanentNavModel before calling PermanentChild." - ) + // use WhileSubscribed or Lazy otherwise desynchronisation issue + .mapState(scope, SharingStarted.WhileSubscribed()) { navElements -> + navElements + .find { it.key.navTarget == navTarget } + ?.let { childOrCreate(it.key) } + } + }.collectAsState() + + child?.let { + decorator(PermanentChildRender(it.node)) } - decorator(PermanentChildRender(child.node)) } @Composable