From 0455d82a4094f380473a2a70dd30c46a12ebe195 Mon Sep 17 00:00:00 2001 From: Fabian Wolter Date: Tue, 24 Feb 2026 21:51:45 +0100 Subject: [PATCH] refactor: start to move from voyager to navigation3 I want to move away from the easy but limited voyager library ind implement my own navigation --- app/build.gradle.kts | 6 +- .../com/fabisahne/cloudsync/MainActivity.kt | 4 +- .../fabisahne/cloudsync/navigation/Route.kt | 27 ++++++++ .../cloudsync/ui/navigation/navigation.kt | 22 ------ .../cloudsync/ui/screens/FolderPairScreen.kt | 39 +++++------ .../cloudsync/ui/screens/HomeScreen.kt | 68 +++++++++---------- .../cloudsync/ui/tabs/SettingsTab.kt | 1 - .../viewmodels/FolderPairScreenViewModel.kt | 20 ++++++ build.gradle.kts | 1 + gradle/libs.versions.toml | 30 +++----- 10 files changed, 114 insertions(+), 104 deletions(-) create mode 100644 app/src/main/java/com/fabisahne/cloudsync/navigation/Route.kt delete mode 100644 app/src/main/java/com/fabisahne/cloudsync/ui/navigation/navigation.kt create mode 100644 app/src/main/java/com/fabisahne/cloudsync/viewmodels/FolderPairScreenViewModel.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 798b270..8dcfdfd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,7 +1,7 @@ plugins { alias(libs.plugins.android.application) alias(libs.plugins.kotlin.compose) - alias(libs.plugins.jetbrains.kotlin.serialization) + alias(libs.plugins.kotlin.serialization) alias(libs.plugins.ksp) } @@ -61,9 +61,7 @@ dependencies { implementation(libs.androidx.navigation3.runtime) implementation(libs.androidx.lifecycle.viewmodel.navigation3) implementation(libs.androidx.material3.adaptive.navigation3) - implementation(libs.kotlinx.serialization.core) - - implementation(libs.bundles.voyager) + implementation(libs.kotlinx.serialization.json) // Room implementation(libs.androidx.room.runtime) diff --git a/app/src/main/java/com/fabisahne/cloudsync/MainActivity.kt b/app/src/main/java/com/fabisahne/cloudsync/MainActivity.kt index deca6f9..f416313 100644 --- a/app/src/main/java/com/fabisahne/cloudsync/MainActivity.kt +++ b/app/src/main/java/com/fabisahne/cloudsync/MainActivity.kt @@ -5,8 +5,6 @@ import androidx.activity.ComponentActivity import androidx.activity.compose.setContent import androidx.activity.enableEdgeToEdge import androidx.compose.material3.ExperimentalMaterial3Api -import cafe.adriel.voyager.navigator.Navigator -import com.fabisahne.cloudsync.ui.screens.HomeScreen import com.fabisahne.cloudsync.ui.theme.CloudSyncTheme class MainActivity : ComponentActivity() { @@ -17,7 +15,7 @@ class MainActivity : ComponentActivity() { enableEdgeToEdge() setContent { CloudSyncTheme { - Navigator(HomeScreen) +// Navigator(HomeScreen) } } } diff --git a/app/src/main/java/com/fabisahne/cloudsync/navigation/Route.kt b/app/src/main/java/com/fabisahne/cloudsync/navigation/Route.kt new file mode 100644 index 0000000..2e34217 --- /dev/null +++ b/app/src/main/java/com/fabisahne/cloudsync/navigation/Route.kt @@ -0,0 +1,27 @@ +package com.fabisahne.cloudsync.navigation + +import androidx.navigation3.runtime.NavKey +import kotlinx.serialization.Serializable + +@Serializable +sealed interface Route : NavKey { + // Screens + @Serializable + data object HomeScreen : Route, NavKey + + @Serializable + data class FolderPairScreen(val id: Long) : Route, NavKey + + // Tabs + @Serializable + data object AccountTab : Route, NavKey + + @Serializable + data object FolderPairTab : Route, NavKey + + @Serializable + data object HistoryTab : Route, NavKey + + @Serializable + data object SettingsTab : Route, NavKey +} \ No newline at end of file diff --git a/app/src/main/java/com/fabisahne/cloudsync/ui/navigation/navigation.kt b/app/src/main/java/com/fabisahne/cloudsync/ui/navigation/navigation.kt deleted file mode 100644 index 4562eb8..0000000 --- a/app/src/main/java/com/fabisahne/cloudsync/ui/navigation/navigation.kt +++ /dev/null @@ -1,22 +0,0 @@ -package com.fabisahne.cloudsync.ui.navigation - -import androidx.compose.foundation.layout.RowScope -import androidx.compose.material3.Icon -import androidx.compose.material3.NavigationBarItem -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import cafe.adriel.voyager.navigator.tab.LocalTabNavigator -import cafe.adriel.voyager.navigator.tab.Tab - - -@Composable -fun RowScope.TabNavigationItem(tab: Tab) { - val tabNavigator = LocalTabNavigator.current - - NavigationBarItem( - selected = tabNavigator.current.key == tab.key, - onClick = { tabNavigator.current = tab }, - label = { Text(tab.options.title) }, - icon = { Icon(painter = tab.options.icon!!, contentDescription = tab.options.title) } - ) -} \ No newline at end of file diff --git a/app/src/main/java/com/fabisahne/cloudsync/ui/screens/FolderPairScreen.kt b/app/src/main/java/com/fabisahne/cloudsync/ui/screens/FolderPairScreen.kt index bd8efc0..e49738c 100644 --- a/app/src/main/java/com/fabisahne/cloudsync/ui/screens/FolderPairScreen.kt +++ b/app/src/main/java/com/fabisahne/cloudsync/ui/screens/FolderPairScreen.kt @@ -8,25 +8,26 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import cafe.adriel.voyager.core.screen.Screen +import androidx.lifecycle.viewmodel.compose.viewModel +import com.fabisahne.cloudsync.viewmodels.FolderPairScreenViewModel -data class FolderPairScreen( - val id: Long -) : Screen { - @OptIn(ExperimentalMaterial3Api::class) - @Composable - override fun Content() { - Scaffold( - topBar = { - TopAppBar( - title = { Text("Folder Pair") } - ) - }, - content = { contentPadding -> - Surface(modifier = Modifier.padding(contentPadding)) { - Text("ASDF: $id") - } +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun FolderPairScreen( + modifier: Modifier = Modifier, + viewModel: FolderPairScreenViewModel = viewModel(), + id: Long +) { + Scaffold( + topBar = { + TopAppBar( + title = { Text("Folder Pair") } + ) + }, + content = { contentPadding -> + Surface(modifier = modifier.padding(contentPadding)) { + Text("ASDF: $id") } - ) - } + } + ) } diff --git a/app/src/main/java/com/fabisahne/cloudsync/ui/screens/HomeScreen.kt b/app/src/main/java/com/fabisahne/cloudsync/ui/screens/HomeScreen.kt index 1dc2888..c56f2b0 100644 --- a/app/src/main/java/com/fabisahne/cloudsync/ui/screens/HomeScreen.kt +++ b/app/src/main/java/com/fabisahne/cloudsync/ui/screens/HomeScreen.kt @@ -1,7 +1,12 @@ package com.fabisahne.cloudsync.ui.screens import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Route +import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarDefaults import androidx.compose.material3.Scaffold @@ -10,55 +15,46 @@ import androidx.compose.material3.Text import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import cafe.adriel.voyager.core.screen.Screen -import cafe.adriel.voyager.navigator.LocalNavigator -import cafe.adriel.voyager.navigator.currentOrThrow -import cafe.adriel.voyager.navigator.tab.CurrentTab -import cafe.adriel.voyager.navigator.tab.TabNavigator -import com.fabisahne.cloudsync.ui.navigation.TabNavigationItem import com.fabisahne.cloudsync.ui.tabs.AccountTab import com.fabisahne.cloudsync.ui.tabs.FolderPairTab import com.fabisahne.cloudsync.ui.tabs.HistoryTab import com.fabisahne.cloudsync.ui.tabs.SettingsTab -object HomeScreen : Screen { - private fun readResolve(): Any = HomeScreen - - private val TABS = listOf( +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun HomeScreen( + modifier: Modifier = Modifier +) { + val tabs = listOf( HistoryTab, FolderPairTab, AccountTab, SettingsTab, ) - @OptIn(ExperimentalMaterial3Api::class) - @Composable - override fun Content() { - val navigator = LocalNavigator.currentOrThrow - - TabNavigator( - HistoryTab - ) { tabNavigator -> - Scaffold( - topBar = { - TopAppBar( - title = { Text(text = tabNavigator.current.options.title) } - ) - }, - content = { padding -> - Surface(modifier = Modifier.padding(padding)) { - CurrentTab() - } - }, - bottomBar = { - NavigationBar(windowInsets = NavigationBarDefaults.windowInsets) { - TABS.forEach { - TabNavigationItem(it) - } + Scaffold( + topBar = { + TopAppBar( + title = { Text("Home Screen") } + ) + }, + content = { padding -> + Surface(modifier = modifier.padding(padding)) { + Text("Home Screen Content") + } + }, + bottomBar = { + NavigationBar(windowInsets = NavigationBarDefaults.windowInsets) { + tabs.forEach { _ -> + Button({}) { + Icon( + Icons.Default.Route, + null + ) } } - ) + } } - } + ) } \ No newline at end of file diff --git a/app/src/main/java/com/fabisahne/cloudsync/ui/tabs/SettingsTab.kt b/app/src/main/java/com/fabisahne/cloudsync/ui/tabs/SettingsTab.kt index 4739757..71c6003 100644 --- a/app/src/main/java/com/fabisahne/cloudsync/ui/tabs/SettingsTab.kt +++ b/app/src/main/java/com/fabisahne/cloudsync/ui/tabs/SettingsTab.kt @@ -1,7 +1,6 @@ package com.fabisahne.cloudsync.ui.tabs import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.AccountBox import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.Text import androidx.compose.runtime.Composable diff --git a/app/src/main/java/com/fabisahne/cloudsync/viewmodels/FolderPairScreenViewModel.kt b/app/src/main/java/com/fabisahne/cloudsync/viewmodels/FolderPairScreenViewModel.kt new file mode 100644 index 0000000..48898e9 --- /dev/null +++ b/app/src/main/java/com/fabisahne/cloudsync/viewmodels/FolderPairScreenViewModel.kt @@ -0,0 +1,20 @@ +package com.fabisahne.cloudsync.viewmodels + +import androidx.lifecycle.ViewModel +import com.fabisahne.cloudsync.data.FolderPair +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow + +class FolderPairScreenViewModel( + private val id: Long +) : ViewModel() { + private val _state = MutableStateFlow( + FolderPair( + id = id, + name = "ASDF", + localDir = "asdf/asdf", + cloudPath = "cloud/folder" + ) + ) + val state = _state.asStateFlow() +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 18318be..cc601ae 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,4 +2,5 @@ plugins { alias(libs.plugins.android.application) apply false alias(libs.plugins.kotlin.compose) apply false + alias(libs.plugins.kotlin.serialization) apply false } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0fd8fd3..8a82362 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,18 +5,18 @@ junit = "4.13.2" junitVersion = "1.3.0" espressoCore = "3.7.0" lifecycleRuntimeKtx = "2.10.0" -activityCompose = "1.12.2" -kotlin = "2.2.10" -composeBom = "2024.09.00" +activityCompose = "1.12.4" +kotlin = "2.3.10" +composeBom = "2026.02.00" voyager = "1.1.0-beta03" -room = "2.7.1" +room = "2.8.4" ksp = "2.3.6" -nav3Core = "1.0.0" +nav3Core = "1.0.1" lifeCycleViewmodelNav3 = "2.10.0" -kotlinSerialization = "2.2.21" -kotlinxSerializationCore = "1.9.0" -material3AdaptiveNav3 = "1.3.0-alpha06" +kotlinSerialization = "2.3.10" +kotlinxSerializationCore = "1.10.0" +material3AdaptiveNav3 = "1.3.0-alpha08" [libraries] androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } @@ -40,14 +40,9 @@ androidx-navigation3-ui = { module = "androidx.navigation3:navigation3-ui", vers androidx-lifecycle-viewmodel-navigation3 = { module = "androidx.lifecycle:lifecycle-viewmodel-navigation3", version.ref = "lifeCycleViewmodelNav3" } kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinxSerializationCore" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinxSerializationCore" } androidx-material3-adaptive-navigation3 = { group = "androidx.compose.material3.adaptive", name = "adaptive-navigation3", version.ref = "material3AdaptiveNav3" } -# Voyager -voyager-navigator = { module = "cafe.adriel.voyager:voyager-navigator", version.ref = "voyager" } -voyager-screenmodel = { module = "cafe.adriel.voyager:voyager-screenmodel", version.ref = "voyager" } -voyager-tab-navigator = { module = "cafe.adriel.voyager:voyager-tab-navigator", version.ref = "voyager" } -voyager-transitions = { module = "cafe.adriel.voyager:voyager-transitions", version.ref = "voyager" } - # Room androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" } androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" } @@ -56,8 +51,5 @@ androidx-room-compiler = { group = "androidx.room", name = "room-compiler", vers [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } -jetbrains-kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinSerialization" } -ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } - -[bundles] -voyager = ["voyager-navigator", "voyager-screenmodel", "voyager-tab-navigator", "voyager-transitions"] \ No newline at end of file +kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlinSerialization" } +ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } \ No newline at end of file