State flow for unit selection screens

This commit is contained in:
Sad Ellie 2022-08-22 22:42:50 +03:00
parent f6c1d44be2
commit 5621848c5a
2 changed files with 39 additions and 37 deletions

View File

@ -45,6 +45,7 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.sadellie.unitto.R
import com.sadellie.unitto.data.units.AbstractUnit
import com.sadellie.unitto.data.units.UnitGroup
@ -73,7 +74,7 @@ fun LeftSideScreen(
navigateToSettingsActtion: () -> Unit,
selectAction: (AbstractUnit) -> Unit
) {
val uiState = viewModel.uiState
val uiState = viewModel.mainFlow.collectAsStateWithLifecycle()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val chipsRowLazyListState = rememberLazyListState()
val focusManager = LocalFocusManager.current
@ -96,12 +97,12 @@ fun LeftSideScreen(
) {
SearchBar(
title = stringResource(R.string.units_screen_from),
value = uiState.searchQuery,
value = uiState.value.searchQuery,
onValueChange = {
viewModel.onSearchQueryChange(it)
viewModel.loadUnitsToShow(true)
},
favoritesOnly = uiState.favoritesOnly,
favoritesOnly = uiState.value.favoritesOnly,
favoriteAction = {
viewModel.toggleFavoritesOnly()
viewModel.loadUnitsToShow(true)
@ -111,8 +112,8 @@ fun LeftSideScreen(
scrollBehavior = scrollBehavior
)
ChipsRow(
chosenUnitGroup = viewModel.uiState.chosenUnitGroup,
items = uiState.shownUnitGroups,
chosenUnitGroup = uiState.value.chosenUnitGroup,
items = uiState.value.shownUnitGroups,
selectAction = {
viewModel.toggleSelectedChip(it)
viewModel.loadUnitsToShow(true)
@ -124,14 +125,14 @@ fun LeftSideScreen(
}
) { paddingValues ->
Crossfade(
targetState = uiState.unitsToShow.isEmpty(),
targetState = uiState.value.unitsToShow.isEmpty(),
modifier = Modifier.padding(paddingValues)
) { noUnits ->
if (noUnits) {
SearchPlaceholder(navigateToSettingsActtion = navigateToSettingsActtion)
} else {
LazyColumn(Modifier.fillMaxSize()) {
uiState.unitsToShow.forEach { (unitGroup, listOfUnits) ->
uiState.value.unitsToShow.forEach { (unitGroup, listOfUnits) ->
item(unitGroup.name) {
UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup)
}
@ -163,7 +164,7 @@ fun LeftSideScreen(
viewModel.setSelectedChip(currentUnit.group)
viewModel.loadUnitsToShow(true)
val groupToSelect = uiState.shownUnitGroups.indexOf(currentUnit.group)
val groupToSelect = uiState.value.shownUnitGroups.indexOf(currentUnit.group)
if (groupToSelect > -1) {
chipsRowLazyListState.animateScrollToItem(groupToSelect)
}
@ -191,7 +192,7 @@ fun RightSideScreen(
inputValue: BigDecimal,
unitFrom: AbstractUnit
) {
val uiState = viewModel.uiState
val uiState = viewModel.mainFlow.collectAsStateWithLifecycle()
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
val focusManager = LocalFocusManager.current
@ -200,12 +201,12 @@ fun RightSideScreen(
topBar = {
SearchBar(
title = stringResource(R.string.units_screen_from),
value = uiState.searchQuery,
value = uiState.value.searchQuery,
onValueChange = {
viewModel.onSearchQueryChange(it)
viewModel.loadUnitsToShow(false)
},
favoritesOnly = uiState.favoritesOnly,
favoritesOnly = uiState.value.favoritesOnly,
favoriteAction = {
viewModel.toggleFavoritesOnly()
viewModel.loadUnitsToShow(false)
@ -217,14 +218,14 @@ fun RightSideScreen(
}
) { paddingValues ->
Crossfade(
targetState = uiState.unitsToShow.isEmpty(),
targetState = uiState.value.unitsToShow.isEmpty(),
modifier = Modifier.padding(paddingValues)
) { noUnits ->
if (noUnits) {
SearchPlaceholder(navigateToSettingsActtion = navigateToSettingsActtion)
} else {
LazyColumn(Modifier.fillMaxSize()) {
uiState.unitsToShow.forEach { (unitGroup, listOfUnits) ->
uiState.value.unitsToShow.forEach { (unitGroup, listOfUnits) ->
item(unitGroup.name) {
UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup)
}

View File

@ -18,9 +18,6 @@
package com.sadellie.unitto.screens.second
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sadellie.unitto.data.units.AbstractUnit
@ -31,6 +28,10 @@ import com.sadellie.unitto.data.units.database.MyBasedUnit
import com.sadellie.unitto.data.units.database.MyBasedUnitsRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
@ -39,18 +40,26 @@ import javax.inject.Inject
class SecondViewModel @Inject constructor(
private val basedUnitRepository: MyBasedUnitsRepository,
private val allUnitsRepository: AllUnitsRepository,
private val unitGroupsRepository: UnitGroupsRepository
unitGroupsRepository: UnitGroupsRepository
) : ViewModel() {
var uiState: SecondScreenUIState by mutableStateOf(SecondScreenUIState())
private set
private val _uiStateFlow = MutableStateFlow(SecondScreenUIState())
val mainFlow = combine(_uiStateFlow, unitGroupsRepository.shownUnitGroups) { uiState, shown ->
return@combine uiState.copy(shownUnitGroups = shown)
}
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5000),
initialValue = SecondScreenUIState()
)
fun toggleFavoritesOnly() {
uiState = uiState.copy(favoritesOnly = !uiState.favoritesOnly)
_uiStateFlow.value = _uiStateFlow.value.copy(favoritesOnly = !_uiStateFlow.value.favoritesOnly)
}
fun onSearchQueryChange(newValue: String) {
uiState = uiState.copy(searchQuery = newValue)
_uiStateFlow.value = _uiStateFlow.value.copy(searchQuery = newValue)
}
/**
@ -59,7 +68,7 @@ class SecondViewModel @Inject constructor(
* @param unitGroup Chip to change to.
*/
fun setSelectedChip(unitGroup: UnitGroup) {
uiState = uiState.copy(chosenUnitGroup = unitGroup)
_uiStateFlow.value = _uiStateFlow.value.copy(chosenUnitGroup = unitGroup)
}
/**
@ -71,8 +80,8 @@ class SecondViewModel @Inject constructor(
* @param unitGroup [UnitGroup], currently selected chip.
*/
fun toggleSelectedChip(unitGroup: UnitGroup) {
val newUnitGroup = if (uiState.chosenUnitGroup == unitGroup) null else unitGroup
uiState = uiState.copy(chosenUnitGroup = newUnitGroup)
val newUnitGroup = if (_uiStateFlow.value.chosenUnitGroup == unitGroup) null else unitGroup
_uiStateFlow.value = _uiStateFlow.value.copy(chosenUnitGroup = newUnitGroup)
}
/**
@ -90,13 +99,13 @@ class SecondViewModel @Inject constructor(
withContext(Dispatchers.Default) {
val unitsToShow = allUnitsRepository.filterUnits(
hideBrokenCurrencies = hideBrokenCurrencies,
chosenUnitGroup = uiState.chosenUnitGroup,
favoritesOnly = uiState.favoritesOnly,
searchQuery = uiState.searchQuery,
allUnitsGroups = uiState.shownUnitGroups
chosenUnitGroup = _uiStateFlow.value.chosenUnitGroup,
favoritesOnly = _uiStateFlow.value.favoritesOnly,
searchQuery = _uiStateFlow.value.searchQuery,
allUnitsGroups = _uiStateFlow.value.shownUnitGroups
)
uiState = uiState.copy(unitsToShow = unitsToShow)
_uiStateFlow.value = _uiStateFlow.value.copy(unitsToShow = unitsToShow)
}
}
}
@ -119,12 +128,4 @@ class SecondViewModel @Inject constructor(
)
}
}
init {
viewModelScope.launch {
unitGroupsRepository.shownUnitGroups.collect {
uiState = uiState.copy(shownUnitGroups = it)
}
}
}
}