I have no idea what i'm doing

This commit is contained in:
Sad Ellie 2023-06-02 16:52:04 +03:00
parent f1f1b7841e
commit 4354d00652
9 changed files with 46 additions and 48 deletions

View File

@ -37,7 +37,6 @@ import java.math.BigDecimal
* @property renderedShortName Used as cache. Stores short name string for this specific device. Need for * @property renderedShortName Used as cache. Stores short name string for this specific device. Need for
* search functionality. * search functionality.
* @property isFavorite Whether this unit is favorite. * @property isFavorite Whether this unit is favorite.
* @property isEnabled Whether we need to show this unit or not
* @property pairedUnit Latest paired unit on the right * @property pairedUnit Latest paired unit on the right
* @property counter The amount of time this unit was chosen * @property counter The amount of time this unit was chosen
*/ */
@ -50,7 +49,6 @@ abstract class AbstractUnit(
var renderedName: String = String(), var renderedName: String = String(),
var renderedShortName: String = String(), var renderedShortName: String = String(),
var isFavorite: Boolean = false, var isFavorite: Boolean = false,
var isEnabled: Boolean = true,
var pairedUnit: String? = null, var pairedUnit: String? = null,
var counter: Int = 0 var counter: Int = 0
) { ) {

View File

@ -50,6 +50,9 @@ class DefaultUnit(
value: BigDecimal, value: BigDecimal,
scale: Int scale: Int
): BigDecimal { ): BigDecimal {
// Avoid division by zero
if (unitTo.basicUnit.compareTo(BigDecimal.ZERO) == 0) return BigDecimal.ZERO
return this return this
.basicUnit .basicUnit
.setScale(MAX_PRECISION) .setScale(MAX_PRECISION)

View File

@ -48,6 +48,9 @@ import com.sadellie.unitto.data.units.collections.temperatureCollection
import com.sadellie.unitto.data.units.collections.timeCollection import com.sadellie.unitto.data.units.collections.timeCollection
import com.sadellie.unitto.data.units.collections.torqueCollection import com.sadellie.unitto.data.units.collections.torqueCollection
import com.sadellie.unitto.data.units.collections.volumeCollection import com.sadellie.unitto.data.units.collections.volumeCollection
import com.sadellie.unitto.data.units.remote.CurrencyApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.math.BigDecimal import java.math.BigDecimal
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@ -123,8 +126,8 @@ class AllUnitsRepository @Inject constructor() {
/** /**
* Filter [AllUnitsRepository.allUnits] and group them. * Filter [AllUnitsRepository.allUnits] and group them.
* *
* @param hideBrokenCurrencies When set to True will remove [AbstractUnit]s that have * @param hideBrokenUnits When set to True will remove [AbstractUnit]s that have
* [AbstractUnit.isEnabled] set to False, which means that [AbstractUnit] can not be used. * [AbstractUnit.basicUnit] set to [BigDecimal.ZERO] (comes from currencies API).
* @param chosenUnitGroup If provided will scope list to a specific [UnitGroup]. * @param chosenUnitGroup If provided will scope list to a specific [UnitGroup].
* @param favoritesOnly When True will filter only [AbstractUnit]s with [AbstractUnit.isFavorite] * @param favoritesOnly When True will filter only [AbstractUnit]s with [AbstractUnit.isFavorite]
* set to True. * set to True.
@ -135,7 +138,7 @@ class AllUnitsRepository @Inject constructor() {
* @return Grouped by [UnitGroup] list of [AbstractUnit]s. * @return Grouped by [UnitGroup] list of [AbstractUnit]s.
*/ */
fun filterUnits( fun filterUnits(
hideBrokenCurrencies: Boolean, hideBrokenUnits: Boolean,
chosenUnitGroup: UnitGroup?, chosenUnitGroup: UnitGroup?,
favoritesOnly: Boolean, favoritesOnly: Boolean,
searchQuery: String, searchQuery: String,
@ -153,8 +156,8 @@ class AllUnitsRepository @Inject constructor() {
if (favoritesOnly) { if (favoritesOnly) {
units = units.filter { it.isFavorite } units = units.filter { it.isFavorite }
} }
if (hideBrokenCurrencies) { if (hideBrokenUnits) {
units = units.filter { it.isEnabled } units = units.filter { it.basicUnit > BigDecimal.ZERO }
} }
units = when (sorting) { units = when (sorting) {
@ -198,22 +201,20 @@ class AllUnitsRepository @Inject constructor() {
/** /**
* Update [AbstractUnit.basicUnit] properties for currencies from [currencyCollection]. * Update [AbstractUnit.basicUnit] properties for currencies from [currencyCollection].
* *
* @param conversions Map: [AbstractUnit.unitId] and [BigDecimal] that will replace current * @param unitFrom Base unit
* [AbstractUnit.basicUnit].
*/ */
fun updateBasicUnitsForCurrencies( suspend fun updateBasicUnitsForCurrencies(
conversions: Map<String, BigDecimal> unitFrom: AbstractUnit
) { ) = withContext(Dispatchers.IO) {
val conversions: Map<String, BigDecimal> = CurrencyApi.retrofitService.getCurrencyPairs(unitFrom.unitId).currency
getCollectionByGroup(UnitGroup.CURRENCY).forEach { getCollectionByGroup(UnitGroup.CURRENCY).forEach {
// Getting rates from map. We set ZERO as default so that it can be skipped // Getting rates from map. We set ZERO as default so that it can be skipped
val rate = conversions.getOrElse(it.unitId) { BigDecimal.ZERO } val rate = conversions.getOrElse(it.unitId) { BigDecimal.ZERO }
// We make sure that we don't divide by zero // We make sure that we don't divide by zero
if (rate > BigDecimal.ZERO) { if (rate > BigDecimal.ZERO) {
it.isEnabled = true
it.basicUnit = BigDecimal.ONE.setScale(MAX_PRECISION).div(rate) it.basicUnit = BigDecimal.ONE.setScale(MAX_PRECISION).div(rate)
} else { } else {
// Hiding broken currencies it.basicUnit = BigDecimal.ZERO
it.isEnabled = false
} }
} }
} }

View File

@ -23,6 +23,7 @@ import com.sadellie.unitto.data.model.AbstractUnit
import com.sadellie.unitto.data.model.UnitGroup import com.sadellie.unitto.data.model.UnitGroup
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
import java.math.BigDecimal
class AllUnitsRepositoryTest { class AllUnitsRepositoryTest {
@ -34,7 +35,7 @@ class AllUnitsRepositoryTest {
fun filterAllUnitsNoFiltersLeft() { fun filterAllUnitsNoFiltersLeft() {
// No filters applied, empty search query, from Left side list // No filters applied, empty search query, from Left side list
val result = allUnitsRepository.filterUnits( val result = allUnitsRepository.filterUnits(
hideBrokenCurrencies = false, hideBrokenUnits = false,
chosenUnitGroup = null, chosenUnitGroup = null,
favoritesOnly = false, favoritesOnly = false,
searchQuery = "", searchQuery = "",
@ -51,7 +52,7 @@ class AllUnitsRepositoryTest {
// All filters applied, from Left side list // All filters applied, from Left side list
val result = allUnitsRepository.filterUnits( val result = allUnitsRepository.filterUnits(
hideBrokenCurrencies = false, hideBrokenUnits = false,
chosenUnitGroup = UnitGroup.SPEED, chosenUnitGroup = UnitGroup.SPEED,
favoritesOnly = true, favoritesOnly = true,
searchQuery = "kilometer per hour", searchQuery = "kilometer per hour",
@ -68,7 +69,7 @@ class AllUnitsRepositoryTest {
fun filterAllUnitsChosenGroupLeft() { fun filterAllUnitsChosenGroupLeft() {
// Only specific group is needed, left side screen // Only specific group is needed, left side screen
val result = allUnitsRepository.filterUnits( val result = allUnitsRepository.filterUnits(
hideBrokenCurrencies = false, hideBrokenUnits = false,
chosenUnitGroup = UnitGroup.TIME, chosenUnitGroup = UnitGroup.TIME,
favoritesOnly = false, favoritesOnly = false,
searchQuery = "", searchQuery = "",
@ -83,7 +84,7 @@ class AllUnitsRepositoryTest {
allUnitsRepository.getById(MyUnitIDS.kilometer).isFavorite = true allUnitsRepository.getById(MyUnitIDS.kilometer).isFavorite = true
// Only favorite units, left side screen // Only favorite units, left side screen
val result = allUnitsRepository.filterUnits( val result = allUnitsRepository.filterUnits(
hideBrokenCurrencies = false, hideBrokenUnits = false,
chosenUnitGroup = null, chosenUnitGroup = null,
favoritesOnly = true, favoritesOnly = true,
searchQuery = "", searchQuery = "",
@ -101,7 +102,7 @@ class AllUnitsRepositoryTest {
// Only search query is entered, other filters are not set, left side screen // Only search query is entered, other filters are not set, left side screen
val result = allUnitsRepository.filterUnits( val result = allUnitsRepository.filterUnits(
hideBrokenCurrencies = false, hideBrokenUnits = false,
chosenUnitGroup = null, chosenUnitGroup = null,
favoritesOnly = false, favoritesOnly = false,
searchQuery = "kilometer per hour", searchQuery = "kilometer per hour",
@ -118,10 +119,10 @@ class AllUnitsRepositoryTest {
fun filterAllUnitsHideBrokenCurrencies() { fun filterAllUnitsHideBrokenCurrencies() {
allUnitsRepository allUnitsRepository
.getById(MyUnitIDS.currency_btc) .getById(MyUnitIDS.currency_btc)
.apply { isEnabled = false } .apply { basicUnit = BigDecimal.ZERO }
// Hide broken currencies (i.e. cannot be used for conversion at the moment) // Hide broken currencies (i.e. cannot be used for conversion at the moment)
val result = allUnitsRepository.filterUnits( val result = allUnitsRepository.filterUnits(
hideBrokenCurrencies = true, hideBrokenUnits = true,
chosenUnitGroup = UnitGroup.CURRENCY, chosenUnitGroup = UnitGroup.CURRENCY,
favoritesOnly = false, favoritesOnly = false,
searchQuery = "", searchQuery = "",

View File

@ -37,8 +37,6 @@ import com.sadellie.unitto.data.model.UnitGroup
import com.sadellie.unitto.data.units.AllUnitsRepository import com.sadellie.unitto.data.units.AllUnitsRepository
import com.sadellie.unitto.data.units.MyUnitIDS import com.sadellie.unitto.data.units.MyUnitIDS
import com.sadellie.unitto.data.units.combine import com.sadellie.unitto.data.units.combine
import com.sadellie.unitto.data.units.remote.CurrencyApi
import com.sadellie.unitto.data.units.remote.CurrencyUnitResponse
import com.sadellie.unitto.data.userprefs.MainPreferences import com.sadellie.unitto.data.userprefs.MainPreferences
import com.sadellie.unitto.data.userprefs.UserPreferencesRepository import com.sadellie.unitto.data.userprefs.UserPreferencesRepository
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
@ -298,9 +296,7 @@ class ConverterViewModel @Inject constructor(
_showLoading.update { true } _showLoading.update { true }
try { try {
val pairs: CurrencyUnitResponse = allUnitsRepository.updateBasicUnitsForCurrencies(unitFrom)
CurrencyApi.retrofitService.getCurrencyPairs(unitFrom.unitId)
allUnitsRepository.updateBasicUnitsForCurrencies(pairs.currency)
convertAsExpression() convertAsExpression()
} catch (e: Exception) { } catch (e: Exception) {
// Dangerous and stupid, but who cares // Dangerous and stupid, but who cares

View File

@ -94,9 +94,9 @@ internal fun LeftSideScreen(
SearchBar( SearchBar(
title = stringResource(R.string.units_screen_from), title = stringResource(R.string.units_screen_from),
value = uiState.value.searchQuery, value = uiState.value.searchQuery,
onValueChange = { viewModel.onSearchQueryChange(it) }, onValueChange = { viewModel.onSearchQueryChange(it, false) },
favoritesOnly = uiState.value.favoritesOnly, favoritesOnly = uiState.value.favoritesOnly,
favoriteAction = { viewModel.toggleFavoritesOnly() }, favoriteAction = { viewModel.toggleFavoritesOnly(false) },
navigateUpAction = navigateUp, navigateUpAction = navigateUp,
focusManager = focusManager, focusManager = focusManager,
scrollBehavior = scrollBehavior scrollBehavior = scrollBehavior
@ -104,7 +104,7 @@ internal fun LeftSideScreen(
ChipsRow( ChipsRow(
chosenUnitGroup = uiState.value.chosenUnitGroup, chosenUnitGroup = uiState.value.chosenUnitGroup,
items = uiState.value.shownUnitGroups, items = uiState.value.shownUnitGroups,
selectAction = { viewModel.toggleSelectedChip(it) }, selectAction = { viewModel.toggleSelectedChip(it, false) },
lazyListState = chipsRowLazyListState, lazyListState = chipsRowLazyListState,
navigateToSettingsAction = navigateToSettingsAction navigateToSettingsAction = navigateToSettingsAction
) )
@ -130,7 +130,7 @@ internal fun LeftSideScreen(
isSelected = currentUnitId == unit.unitId, isSelected = currentUnitId == unit.unitId,
selectAction = { selectAction = {
selectAction(it) selectAction(it)
viewModel.onSearchQueryChange("") viewModel.onSearchQueryChange("", false)
focusManager.clearFocus(true) focusManager.clearFocus(true)
navigateUp() navigateUp()
}, },
@ -147,7 +147,7 @@ internal fun LeftSideScreen(
if (currentUnitId == null) return@LaunchedEffect if (currentUnitId == null) return@LaunchedEffect
// This is still wrong, but works good enough. // This is still wrong, but works good enough.
// Ideally we shouldn't use uiState.value.shownUnitGroups // Ideally we shouldn't use uiState.value.shownUnitGroups
viewModel.setSelectedChip(currentUnitId) viewModel.setSelectedChip(currentUnitId, false)
val groupToSelect = uiState.value.shownUnitGroups.indexOf(uiState.value.chosenUnitGroup) val groupToSelect = uiState.value.shownUnitGroups.indexOf(uiState.value.chosenUnitGroup)
if (groupToSelect > -1) { if (groupToSelect > -1) {
chipsRowLazyListState.animateScrollToItem(groupToSelect) chipsRowLazyListState.animateScrollToItem(groupToSelect)

View File

@ -96,11 +96,11 @@ internal fun RightSideScreen(
title = stringResource(R.string.units_screen_to), title = stringResource(R.string.units_screen_to),
value = uiState.value.searchQuery, value = uiState.value.searchQuery,
onValueChange = { onValueChange = {
viewModel.onSearchQueryChange(it, false) viewModel.onSearchQueryChange(it, true)
}, },
favoritesOnly = uiState.value.favoritesOnly, favoritesOnly = uiState.value.favoritesOnly,
favoriteAction = { favoriteAction = {
viewModel.toggleFavoritesOnly(false) viewModel.toggleFavoritesOnly(true)
}, },
navigateUpAction = navigateUp, navigateUpAction = navigateUp,
focusManager = focusManager, focusManager = focusManager,
@ -127,7 +127,7 @@ internal fun RightSideScreen(
isSelected = currentUnit == unit.unitId, isSelected = currentUnit == unit.unitId,
selectAction = { selectAction = {
selectAction(it) selectAction(it)
viewModel.onSearchQueryChange("") viewModel.onSearchQueryChange("", true)
focusManager.clearFocus(true) focusManager.clearFocus(true)
navigateUp() navigateUp()
}, },

View File

@ -76,18 +76,18 @@ class UnitsListViewModel @Inject constructor(
} }
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), SecondScreenUIState()) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), SecondScreenUIState())
fun toggleFavoritesOnly(hideBrokenCurrencies: Boolean = true) { fun toggleFavoritesOnly(hideBrokenUnits: Boolean) {
viewModelScope.launch { viewModelScope.launch {
userPrefsRepository.updateUnitConverterFavoritesOnly( userPrefsRepository.updateUnitConverterFavoritesOnly(
!_userPrefs.value.unitConverterFavoritesOnly !_userPrefs.value.unitConverterFavoritesOnly
) )
loadUnitsToShow(hideBrokenCurrencies) loadUnitsToShow(hideBrokenUnits)
} }
} }
fun onSearchQueryChange(newValue: String, hideBrokenCurrencies: Boolean = true) { fun onSearchQueryChange(newValue: String, hideBrokenUnits: Boolean) {
_searchQuery.update { newValue } _searchQuery.update { newValue }
loadUnitsToShow(hideBrokenCurrencies) loadUnitsToShow(hideBrokenUnits)
} }
/** /**
@ -95,9 +95,9 @@ class UnitsListViewModel @Inject constructor(
* *
* @param unit Will find group for unit with this id. * @param unit Will find group for unit with this id.
*/ */
fun setSelectedChip(unit: String, hideBrokenCurrencies: Boolean = true) { fun setSelectedChip(unit: String, hideBrokenUnits: Boolean) {
_chosenUnitGroup.update { allUnitsRepository.getById(unit).group } _chosenUnitGroup.update { allUnitsRepository.getById(unit).group }
loadUnitsToShow(hideBrokenCurrencies) loadUnitsToShow(hideBrokenUnits)
} }
/** /**
@ -108,27 +108,26 @@ class UnitsListViewModel @Inject constructor(
* *
* @param unitGroup [UnitGroup], currently selected chip. * @param unitGroup [UnitGroup], currently selected chip.
*/ */
fun toggleSelectedChip(unitGroup: UnitGroup, hideBrokenCurrencies: Boolean = true) { fun toggleSelectedChip(unitGroup: UnitGroup, hideBrokenUnits: Boolean) {
val newUnitGroup = if (_chosenUnitGroup.value == unitGroup) null else unitGroup val newUnitGroup = if (_chosenUnitGroup.value == unitGroup) null else unitGroup
_chosenUnitGroup.update { newUnitGroup } _chosenUnitGroup.update { newUnitGroup }
loadUnitsToShow(hideBrokenCurrencies) loadUnitsToShow(hideBrokenUnits)
} }
/** /**
* Filters and groups [AllUnitsRepository.allUnits] in coroutine * Filters and groups [AllUnitsRepository.allUnits] in coroutine
* *
* @param hideBrokenCurrencies Decide whether or not we are on left side. Need it because right side requires * @param hideBrokenUnits Broken units come from currencies API (basic unit is zero)
* us to mark disabled currency units
*/ */
private fun loadUnitsToShow( private fun loadUnitsToShow(
hideBrokenCurrencies: Boolean hideBrokenUnits: Boolean
) { ) {
viewModelScope.launch { viewModelScope.launch {
// This is mostly not UI related stuff and viewModelScope.launch uses Dispatchers.Main // This is mostly not UI related stuff and viewModelScope.launch uses Dispatchers.Main
// So we switch to Default // So we switch to Default
withContext(Dispatchers.Default) { withContext(Dispatchers.Default) {
val unitsToShow = allUnitsRepository.filterUnits( val unitsToShow = allUnitsRepository.filterUnits(
hideBrokenCurrencies = hideBrokenCurrencies, hideBrokenUnits = hideBrokenUnits,
chosenUnitGroup = _chosenUnitGroup.value, chosenUnitGroup = _chosenUnitGroup.value,
favoritesOnly = _userPrefs.value.unitConverterFavoritesOnly, favoritesOnly = _userPrefs.value.unitConverterFavoritesOnly,
searchQuery = _searchQuery.value, searchQuery = _searchQuery.value,

View File

@ -73,7 +73,7 @@ fun NavGraphBuilder.rightScreen(
val unitFromId = it.arguments?.getString(unitFromIdArg) ?: return@composable val unitFromId = it.arguments?.getString(unitFromIdArg) ?: return@composable
val unitToId = it.arguments?.getString(unitToIdArg) ?: return@composable val unitToId = it.arguments?.getString(unitToIdArg) ?: return@composable
val input = it.arguments?.getString(inputArg) val input = it.arguments?.getString(inputArg)
viewModel.setSelectedChip(unitFromId, false) viewModel.setSelectedChip(unitFromId, true)
RightSideScreen( RightSideScreen(
viewModel = viewModel, viewModel = viewModel,