From f5fc00ba80f8db47727f173d23dbb756c9315616 Mon Sep 17 00:00:00 2001 From: ikarenkov Date: Mon, 28 Aug 2023 20:53:02 +0300 Subject: [PATCH 1/2] fixed wrong Composition Local providing --- .../com/github/terrakok/modo/ComposeRender.kt | 5 +--- .../java/com/github/terrakok/modo/Modo.kt | 10 ++++---- .../com/github/terrakok/modo/RootScreen.kt | 25 +++++++++++++++++++ .../github/terrakok/modo/stack/StackScreen.kt | 2 +- .../terrakok/androidcomposeapp/AppActivity.kt | 3 ++- .../androidcomposeapp/screens/SampleScreen.kt | 4 +-- ...inerScreen.kt => SampleContainerScreen.kt} | 4 +-- 7 files changed, 38 insertions(+), 15 deletions(-) create mode 100644 modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt rename sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/containers/{ContainerScreen.kt => SampleContainerScreen.kt} (97%) diff --git a/modo-compose/src/main/java/com/github/terrakok/modo/ComposeRender.kt b/modo-compose/src/main/java/com/github/terrakok/modo/ComposeRender.kt index ca3159fb..7a892752 100644 --- a/modo-compose/src/main/java/com/github/terrakok/modo/ComposeRender.kt +++ b/modo-compose/src/main/java/com/github/terrakok/modo/ComposeRender.kt @@ -7,7 +7,6 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.neverEqualPolicy import androidx.compose.runtime.saveable.SaveableStateHolder -import androidx.compose.runtime.saveable.rememberSaveableStateHolder import androidx.compose.runtime.setValue import androidx.compose.runtime.staticCompositionLocalOf import com.github.terrakok.modo.model.ScreenModelStore @@ -61,15 +60,13 @@ internal class ComposeRenderer( screen: Screen, content: RendererContent = defaultRendererContent ) { - // use single state holder for whole hierarchy, store it on top of it - val stateHolder: SaveableStateHolder = LocalSaveableStateHolder.current ?: rememberSaveableStateHolder() + val stateHolder: SaveableStateHolder = LocalSaveableStateHolder.currentOrThrow DisposableEffect(key1 = state) { onDispose { clearScreens(stateHolder) } } CompositionLocalProvider( - LocalSaveableStateHolder providesDefault stateHolder, LocalContainerScreen provides containerScreen ) { ComposeRendererScope(lastState, state, screen).content() diff --git a/modo-compose/src/main/java/com/github/terrakok/modo/Modo.kt b/modo-compose/src/main/java/com/github/terrakok/modo/Modo.kt index 449cd98a..96a52241 100644 --- a/modo-compose/src/main/java/com/github/terrakok/modo/Modo.kt +++ b/modo-compose/src/main/java/com/github/terrakok/modo/Modo.kt @@ -21,21 +21,21 @@ object Modo { * @param savedState - container with modo state and graph * @param rootScreenProvider invokes when [savedState] is null and [inMemoryScreen] is null and we need to provide root screen. */ - fun init(savedState: Bundle?, inMemoryScreen: T?, rootScreenProvider: () -> T): T { - val modoGraph = savedState?.getParcelable(MODO_GRAPH) + fun init(savedState: Bundle?, inMemoryScreen: RootScreen?, rootScreenProvider: () -> T): RootScreen { + val modoGraph = savedState?.getParcelable>(MODO_GRAPH) return if (modoGraph != null) { restoreScreenCounter(savedState.getInt(MODO_SCREEN_COUNTER_KEY)) modoGraph } else { - inMemoryScreen ?: rootScreenProvider() + inMemoryScreen ?: RootScreen(rootScreenProvider()) } } /** * Must be called to clear all data from [ScreenModelStore], related with removed screens. */ - fun onRootScreenFinished(rootScreen: ContainerScreen<*>?) { - rootScreen?.let(::clearScreenModel) + fun > onRootScreenFinished(rootScreen: RootScreen?) { + rootScreen?.screen?.let(::clearScreenModel) } private fun clearScreenModel(screen: Screen) { diff --git a/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt b/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt new file mode 100644 index 00000000..314bf2c2 --- /dev/null +++ b/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt @@ -0,0 +1,25 @@ +package com.github.terrakok.modo + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.saveable.SaveableStateHolder +import androidx.compose.runtime.saveable.rememberSaveableStateHolder +import kotlinx.parcelize.Parcelize + +@Parcelize +class RootScreen( + val screen: T, + override val screenKey: ScreenKey = generateScreenKey() +) : Screen { + + @Composable + override fun Content() { + val stateHolder: SaveableStateHolder = LocalSaveableStateHolder.current ?: rememberSaveableStateHolder() + CompositionLocalProvider( + LocalSaveableStateHolder providesDefault stateHolder + ) { + screen.Content() + } + } + +} \ No newline at end of file diff --git a/modo-compose/src/main/java/com/github/terrakok/modo/stack/StackScreen.kt b/modo-compose/src/main/java/com/github/terrakok/modo/stack/StackScreen.kt index 99b0ac23..c1a504a5 100644 --- a/modo-compose/src/main/java/com/github/terrakok/modo/stack/StackScreen.kt +++ b/modo-compose/src/main/java/com/github/terrakok/modo/stack/StackScreen.kt @@ -59,7 +59,7 @@ abstract class StackScreen( onDismissRequest = { back() }, properties = remember { dialog.provideDialogProperties() } ) { - Content(screen = dialog) + Content(dialog, content) } } } diff --git a/sample/src/main/java/com/github/terrakok/androidcomposeapp/AppActivity.kt b/sample/src/main/java/com/github/terrakok/androidcomposeapp/AppActivity.kt index e188e7be..6b85deb7 100644 --- a/sample/src/main/java/com/github/terrakok/androidcomposeapp/AppActivity.kt +++ b/sample/src/main/java/com/github/terrakok/androidcomposeapp/AppActivity.kt @@ -8,11 +8,12 @@ import androidx.compose.material.Surface import com.github.terrakok.androidcomposeapp.screens.SampleScreen import com.github.terrakok.androidcomposeapp.screens.containers.SampleStack import com.github.terrakok.modo.Modo +import com.github.terrakok.modo.RootScreen import com.github.terrakok.modo.stack.StackScreen class AppActivity : AppCompatActivity() { - private var rootScreen: StackScreen? = null + private var rootScreen: RootScreen? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/SampleScreen.kt b/sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/SampleScreen.kt index d843d74b..86e49239 100644 --- a/sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/SampleScreen.kt +++ b/sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/SampleScreen.kt @@ -23,7 +23,7 @@ import com.github.terrakok.androidcomposeapp.ListScreen import com.github.terrakok.androidcomposeapp.ModelSampleScreen import com.github.terrakok.androidcomposeapp.randomBackground import com.github.terrakok.androidcomposeapp.screens.containers.SampleMultiScreen -import com.github.terrakok.androidcomposeapp.screens.containers.SampleStackScreen +import com.github.terrakok.androidcomposeapp.screens.containers.SampleContainerScreen import com.github.terrakok.modo.LocalContainerScreen import com.github.terrakok.modo.NavigationContainer import com.github.terrakok.modo.Screen @@ -131,7 +131,7 @@ private fun rememberButtons( navigator.backTo(it) } }, - "Container" to { navigator.forward(SampleStackScreen(i + 1)) }, + "Container" to { navigator.forward(SampleContainerScreen(i + 1)) }, "Multiscreen" to { navigator.forward(SampleMultiScreen()) }, "List/Details" to { navigator.forward(ListScreen()) }, // Just experiments diff --git a/sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/containers/ContainerScreen.kt b/sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/containers/SampleContainerScreen.kt similarity index 97% rename from sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/containers/ContainerScreen.kt rename to sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/containers/SampleContainerScreen.kt index 75de0c7f..9bd4b51f 100644 --- a/sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/containers/ContainerScreen.kt +++ b/sample/src/main/java/com/github/terrakok/androidcomposeapp/screens/containers/SampleContainerScreen.kt @@ -25,7 +25,7 @@ import com.github.terrakok.modo.stack.back import kotlinx.parcelize.Parcelize @Parcelize -class SampleStackScreen( +class SampleContainerScreen( private val i: Int, private val navModel: StackNavModel ) : StackScreen(navModel) { @@ -68,5 +68,5 @@ class SampleStackScreen( @Preview @Composable private fun PreviewContainerScreen() { - SampleStackScreen(1).Content() + SampleContainerScreen(1).Content() } \ No newline at end of file From 8b35884008f282526395ca31180ba8d544eccda7 Mon Sep 17 00:00:00 2001 From: ikarenkov Date: Thu, 7 Sep 2023 14:12:30 +0300 Subject: [PATCH 2/2] added commment --- .../src/main/java/com/github/terrakok/modo/RootScreen.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt b/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt index 314bf2c2..8fcf2f18 100644 --- a/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt +++ b/modo-compose/src/main/java/com/github/terrakok/modo/RootScreen.kt @@ -6,6 +6,9 @@ import androidx.compose.runtime.saveable.SaveableStateHolder import androidx.compose.runtime.saveable.rememberSaveableStateHolder import kotlinx.parcelize.Parcelize +/** + * Screen for single source of providing [LocalSaveableStateHolder]. Should be used with [Modo.init]. + */ @Parcelize class RootScreen( val screen: T,