Convert the AdventureDetailScreen to flow instead of snapshot.

This commit is contained in:
Andres Gomez, Thomas (ITDV RL) 2024-06-21 14:06:50 +02:00
parent acb76e72cf
commit e62b558c21
4 changed files with 106 additions and 51 deletions

View file

@ -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<List<Adventure>> {
return adventures
}
fun storyFlow(
bookTitle: String,
): Flow<List<Adventure>> {
return adventures.map { adventures ->
adventures.filter { adventure ->
adventure.bookTitle == bookTitle
}
}
}
fun adventureFlow(
bookTitle: String,
adventureTitle: String,
): Flow<Adventure?> {
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<Adventure> {
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<AdventureBook> {
return googleRepository.fetch { sheet ->

View file

@ -29,7 +29,7 @@ class AdventureBooksViewModel @Inject constructor(
private val _isLoading = mutableStateOf(false)
val isLoading: State<Boolean> get() = _isLoading
private val _books = adventureRepository.adventure
private val _books = adventureRepository.bookFlow()
.map { adventures ->
adventures
.map { adventure ->

View file

@ -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 }

View file

@ -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,19 +25,28 @@ class AdventureDetailViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
) : ViewModel() {
private val argument = savedStateHandle.adventureDetailArgument
private val _detail = mutableStateOf(
adventureRepository.find(
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<Uri?>
@Composable
get() = remember(detail) {
detail.map { it?.storyBackground }
}.collectAsState(initial = null)
val adventure = derivedStateOf {
_detail.value?.story?.map { line ->
val adventure: State<List<AdventureLineUio>>
@Composable
get() = remember(detail) {
detail
.map { adventure ->
adventure?.story?.map { line ->
AdventureLineUio(
text = line.text,
style = when (line.format) {
@ -44,17 +61,40 @@ class AdventureDetailViewModel @Inject constructor(
)
} ?: emptyList()
}
}.collectAsState(initial = emptyList())
private val titleCell = derivedStateOf {
adventure.value.let { adventures ->
private val titleCell: State<AdventureLineUio?>
@Composable
get() = adventure.let { state ->
remember(state) {
derivedStateOf {
state.value.let { adventures ->
adventures.firstOrNull { it.style == Style.TITLE }
?: adventures.firstOrNull()
}
}
val title = derivedStateOf {
titleCell.value?.text ?: ""
}
val titleIndex = derivedStateOf {
adventure.value.indexOf(titleCell.value)
}
val title: State<String>
@Composable
get() = titleCell.let { state ->
remember(state) {
derivedStateOf {
state.value?.text ?: ""
}
}
}
val titleIndex: State<Int>
@Composable
get() {
val cell = titleCell
val adv = adventure
return remember(cell, adv) {
derivedStateOf {
adv.value.indexOf(cell.value)
}
}
}
}