Subject: [PATCH] Changes to show TabNavigator bug --- Index: samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/BasicNavigationScreen.kt IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/BasicNavigationScreen.kt b/samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/BasicNavigationScreen.kt --- a/samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/BasicNavigationScreen.kt (revision 22cbd6295167336c719d76ab9472d2b85c9ac68d) +++ b/samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/BasicNavigationScreen.kt (date 1712603349796) @@ -1,27 +1,47 @@ package cafe.adriel.voyager.sample.multiplatform +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.Button import androidx.compose.material.MaterialTheme +import androidx.compose.material.Scaffold import androidx.compose.material.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import cafe.adriel.voyager.core.annotation.InternalVoyagerApi import cafe.adriel.voyager.core.lifecycle.LifecycleEffect import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.core.screen.ScreenKey import cafe.adriel.voyager.core.screen.uniqueScreenKey import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.currentOrThrow +import cafe.adriel.voyager.navigator.tab.CurrentTab +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabDisposable +import cafe.adriel.voyager.navigator.tab.TabNavigator +import cafe.adriel.voyager.navigator.tab.TabOptions public data class BasicNavigationScreen( val index: Int, @@ -71,20 +91,20 @@ Spacer(modifier = Modifier.weight(.1f)) Button( - onClick = { navigator.push(BasicNavigationScreen(index.inc(), wrapContent)) }, + onClick = { navigator.push(TabScreen()) }, modifier = Modifier.weight(.5f) ) { - Text(text = "Push") + Text(text = "Push Tab Screen") } - Spacer(modifier = Modifier.weight(.1f)) - - Button( - onClick = { navigator.replace(BasicNavigationScreen(index.inc(), wrapContent)) }, - modifier = Modifier.weight(.5f) - ) { - Text(text = "Replace") - } +// Spacer(modifier = Modifier.weight(.1f)) +// +// Button( +// onClick = { navigator.replace(BasicNavigationScreen(index.inc(), wrapContent)) }, +// modifier = Modifier.weight(.5f) +// ) { +// Text(text = "Replace") +// } } LazyColumn( @@ -97,3 +117,132 @@ } } } + +class TabScreen: Screen { + + @Composable + override fun Content() { + TabNavigator( + ScrollingTab, + tabDisposable = { + TabDisposable( + navigator = it, + tabs = listOf(ScrollingTab, ScrollingTab) + ) + } + ) { tabNavigator -> + Scaffold( + modifier = Modifier + .background(Color.Blue.copy(alpha = 0.6f)) + .fillMaxSize(), + content = { paddingValues -> + CurrentTab() + }, + bottomBar = { + Box( + modifier = Modifier + .background(Color.Red.copy(alpha = 0.6f)) + .fillMaxWidth() + .height(64.dp), + contentAlignment = Alignment.Center + ) { + Text( + text = "This is where bottom nav would go" + ) + } + } + ) + } + } +} + +@OptIn( + InternalVoyagerApi::class +) +fun Navigator.findParentByKey(key: String): Navigator { + return if (this.key == key) { + this + } else { + parent?.findParentByKey(key) + ?: throw IllegalStateException("Invalid navigator key") + } +} + +object ScrollingTab: Tab { + + override val options: TabOptions + @Composable + get() { + return TabOptions( + index = 0u, + title = "Home" + ) + } + + @Composable + override fun Content() { + val lazyListState = rememberLazyListState() + + val navigator = LocalNavigator.currentOrThrow + .findParentByKey("root") + + LazyColumn( + modifier = Modifier + .fillMaxSize() + .background(Color.White), + state = lazyListState + ) { + items(25) { + Row( + modifier = Modifier + .padding(top = 4.dp) + .fillMaxWidth() + .height(84.dp) + .background(Color.LightGray), + verticalAlignment = Alignment.CenterVertically + ) { + Box( + modifier = Modifier + .aspectRatio(1f) + .fillMaxHeight() + .background(Color.Blue.copy(alpha = 0.4f)), + contentAlignment = Alignment.Center + ) { + Text( + text = it.toString(), + color = Color.White, + fontSize = 24.sp + ) + } + + Button( + modifier = Modifier + .padding(start = 4.dp), + onClick = { + navigator.push(DemoEndScreen()) + } + ) { + Text("Click to observe bug") + } + } + } + } + } +} + +class DemoEndScreen(): Screen { + + @Composable + override fun Content() { + Box( + modifier = Modifier + .fillMaxSize() + .background(Color.Green.copy(alpha = 0.4f)), + contentAlignment = Alignment.Center + ) { + Text( + text = "Navigating back from this screen should lose scroll postion" + ) + } + } +} Index: samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/Application.kt IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/Application.kt b/samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/Application.kt --- a/samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/Application.kt (revision 22cbd6295167336c719d76ab9472d2b85c9ac68d) +++ b/samples/multiplatform/src/commonMain/kotlin/cafe/adriel/voyager/sample/multiplatform/Application.kt (date 1712603358158) @@ -2,14 +2,19 @@ import androidx.compose.runtime.Composable import cafe.adriel.voyager.navigator.Navigator +import cafe.adriel.voyager.navigator.NavigatorDisposeBehavior @Composable public fun SampleApplication() { Navigator( screen = BasicNavigationScreen(index = 0), - onBackPressed = { currentScreen -> - println("Navigator: Pop screen #${(currentScreen as BasicNavigationScreen).index}") - true - } + key = "root", + disposeBehavior = NavigatorDisposeBehavior( + disposeNestedNavigators = false + ) +// onBackPressed = { currentScreen -> +// println("Navigator: Pop screen #${(currentScreen as BasicNavigationScreen).index}") +// true +// } ) } Index: voyager-tab-navigator/src/commonMain/kotlin/cafe/adriel/voyager/navigator/tab/TabNavigator.kt IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/voyager-tab-navigator/src/commonMain/kotlin/cafe/adriel/voyager/navigator/tab/TabNavigator.kt b/voyager-tab-navigator/src/commonMain/kotlin/cafe/adriel/voyager/navigator/tab/TabNavigator.kt --- a/voyager-tab-navigator/src/commonMain/kotlin/cafe/adriel/voyager/navigator/tab/TabNavigator.kt (revision 22cbd6295167336c719d76ab9472d2b85c9ac68d) +++ b/voyager-tab-navigator/src/commonMain/kotlin/cafe/adriel/voyager/navigator/tab/TabNavigator.kt (date 1712603358161) @@ -49,6 +49,7 @@ DisposableEffectIgnoringConfiguration(Unit) { onDispose { tabs.forEach { + println("::: You are disposing the tabs") navigator.navigator.dispose(it) } } Index: samples/multiplatform/build.gradle.kts IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/samples/multiplatform/build.gradle.kts b/samples/multiplatform/build.gradle.kts --- a/samples/multiplatform/build.gradle.kts (revision 22cbd6295167336c719d76ab9472d2b85c9ac68d) +++ b/samples/multiplatform/build.gradle.kts (date 1712603349791) @@ -73,6 +73,7 @@ implementation(projects.voyagerCore) implementation(projects.voyagerNavigator) + implementation(projects.voyagerTabNavigator) implementation(libs.coroutines.core) } }