From 235bd40296af4e78fff06437188d64b8e6060da6 Mon Sep 17 00:00:00 2001 From: Antoine Jaury Date: Tue, 9 Jun 2026 16:11:53 +0200 Subject: [PATCH] refactor: integrate ViewModel and repository for record management --- .../kotlin/fr/ajaury/gwenedeg/App.kt | 9 ++++- .../records/data/InMemoryRecordRepository.kt | 35 +++++++++++++++++ .../ajaury/gwenedeg/records/domain/Record.kt | 5 +++ .../records/domain/RecordRepository.kt | 7 ++++ .../ajaury/gwenedeg/records/ui/RecordView.kt | 5 ++- .../gwenedeg/records/ui/RecordsScreen.kt | 39 ++++--------------- .../records/ui/viewmodel/RecordsViewModel.kt | 21 ++++++++++ .../fr/ajaury/gwenedeg/MainViewController.kt | 2 +- .../webMain/kotlin/fr/ajaury/gwenedeg/main.kt | 2 +- 9 files changed, 89 insertions(+), 36 deletions(-) create mode 100644 shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/data/InMemoryRecordRepository.kt create mode 100644 shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/domain/Record.kt create mode 100644 shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/domain/RecordRepository.kt create mode 100644 shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/viewmodel/RecordsViewModel.kt diff --git a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/App.kt b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/App.kt index 9ca82ef..de4d45e 100644 --- a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/App.kt +++ b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/App.kt @@ -2,13 +2,20 @@ package fr.ajaury.gwenedeg import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember import androidx.compose.ui.tooling.preview.Preview +import fr.ajaury.gwenedeg.records.data.InMemoryRecordRepository import fr.ajaury.gwenedeg.records.ui.RecordsScreen +import fr.ajaury.gwenedeg.records.ui.viewmodel.RecordsViewModel @Composable @Preview fun App() { + val viewModel = remember { + RecordsViewModel(InMemoryRecordRepository()) + } + MaterialTheme { - RecordsScreen() + RecordsScreen(viewModel) } } diff --git a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/data/InMemoryRecordRepository.kt b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/data/InMemoryRecordRepository.kt new file mode 100644 index 0000000..a75146d --- /dev/null +++ b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/data/InMemoryRecordRepository.kt @@ -0,0 +1,35 @@ +package fr.ajaury.gwenedeg.records.data + +import fr.ajaury.gwenedeg.records.domain.Record +import fr.ajaury.gwenedeg.records.domain.RecordRepository +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf + +class InMemoryRecordRepository : RecordRepository { + private val records = + listOf( + "An onestiz", + "En em brezntiñ", + "An amzer a ra", + "E komz get unan arall", + "Me hag ar brezhoneg", + "Ar yec'hed", + "Deskriviñ", + "Me 'gar / Ne garan ket", + "C'hoantoù", + "Penaos 'peus kavet...?", + "Oberiantizoù", + "Debriñ hag evet", + "Bale, pourmen ha beajiñ", + "Ma c'horf", + "Dle eo / ret eo / dav eo / mall eo...", + "Deizioù ar sizhun", + "Mizioù ha kourzoù ar blez", + "Bez'zo / N'eus ket...", + "Banne.../Tamm...", + "Stad a vuhez", + "Lec'hiiñ", + ).map { Record(it) } + + override fun getRecords(): Flow> = flowOf(records) +} diff --git a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/domain/Record.kt b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/domain/Record.kt new file mode 100644 index 0000000..b238cc3 --- /dev/null +++ b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/domain/Record.kt @@ -0,0 +1,5 @@ +package fr.ajaury.gwenedeg.records.domain + +data class Record( + val title: String, +) diff --git a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/domain/RecordRepository.kt b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/domain/RecordRepository.kt new file mode 100644 index 0000000..6f2848e --- /dev/null +++ b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/domain/RecordRepository.kt @@ -0,0 +1,7 @@ +package fr.ajaury.gwenedeg.records.domain + +import kotlinx.coroutines.flow.Flow + +interface RecordRepository { + fun getRecords(): Flow> +} diff --git a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/RecordView.kt b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/RecordView.kt index c6658e2..418ce44 100644 --- a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/RecordView.kt +++ b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/RecordView.kt @@ -5,11 +5,12 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import fr.ajaury.gwenedeg.records.domain.Record @Composable -fun RecordView(record: String) { +fun RecordView(record: Record) { Text( - text = record, + text = record.title, modifier = Modifier.padding(16.dp), ) } diff --git a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/RecordsScreen.kt b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/RecordsScreen.kt index b16d57c..5627272 100644 --- a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/RecordsScreen.kt +++ b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/RecordsScreen.kt @@ -5,41 +5,20 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.safeContentPadding import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp - -private val records = - listOf( - "An onestiz", - "En em brezntiñ", - "An amzer a ra", - "E komz get unan arall", - "Me hag ar brezhoneg", - "Ar yec'hed", - "Deskriviñ", - "Me 'gar / Ne garan ket", - "C'hoantoù", - "Penaos 'peus kavet...?", - "Oberiantizoù", - "Debriñ hag evet", - "Bale, pourmen ha beajiñ", - "Ma c'horf", - "Dle eo / ret eo / dav eo / mall eo...", - "Deizioù ar sizhun", - "Mizioù ha kourzoù ar blez", - "Bez'zo / N'eus ket...", - "Banne.../Tamm...", - "Stad a vuhez", - "Lec'hiiñ", - ) +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import fr.ajaury.gwenedeg.records.ui.viewmodel.RecordsViewModel @Composable -fun RecordsScreen() { +fun RecordsScreen(viewModel: RecordsViewModel) { + val records by viewModel.uiState.collectAsStateWithLifecycle() Scaffold { innerPadding -> LazyColumn( modifier = @@ -48,12 +27,12 @@ fun RecordsScreen() { .background(MaterialTheme.colorScheme.primaryContainer) .fillMaxSize(), ) { - items(records) { item -> + itemsIndexed(records) { index, item -> RecordView( record = item, ) - if (!item.isLastItem()) { + if (index < records.lastIndex) { HorizontalDivider( modifier = Modifier.padding(horizontal = 16.dp), thickness = 1.dp, @@ -64,5 +43,3 @@ fun RecordsScreen() { } } } - -private fun String.isLastItem(): Boolean = this == records.last() diff --git a/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/viewmodel/RecordsViewModel.kt b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/viewmodel/RecordsViewModel.kt new file mode 100644 index 0000000..7600979 --- /dev/null +++ b/shared/src/commonMain/kotlin/fr/ajaury/gwenedeg/records/ui/viewmodel/RecordsViewModel.kt @@ -0,0 +1,21 @@ +package fr.ajaury.gwenedeg.records.ui.viewmodel + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import fr.ajaury.gwenedeg.records.domain.Record +import fr.ajaury.gwenedeg.records.domain.RecordRepository +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.stateIn + +class RecordsViewModel( + recordRepository: RecordRepository, +) : ViewModel() { + val uiState: StateFlow> = recordRepository + .getRecords() + .stateIn( + scope = viewModelScope, + started = SharingStarted.WhileSubscribed(5000), + initialValue = emptyList(), + ) +} diff --git a/shared/src/iosMain/kotlin/fr/ajaury/gwenedeg/MainViewController.kt b/shared/src/iosMain/kotlin/fr/ajaury/gwenedeg/MainViewController.kt index 2fe4f1e..454b9b8 100644 --- a/shared/src/iosMain/kotlin/fr/ajaury/gwenedeg/MainViewController.kt +++ b/shared/src/iosMain/kotlin/fr/ajaury/gwenedeg/MainViewController.kt @@ -2,4 +2,4 @@ package fr.ajaury.gwenedeg import androidx.compose.ui.window.ComposeUIViewController -fun MainViewController() = ComposeUIViewController { App() } \ No newline at end of file +fun MainViewController() = ComposeUIViewController { App() } diff --git a/webApp/src/webMain/kotlin/fr/ajaury/gwenedeg/main.kt b/webApp/src/webMain/kotlin/fr/ajaury/gwenedeg/main.kt index 8a9523b..8f1ef28 100644 --- a/webApp/src/webMain/kotlin/fr/ajaury/gwenedeg/main.kt +++ b/webApp/src/webMain/kotlin/fr/ajaury/gwenedeg/main.kt @@ -8,4 +8,4 @@ fun main() { ComposeViewport { App() } -} \ No newline at end of file +}