Skip to content

Commit

Permalink
Refactor unit selector screens
Browse files Browse the repository at this point in the history
decrease duplicate logic in ConverterViewModel
  • Loading branch information
sadellie committed Feb 10, 2024
1 parent 9d76c16 commit 7cbbb84
Show file tree
Hide file tree
Showing 10 changed files with 404 additions and 273 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,45 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, T9, R> combine(
)
}

@Suppress("UNCHECKED_CAST", "UNUSED")
fun <T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, R> combine(
flow: Flow<T1>,
flow2: Flow<T2>,
flow3: Flow<T3>,
flow4: Flow<T4>,
flow5: Flow<T5>,
flow6: Flow<T6>,
flow7: Flow<T7>,
flow8: Flow<T8>,
flow9: Flow<T9>,
flow10: Flow<T10>,
transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) -> R,
): Flow<R> =
kotlinx.coroutines.flow.combine(
flow,
flow2,
flow3,
flow4,
flow5,
flow6,
flow7,
flow8,
flow9,
flow10
) { args: Array<*> ->
transform(
args[0] as T1,
args[1] as T2,
args[2] as T3,
args[3] as T4,
args[4] as T5,
args[5] as T6,
args[6] as T7,
args[7] as T8,
args[8] as T9,
args[9] as T10,
)
}

