From e62b558c214fd35efdea8150ae07898be97c1540 Mon Sep 17 00:00:00 2001 From: "Andres Gomez, Thomas (ITDV RL)" Date: Fri, 21 Jun 2024 14:06:50 +0200 Subject: [PATCH] Convert the AdventureDetailScreen to flow instead of snapshot. --- .../adventure/AdventureRepository.kt | 41 +++++-- .../adventure/book/AdventureBooksViewModel.kt | 2 +- .../chapter/AdventureStoriesViewModel.kt | 2 +- .../detail/AdventureDetailViewModel.kt | 112 ++++++++++++------ 4 files changed, 106 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/com/pixelized/rplexicon/data/repository/adventure/AdventureRepository.kt b/app/src/main/java/com/pixelized/rplexicon/data/repository/adventure/AdventureRepository.kt index 67f4126..58ac45d 100644 --- a/app/src/main/java/com/pixelized/rplexicon/data/repository/adventure/AdventureRepository.kt +++ b/app/src/main/java/com/pixelized/rplexicon/data/repository/adventure/AdventureRepository.kt @@ -17,8 +17,10 @@ import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn import javax.inject.Inject import javax.inject.Singleton @@ -32,7 +34,7 @@ class AdventureRepository @Inject constructor( private val adventureStoryLineParser: AdventureStoryLineParser, private val adventureDboFactory: AdventureDboFactory, ) { - val adventure = database.adventureDao().let { database -> + private val adventures = database.adventureDao().let { database -> combine( database.getBooksFlow(), database.getStoriesFlow(), @@ -50,6 +52,31 @@ class AdventureRepository @Inject constructor( ) } + fun bookFlow(): Flow> { + return adventures + } + + fun storyFlow( + bookTitle: String, + ): Flow> { + return adventures.map { adventures -> + adventures.filter { adventure -> + adventure.bookTitle == bookTitle + } + } + } + + fun adventureFlow( + bookTitle: String, + adventureTitle: String, + ): Flow { + return adventures.map { adventures -> + adventures.firstOrNull { adventure -> + adventure.bookTitle == bookTitle && adventure.storyTitle == adventureTitle + } + } + } + @Throws(IncompatibleSheetStructure::class, Exception::class) suspend fun fetchBooks() { val database = database.adventureDao() @@ -177,18 +204,6 @@ class AdventureRepository @Inject constructor( ) } - fun find(bookTitle: String): List { - return adventure.value.filter { adventure -> - adventure.bookTitle == bookTitle - } - } - - fun find(bookTitle: String, adventureTitle: String): Adventure? { - return adventure.value.firstOrNull { adventure -> - adventure.bookTitle == bookTitle && adventure.storyTitle == adventureTitle - } - } - @Throws(IncompatibleSheetStructure::class, Exception::class) private suspend fun fetchAdventureBooks(): List { return googleRepository.fetch { sheet -> diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/book/AdventureBooksViewModel.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/book/AdventureBooksViewModel.kt index e719248..c33420b 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/book/AdventureBooksViewModel.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/book/AdventureBooksViewModel.kt @@ -29,7 +29,7 @@ class AdventureBooksViewModel @Inject constructor( private val _isLoading = mutableStateOf(false) val isLoading: State get() = _isLoading - private val _books = adventureRepository.adventure + private val _books = adventureRepository.bookFlow() .map { adventures -> adventures .map { adventure -> diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/chapter/AdventureStoriesViewModel.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/chapter/AdventureStoriesViewModel.kt index 322ef12..01f304f 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/chapter/AdventureStoriesViewModel.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/chapter/AdventureStoriesViewModel.kt @@ -36,7 +36,7 @@ class AdventureStoriesViewModel @Inject constructor( argument.bookTitle } - private val _chapters = adventureRepository.adventure + private val _chapters = adventureRepository.storyFlow(bookTitle = argument.bookTitle) .map { adventures -> adventures .filter { it.bookTitle == argument.bookTitle && it.documentId == argument.documentId } diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/detail/AdventureDetailViewModel.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/detail/AdventureDetailViewModel.kt index fe205ef..aa707b6 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/detail/AdventureDetailViewModel.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/adventure/detail/AdventureDetailViewModel.kt @@ -1,14 +1,22 @@ package com.pixelized.rplexicon.ui.screens.adventure.detail +import android.net.Uri +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf -import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.pixelized.rplexicon.data.model.adventure.AdventureLine.Format import com.pixelized.rplexicon.data.repository.adventure.AdventureRepository import com.pixelized.rplexicon.ui.navigation.screens.adventureDetailArgument import com.pixelized.rplexicon.ui.screens.adventure.detail.AdventureLineUio.Style import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn import javax.inject.Inject @HiltViewModel @@ -17,44 +25,76 @@ class AdventureDetailViewModel @Inject constructor( savedStateHandle: SavedStateHandle, ) : ViewModel() { private val argument = savedStateHandle.adventureDetailArgument - private val _detail = mutableStateOf( - adventureRepository.find( - bookTitle = argument.bookTitle, - adventureTitle = argument.adventureTitle, - ) + + private val detail = adventureRepository.adventureFlow( + bookTitle = argument.bookTitle, + adventureTitle = argument.adventureTitle, + ).stateIn( + scope = viewModelScope, + started = SharingStarted.Lazily, + initialValue = null, ) - val background = derivedStateOf { - _detail.value?.storyBackground - } + val background: State + @Composable + get() = remember(detail) { + detail.map { it?.storyBackground } + }.collectAsState(initial = null) - val adventure = derivedStateOf { - _detail.value?.story?.map { line -> - AdventureLineUio( - text = line.text, - style = when (line.format) { - Format.TITLE -> Style.TITLE - Format.SUB_TITLE -> Style.SUB_TITLE - Format.CHAPTER -> Style.CHAPTER - Format.PARAGRAPH -> Style.PARAGRAPH - Format.DIALOGUE -> Style.DIALOGUE - Format.ANNEX -> Style.ANNEX - Format.LEGEND -> Style.LEGEND - }, - ) - } ?: emptyList() - } + val adventure: State> + @Composable + get() = remember(detail) { + detail + .map { adventure -> + adventure?.story?.map { line -> + AdventureLineUio( + text = line.text, + style = when (line.format) { + Format.TITLE -> Style.TITLE + Format.SUB_TITLE -> Style.SUB_TITLE + Format.CHAPTER -> Style.CHAPTER + Format.PARAGRAPH -> Style.PARAGRAPH + Format.DIALOGUE -> Style.DIALOGUE + Format.ANNEX -> Style.ANNEX + Format.LEGEND -> Style.LEGEND + }, + ) + } ?: emptyList() + } + }.collectAsState(initial = emptyList()) - private val titleCell = derivedStateOf { - adventure.value.let { adventures -> - adventures.firstOrNull { it.style == Style.TITLE } - ?: adventures.firstOrNull() + private val titleCell: State + @Composable + get() = adventure.let { state -> + remember(state) { + derivedStateOf { + state.value.let { adventures -> + adventures.firstOrNull { it.style == Style.TITLE } + ?: adventures.firstOrNull() + } + } + } + } + + val title: State + @Composable + get() = titleCell.let { state -> + remember(state) { + derivedStateOf { + state.value?.text ?: "" + } + } + } + + val titleIndex: State + @Composable + get() { + val cell = titleCell + val adv = adventure + return remember(cell, adv) { + derivedStateOf { + adv.value.indexOf(cell.value) + } + } } - } - val title = derivedStateOf { - titleCell.value?.text ?: "" - } - val titleIndex = derivedStateOf { - adventure.value.indexOf(titleCell.value) - } } \ No newline at end of file