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

View File

@ -18,9 +18,6 @@
package com.sadellie.unitto.screens.second 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.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.sadellie.unitto.data.units.AbstractUnit 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 com.sadellie.unitto.data.units.database.MyBasedUnitsRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers 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.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import javax.inject.Inject import javax.inject.Inject
@ -39,18 +40,26 @@ import javax.inject.Inject
class SecondViewModel @Inject constructor( class SecondViewModel @Inject constructor(
private val basedUnitRepository: MyBasedUnitsRepository, private val basedUnitRepository: MyBasedUnitsRepository,
private val allUnitsRepository: AllUnitsRepository, private val allUnitsRepository: AllUnitsRepository,
private val unitGroupsRepository: UnitGroupsRepository unitGroupsRepository: UnitGroupsRepository
) : ViewModel() { ) : ViewModel() {
var uiState: SecondScreenUIState by mutableStateOf(SecondScreenUIState()) private val _uiStateFlow = MutableStateFlow(SecondScreenUIState())
private set
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() { fun toggleFavoritesOnly() {
uiState = uiState.copy(favoritesOnly = !uiState.favoritesOnly) _uiStateFlow.value = _uiStateFlow.value.copy(favoritesOnly = !_uiStateFlow.value.favoritesOnly)
} }
fun onSearchQueryChange(newValue: String) { 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. * @param unitGroup Chip to change to.
*/ */
fun setSelectedChip(unitGroup: UnitGroup) { 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. * @param unitGroup [UnitGroup], currently selected chip.
*/ */
fun toggleSelectedChip(unitGroup: UnitGroup) { fun toggleSelectedChip(unitGroup: UnitGroup) {
val newUnitGroup = if (uiState.chosenUnitGroup == unitGroup) null else unitGroup val newUnitGroup = if (_uiStateFlow.value.chosenUnitGroup == unitGroup) null else unitGroup
uiState = uiState.copy(chosenUnitGroup = newUnitGroup) _uiStateFlow.value = _uiStateFlow.value.copy(chosenUnitGroup = newUnitGroup)
} }
/** /**
@ -90,13 +99,13 @@ class SecondViewModel @Inject constructor(
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
val unitsToShow = allUnitsRepository.filterUnits( val unitsToShow = allUnitsRepository.filterUnits(
hideBrokenCurrencies = hideBrokenCurrencies, hideBrokenCurrencies = hideBrokenCurrencies,
chosenUnitGroup = uiState.chosenUnitGroup, chosenUnitGroup = _uiStateFlow.value.chosenUnitGroup,
favoritesOnly = uiState.favoritesOnly, favoritesOnly = _uiStateFlow.value.favoritesOnly,
searchQuery = uiState.searchQuery, searchQuery = _uiStateFlow.value.searchQuery,
allUnitsGroups = uiState.shownUnitGroups 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)
}
}
}
} }