new: integrate navigation

This commit is contained in:
2026-06-11 17:50:21 +02:00
parent afc3af7466
commit 767fff7208
8 changed files with 118 additions and 9 deletions
+6 -2
View File
@@ -6,6 +6,7 @@ plugins {
alias(libs.plugins.androidMultiplatformLibrary)
alias(libs.plugins.composeMultiplatform)
alias(libs.plugins.composeCompiler)
alias(libs.plugins.kotlinSerialization)
}
kotlin {
@@ -33,11 +34,11 @@ kotlin {
androidLibrary {
namespace = "fr.ajaury.gwenedeg.shared"
compileSdk =
libs.versions.android.compileSdk
libs.versions.androidCompileSdk
.get()
.toInt()
minSdk =
libs.versions.android.minSdk
libs.versions.androidMinSdk
.get()
.toInt()
@@ -66,6 +67,9 @@ kotlin {
implementation(libs.androidx.lifecycle.viewmodelCompose)
implementation(libs.androidx.lifecycle.runtimeCompose)
// Navigation
implementation(libs.navigation3)
// DI
implementation(project.dependencies.platform(libs.koin.bom))
implementation(libs.koin.core)
@@ -2,8 +2,15 @@ package fr.ajaury.gwenedeg
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.saveable.rememberSerializable
import androidx.compose.ui.tooling.preview.Preview
import androidx.navigation3.runtime.NavEntry
import androidx.navigation3.ui.NavDisplay
import androidx.savedstate.compose.serialization.serializers.SnapshotStateListSerializer
import fr.ajaury.gwenedeg.di.appModule
import fr.ajaury.gwenedeg.navigation.Route
import fr.ajaury.gwenedeg.player.ui.PlayerScreen
import fr.ajaury.gwenedeg.records.ui.RecordsScreen
import org.koin.compose.KoinApplication
import org.koin.dsl.koinConfiguration
@@ -16,8 +23,33 @@ fun App() {
modules(appModule)
},
) {
val serializer = SnapshotStateListSerializer<Route>()
val backStack: MutableList<Route> = rememberSerializable(serializer = serializer) {
mutableStateListOf(Route.Records)
}
MaterialTheme {
RecordsScreen()
NavDisplay(
backStack = backStack,
onBack = { backStack.removeLastOrNull() },
entryProvider = { key ->
when (key) {
is Route.Records -> NavEntry(key) {
RecordsScreen(
onRecordClick = { record ->
backStack.add(Route.Player(record.title))
},
)
}
is Route.Player -> NavEntry(key) {
PlayerScreen(
recordTitle = key.title,
)
}
}
},
)
}
}
}
@@ -0,0 +1,15 @@
package fr.ajaury.gwenedeg.navigation
import androidx.navigation3.runtime.NavKey
import kotlinx.serialization.Serializable
@Serializable
sealed interface Route : NavKey {
@Serializable
data object Records : Route
@Serializable
data class Player(
val title: String,
) : Route
}
@@ -0,0 +1,33 @@
package fr.ajaury.gwenedeg.player.ui
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import org.jetbrains.compose.resources.ExperimentalResourceApi
@OptIn(ExperimentalResourceApi::class)
@Composable
fun PlayerScreen(recordTitle: String) {
Scaffold { innerPadding ->
Box(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
contentAlignment = Alignment.Center,
) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
Text(
text = "Playing: $recordTitle",
style = MaterialTheme.typography.headlineMedium,
)
}
}
}
}
@@ -1,5 +1,6 @@
package fr.ajaury.gwenedeg.records.ui
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -8,9 +9,15 @@ import androidx.compose.ui.unit.dp
import fr.ajaury.gwenedeg.records.domain.Record
@Composable
fun RecordView(record: Record) {
fun RecordView(
record: Record,
onClick: () -> Unit,
) {
Text(
text = record.title,
modifier = Modifier.padding(16.dp),
modifier =
Modifier
.clickable { onClick() }
.padding(16.dp),
)
}
@@ -19,16 +19,23 @@ import fr.ajaury.gwenedeg.records.ui.viewmodel.RecordsViewModel
import org.koin.compose.viewmodel.koinViewModel
@Composable
fun RecordsScreen(viewModel: RecordsViewModel = koinViewModel()) {
fun RecordsScreen(
viewModel: RecordsViewModel = koinViewModel(),
onRecordClick: (Record) -> Unit,
) {
val records by viewModel.uiState.collectAsStateWithLifecycle()
RecordsScreen(
records = records,
onRecordClick = onRecordClick,
)
}
@Composable
fun RecordsScreen(records: List<Record>) {
fun RecordsScreen(
records: List<Record>,
onRecordClick: (Record) -> Unit,
) {
Scaffold { innerPadding ->
LazyColumn(
modifier =
@@ -40,6 +47,7 @@ fun RecordsScreen(records: List<Record>) {
itemsIndexed(records) { index, item ->
RecordView(
record = item,
onClick = { onRecordClick(item) },
)
if (index < records.lastIndex) {