fun <T> Flow<T>.stateIn(scope: CoroutineScope, initialValue: T): StateFlow<T> =
stateIn(scope, SharingStarted.WhileSubscribed(5000L), initialValue)
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@ import java.util.Locale
@Composable
internal fun ConverterRoute(
viewModel: ConverterViewModel = hiltViewModel(),
navigateToLeftScreen: () -> Unit,
navigateToRightScreen: () -> Unit,
navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit,
navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit,
navigateToMenu: () -> Unit,
navigateToSettings: () -> Unit,
) {
Expand All @@ -124,8 +124,8 @@ internal fun ConverterRoute(
@Composable
private fun ConverterScreen(
uiState: UnitConverterUIState,
navigateToLeftScreen: () -> Unit,
navigateToRightScreen: () -> Unit,
navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit,
navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit,
navigateToSettings: () -> Unit,
navigateToMenu: () -> Unit,
swapUnits: () -> Unit,
Expand Down Expand Up @@ -207,9 +207,9 @@ private fun NumberBase(
onValueChange: (TextFieldValue) -> Unit,
processInput: (String) -> Unit,
deleteDigit: () -> Unit,
navigateToLeftScreen: () -> Unit,
navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit,
swapUnits: () -> Unit,
navigateToRightScreen: () -> Unit,
navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit,
clearInput: () -> Unit,
) {
PortraitLandscape(
Expand Down Expand Up @@ -239,8 +239,8 @@ private fun NumberBase(
unitFromLabel = stringResource(uiState.unitFrom.displayName),
unitToLabel = stringResource(uiState.unitTo.displayName),
swapUnits = swapUnits,
navigateToLeftScreen = navigateToLeftScreen,
navigateToRightScreen = navigateToRightScreen
navigateToLeftScreen = { navigateToLeftScreen(uiState) },
navigateToRightScreen = { navigateToRightScreen(uiState) }
)
}
},
Expand All @@ -263,9 +263,9 @@ private fun Default(
onFocusOnInput2: (Boolean) -> Unit,
processInput: (String) -> Unit,
deleteDigit: () -> Unit,
navigateToLeftScreen: () -> Unit,
navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit,
swapUnits: () -> Unit,
navigateToRightScreen: () -> Unit,
navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit,
clearInput: () -> Unit,
refreshCurrencyRates: (AbstractUnit) -> Unit,
addBracket: () -> Unit,
Expand Down Expand Up @@ -327,7 +327,9 @@ private fun Default(
.weight(1f)
) {
ExpressionTextField(
modifier = Modifier.fillMaxWidth().weight(1f),
modifier = Modifier
.fillMaxWidth()
.weight(1f),
value = uiState.input1,
minRatio = 0.7f,
onValueChange = onValueChange,
Expand All @@ -345,7 +347,9 @@ private fun Default(
.weight(1f)
) {
ExpressionTextField(
modifier = Modifier.fillMaxWidth().weight(1f)
modifier = Modifier
.fillMaxWidth()
.weight(1f)
.onFocusEvent { state -> onFocusOnInput2(state.hasFocus) },
value = uiState.input2,
minRatio = 0.7f,
Expand Down Expand Up @@ -405,8 +409,8 @@ private fun Default(
unitFromLabel = stringResource(uiState.unitFrom.displayName),
unitToLabel = stringResource(uiState.unitTo.displayName),
swapUnits = swapUnits,
navigateToLeftScreen = navigateToLeftScreen,
navigateToRightScreen = navigateToRightScreen
navigateToLeftScreen = { navigateToLeftScreen(uiState) },
navigateToRightScreen = { navigateToRightScreen(uiState) }
)
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import com.sadellie.unitto.data.common.isExpression
import com.sadellie.unitto.data.common.stateIn
import com.sadellie.unitto.data.converter.UnitID
import com.sadellie.unitto.data.model.UnitGroup
import com.sadellie.unitto.data.model.UnitsListSorting
import com.sadellie.unitto.data.model.repository.UnitsRepository
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
import com.sadellie.unitto.data.model.unit.AbstractUnit
Expand All @@ -45,12 +44,10 @@ import io.github.sadellie.evaluatto.ExpressionException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand All @@ -74,13 +71,6 @@ internal class ConverterViewModel @Inject constructor(
private val _unitFrom = MutableStateFlow<AbstractUnit?>(null)
private val _unitTo = MutableStateFlow<AbstractUnit?>(null)

private val _leftQuery = MutableStateFlow(TextFieldValue())
private val _leftUnits = MutableStateFlow<Map<UnitGroup, List<AbstractUnit>>>(emptyMap())
private val _leftUnitGroup = MutableStateFlow<UnitGroup?>(null)

private val _rightQuery = MutableStateFlow(TextFieldValue())
private val _rightUnits = MutableStateFlow<Map<UnitGroup, List<AbstractUnit>>>(emptyMap())

private val _currenciesState = MutableStateFlow<CurrencyRateUpdateState>(CurrencyRateUpdateState.Nothing)
private var _loadCurrenciesJob: Job? = null

Expand Down Expand Up @@ -160,81 +150,6 @@ internal class ConverterViewModel @Inject constructor(
}
.stateIn(viewModelScope, UnitConverterUIState.Loading)

val leftSideUIState = combine(
_unitFrom,
_leftQuery,
_leftUnits,
_leftUnitGroup,
userPrefsRepository.converterPrefs,
unitsRepo.units
) { unitFrom, query, units, unitGroup, prefs, _ ->
unitFrom ?: return@combine LeftSideUIState.Loading

return@combine LeftSideUIState.Ready(
unitFrom = unitFrom,
sorting = prefs.unitConverterSorting,
shownUnitGroups = prefs.shownUnitGroups,
favorites = prefs.unitConverterFavoritesOnly,
query = query,
units = units,
unitGroup = unitGroup
)
}
.mapLatest {
if (it !is LeftSideUIState.Ready) return@mapLatest it

filterUnitsLeft(
query = it.query,
unitGroup = it.unitGroup,
favoritesOnly = it.favorites,
sorting = it.sorting,
shownUnitGroups = it.shownUnitGroups,
)
it
}
.stateIn(viewModelScope, SharingStarted.Lazily, LeftSideUIState.Loading)

val rightSideUIState = combine(
_unitFrom,
_unitTo,
_input1,
_calculation,
_rightQuery,
_rightUnits,
userPrefsRepository.converterPrefs,
_currenciesState,
unitsRepo.units,
) { unitFrom, unitTo, input, calculation, query, units, prefs, currenciesState, _ ->
unitFrom ?: return@combine RightSideUIState.Loading
unitTo ?: return@combine RightSideUIState.Loading

return@combine RightSideUIState.Ready(
unitFrom = unitFrom,
unitTo = unitTo,
sorting = prefs.unitConverterSorting,
favorites = prefs.unitConverterFavoritesOnly,
input = (calculation?.toPlainString() ?: input.text).replace(Token.Operator.minus, "-"),
scale = prefs.precision,
outputFormat = prefs.outputFormat,
formatterSymbols = AllFormatterSymbols.getById(prefs.separator),
currencyRateUpdateState = currenciesState,
query = query,
units = units,
)
}
.mapLatest {
if (it !is RightSideUIState.Ready) return@mapLatest it

filterUnitsRight(
query = it.query,
unitGroup = it.unitFrom.group,
favoritesOnly = it.favorites,
sorting = it.sorting,
)
it
}
.stateIn(viewModelScope, SharingStarted.Lazily, RightSideUIState.Loading)

fun swapUnits() {
_unitFrom
.getAndUpdate { _unitTo.value }
Expand Down Expand Up @@ -380,56 +295,6 @@ internal class ConverterViewModel @Inject constructor(
}
}

fun queryChangeLeft(query: TextFieldValue) = _leftQuery.update { query }

fun queryChangeRight(query: TextFieldValue) = _rightQuery.update { query }

fun favoritesOnlyChange(enabled: Boolean) = viewModelScope.launch {
userPrefsRepository.updateUnitConverterFavoritesOnly(enabled)
}

fun updateUnitGroupLeft(unitGroup: UnitGroup?) = _leftUnitGroup.update { unitGroup }

fun favoriteUnit(unit: AbstractUnit) = viewModelScope.launch {
unitsRepo.favorite(unit)
}

private fun filterUnitsLeft(
query: TextFieldValue,
unitGroup: UnitGroup?,
favoritesOnly: Boolean,
sorting: UnitsListSorting,
shownUnitGroups: List<UnitGroup>,
) = viewModelScope.launch(Dispatchers.Default) {
_leftUnits.update {
unitsRepo.filterUnits(
query = query.text,
unitGroup = unitGroup,
favoritesOnly = favoritesOnly,
hideBrokenUnits = false,
sorting = sorting,
shownUnitGroups = shownUnitGroups
)
}
}

private fun filterUnitsRight(
query: TextFieldValue,
unitGroup: UnitGroup?,
favoritesOnly: Boolean,
sorting: UnitsListSorting,
) = viewModelScope.launch(Dispatchers.Default) {
_rightUnits.update {
unitsRepo.filterUnits(
query = query.text,
unitGroup = unitGroup,
favoritesOnly = favoritesOnly,
hideBrokenUnits = true,
sorting = sorting,
)
}
}

private fun convertDefault(
unitFrom: DefaultUnit,
unitTo: DefaultUnit,
Expand Down

This file was deleted.

Loading

0 comments on commit 7cbbb84

Please sign in to comment.