mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-18 16:25:27 +02:00
Bumped dependencies really hard this time
This commit is contained in:
parent
83f092fb7c
commit
49f1520d88
@ -90,9 +90,6 @@ android {
|
|||||||
|
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = JavaVersion.VERSION_11.toString()
|
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||||
freeCompilerArgs = freeCompilerArgs + listOf(
|
|
||||||
"-opt-in=androidx.lifecycle.compose.ExperimentalLifecycleComposeApi"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
composeOptions {
|
composeOptions {
|
||||||
|
@ -73,7 +73,6 @@ internal fun Project.configureKotlinAndroid(
|
|||||||
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
"-opt-in=androidx.compose.animation.ExperimentalAnimationApi",
|
||||||
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
"-opt-in=androidx.compose.foundation.ExperimentalFoundationApi",
|
||||||
"-opt-in=androidx.compose.ui.unit.ExperimentalUnitApi",
|
"-opt-in=androidx.compose.ui.unit.ExperimentalUnitApi",
|
||||||
"-opt-in=androidx.lifecycle.compose.ExperimentalLifecycleComposeApi",
|
|
||||||
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
"-opt-in=kotlinx.coroutines.ExperimentalCoroutinesApi",
|
||||||
)
|
)
|
||||||
jvmTarget = JavaVersion.VERSION_11.toString()
|
jvmTarget = JavaVersion.VERSION_11.toString()
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("UnstableApiUsage")
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("unitto.library")
|
id("unitto.library")
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package com.sadellie.unitto.core.base
|
package com.sadellie.unitto.core.base
|
||||||
|
|
||||||
|
@Suppress("ObjectPropertyName")
|
||||||
object Token {
|
object Token {
|
||||||
object Digit {
|
object Digit {
|
||||||
const val _1 = "1"
|
const val _1 = "1"
|
||||||
|
@ -117,5 +117,42 @@ fun <T1, T2, T3, T4, T5, T6, T7, T8, R> combine(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST", "UNUSED")
|
||||||
|
fun <T1, T2, T3, T4, T5, T6, T7, T8, T9, 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>,
|
||||||
|
transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8, T9) -> R,
|
||||||
|
): Flow<R> =
|
||||||
|
kotlinx.coroutines.flow.combine(
|
||||||
|
flow,
|
||||||
|
flow2,
|
||||||
|
flow3,
|
||||||
|
flow4,
|
||||||
|
flow5,
|
||||||
|
flow6,
|
||||||
|
flow7,
|
||||||
|
flow8,
|
||||||
|
flow9
|
||||||
|
) { 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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun <T> Flow<T>.stateIn(scope: CoroutineScope, initialValue: T): StateFlow<T> =
|
fun <T> Flow<T>.stateIn(scope: CoroutineScope, initialValue: T): StateFlow<T> =
|
||||||
stateIn(scope, SharingStarted.WhileSubscribed(5000L), initialValue)
|
stateIn(scope, SharingStarted.WhileSubscribed(5000L), initialValue)
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
package io.github.sadellie.evaluatto
|
package io.github.sadellie.evaluatto
|
||||||
|
|
||||||
import org.junit.jupiter.api.Assertions.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.jupiter.api.Assertions.assertThrows
|
import org.junit.Assert.assertThrows
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
|
|
||||||
|
@ -245,7 +245,7 @@ class UnitsRepository @Inject constructor(
|
|||||||
favoritesOnly: Boolean,
|
favoritesOnly: Boolean,
|
||||||
hideBrokenUnits: Boolean,
|
hideBrokenUnits: Boolean,
|
||||||
sorting: UnitsListSorting,
|
sorting: UnitsListSorting,
|
||||||
shownUnitGroups: List<UnitGroup>,
|
shownUnitGroups: List<UnitGroup> = emptyList(),
|
||||||
): Map<UnitGroup, List<AbstractUnit>> {
|
): Map<UnitGroup, List<AbstractUnit>> {
|
||||||
// Leave only shown unit groups
|
// Leave only shown unit groups
|
||||||
var units: Sequence<AbstractUnit> = if (unitGroup == null) {
|
var units: Sequence<AbstractUnit> = if (unitGroup == null) {
|
||||||
|
@ -45,7 +45,6 @@ import kotlinx.coroutines.Job
|
|||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.getAndUpdate
|
import kotlinx.coroutines.flow.getAndUpdate
|
||||||
import kotlinx.coroutines.flow.mapLatest
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
@ -73,8 +72,13 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
private val _unitFrom = MutableStateFlow<AbstractUnit?>(null)
|
private val _unitFrom = MutableStateFlow<AbstractUnit?>(null)
|
||||||
private val _unitTo = MutableStateFlow<AbstractUnit?>(null)
|
private val _unitTo = MutableStateFlow<AbstractUnit?>(null)
|
||||||
|
|
||||||
private val _leftSideUIState = MutableStateFlow(LeftSideUIState())
|
private val _leftQuery = MutableStateFlow(TextFieldValue())
|
||||||
private val _rightSideUIState = MutableStateFlow(RightSideUIState())
|
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 val _currenciesState = MutableStateFlow<CurrencyRateUpdateState>(CurrencyRateUpdateState.Nothing)
|
||||||
private var _loadCurrenciesJob: Job? = null
|
private var _loadCurrenciesJob: Job? = null
|
||||||
|
|
||||||
@ -153,19 +157,28 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
|
|
||||||
val leftSideUIState = combine(
|
val leftSideUIState = combine(
|
||||||
_unitFrom,
|
_unitFrom,
|
||||||
_leftSideUIState,
|
_leftQuery,
|
||||||
|
_leftUnits,
|
||||||
|
_leftUnitGroup,
|
||||||
userPrefsRepository.converterPrefs,
|
userPrefsRepository.converterPrefs,
|
||||||
unitsRepo.allUnits
|
unitsRepo.allUnits
|
||||||
) { unitFrom, ui, prefs, _ ->
|
) { unitFrom, query, units, unitGroup, prefs, _ ->
|
||||||
return@combine ui.copy(
|
unitFrom ?: return@combine LeftSideUIState.Loading
|
||||||
|
|
||||||
|
return@combine LeftSideUIState.Ready(
|
||||||
unitFrom = unitFrom,
|
unitFrom = unitFrom,
|
||||||
sorting = prefs.unitConverterSorting,
|
sorting = prefs.unitConverterSorting,
|
||||||
shownUnitGroups = prefs.shownUnitGroups,
|
shownUnitGroups = prefs.shownUnitGroups,
|
||||||
favorites = prefs.unitConverterFavoritesOnly,
|
favorites = prefs.unitConverterFavoritesOnly,
|
||||||
verticalList = prefs.enableToolsExperiment,
|
verticalList = prefs.enableToolsExperiment,
|
||||||
|
query = query,
|
||||||
|
units = units,
|
||||||
|
unitGroup = unitGroup
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.mapLatest {
|
.mapLatest {
|
||||||
|
if (it !is LeftSideUIState.Ready) return@mapLatest it
|
||||||
|
|
||||||
filterUnitsLeft(
|
filterUnitsLeft(
|
||||||
query = it.query,
|
query = it.query,
|
||||||
unitGroup = it.unitGroup,
|
unitGroup = it.unitGroup,
|
||||||
@ -175,19 +188,23 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
)
|
)
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
.stateIn(viewModelScope, SharingStarted.Lazily, LeftSideUIState())
|
.stateIn(viewModelScope, SharingStarted.Lazily, LeftSideUIState.Loading)
|
||||||
|
|
||||||
val rightSideUIState = combine(
|
val rightSideUIState = combine(
|
||||||
_unitFrom,
|
_unitFrom,
|
||||||
_unitTo,
|
_unitTo,
|
||||||
_input,
|
_input,
|
||||||
_calculation,
|
_calculation,
|
||||||
_rightSideUIState,
|
_rightQuery,
|
||||||
|
_rightUnits,
|
||||||
userPrefsRepository.converterPrefs,
|
userPrefsRepository.converterPrefs,
|
||||||
_currenciesState,
|
_currenciesState,
|
||||||
unitsRepo.allUnits,
|
unitsRepo.allUnits,
|
||||||
) { unitFrom, unitTo, input, calculation, ui, prefs, currenciesState, _ ->
|
) { unitFrom, unitTo, input, calculation, query, units, prefs, currenciesState, _ ->
|
||||||
return@combine ui.copy(
|
unitFrom ?: return@combine RightSideUIState.Loading
|
||||||
|
unitTo ?: return@combine RightSideUIState.Loading
|
||||||
|
|
||||||
|
return@combine RightSideUIState.Ready(
|
||||||
unitFrom = unitFrom,
|
unitFrom = unitFrom,
|
||||||
unitTo = unitTo,
|
unitTo = unitTo,
|
||||||
sorting = prefs.unitConverterSorting,
|
sorting = prefs.unitConverterSorting,
|
||||||
@ -196,20 +213,23 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
scale = prefs.precision,
|
scale = prefs.precision,
|
||||||
outputFormat = prefs.outputFormat,
|
outputFormat = prefs.outputFormat,
|
||||||
formatterSymbols = AllFormatterSymbols.getById(prefs.separator),
|
formatterSymbols = AllFormatterSymbols.getById(prefs.separator),
|
||||||
currencyRateUpdateState = currenciesState
|
currencyRateUpdateState = currenciesState,
|
||||||
|
query = query,
|
||||||
|
units = units,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.mapLatest {
|
.mapLatest {
|
||||||
|
if (it !is RightSideUIState.Ready) return@mapLatest it
|
||||||
|
|
||||||
filterUnitsRight(
|
filterUnitsRight(
|
||||||
query = it.query,
|
query = it.query,
|
||||||
unitGroup = it.unitTo?.group,
|
unitGroup = it.unitTo.group,
|
||||||
favoritesOnly = it.favorites,
|
favoritesOnly = it.favorites,
|
||||||
sorting = it.sorting,
|
sorting = it.sorting,
|
||||||
shownUnitGroups = emptyList(),
|
|
||||||
)
|
)
|
||||||
it
|
it
|
||||||
}
|
}
|
||||||
.stateIn(viewModelScope, SharingStarted.Lazily, RightSideUIState())
|
.stateIn(viewModelScope, SharingStarted.Lazily, RightSideUIState.Loading)
|
||||||
|
|
||||||
fun swapUnits() {
|
fun swapUnits() {
|
||||||
_unitFrom
|
_unitFrom
|
||||||
@ -303,21 +323,15 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun queryChangeLeft(query: TextFieldValue) = _leftSideUIState.update {
|
fun queryChangeLeft(query: TextFieldValue) = _leftQuery.update { query }
|
||||||
it.copy(query = query)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun queryChangeRight(query: TextFieldValue) = _rightSideUIState.update {
|
fun queryChangeRight(query: TextFieldValue) = _rightQuery.update { query }
|
||||||
it.copy(query = query)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun favoritesOnlyChange(enabled: Boolean) = viewModelScope.launch {
|
fun favoritesOnlyChange(enabled: Boolean) = viewModelScope.launch {
|
||||||
userPrefsRepository.updateUnitConverterFavoritesOnly(enabled)
|
userPrefsRepository.updateUnitConverterFavoritesOnly(enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateUnitGroupLeft(unitGroup: UnitGroup?) = _leftSideUIState.update {
|
fun updateUnitGroupLeft(unitGroup: UnitGroup?) = _leftUnitGroup.update { unitGroup }
|
||||||
it.copy(unitGroup = unitGroup)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun favoriteUnit(unit: AbstractUnit) = viewModelScope.launch {
|
fun favoriteUnit(unit: AbstractUnit) = viewModelScope.launch {
|
||||||
unitsRepo.favorite(unit)
|
unitsRepo.favorite(unit)
|
||||||
@ -330,16 +344,14 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
sorting: UnitsListSorting,
|
sorting: UnitsListSorting,
|
||||||
shownUnitGroups: List<UnitGroup>,
|
shownUnitGroups: List<UnitGroup>,
|
||||||
) = viewModelScope.launch(Dispatchers.Default) {
|
) = viewModelScope.launch(Dispatchers.Default) {
|
||||||
_leftSideUIState.update {
|
_leftUnits.update {
|
||||||
it.copy(
|
unitsRepo.filterUnits(
|
||||||
units = unitsRepo.filterUnits(
|
query = query.text,
|
||||||
query = query.text,
|
unitGroup = unitGroup,
|
||||||
unitGroup = unitGroup,
|
favoritesOnly = favoritesOnly,
|
||||||
favoritesOnly = favoritesOnly,
|
hideBrokenUnits = false,
|
||||||
hideBrokenUnits = false,
|
sorting = sorting,
|
||||||
sorting = sorting,
|
shownUnitGroups = shownUnitGroups
|
||||||
shownUnitGroups = shownUnitGroups
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,18 +361,14 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
unitGroup: UnitGroup?,
|
unitGroup: UnitGroup?,
|
||||||
favoritesOnly: Boolean,
|
favoritesOnly: Boolean,
|
||||||
sorting: UnitsListSorting,
|
sorting: UnitsListSorting,
|
||||||
shownUnitGroups: List<UnitGroup>,
|
|
||||||
) = viewModelScope.launch(Dispatchers.Default) {
|
) = viewModelScope.launch(Dispatchers.Default) {
|
||||||
_rightSideUIState.update {
|
_rightUnits.update {
|
||||||
it.copy(
|
unitsRepo.filterUnits(
|
||||||
units = unitsRepo.filterUnits(
|
query = query.text,
|
||||||
query = query.text,
|
unitGroup = unitGroup,
|
||||||
unitGroup = unitGroup,
|
favoritesOnly = favoritesOnly,
|
||||||
favoritesOnly = favoritesOnly,
|
hideBrokenUnits = true,
|
||||||
hideBrokenUnits = true,
|
sorting = sorting,
|
||||||
sorting = sorting,
|
|
||||||
shownUnitGroups = shownUnitGroups
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import androidx.compose.animation.animateColorAsState
|
|||||||
import androidx.compose.animation.core.LinearOutSlowInEasing
|
import androidx.compose.animation.core.LinearOutSlowInEasing
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
@ -49,13 +50,17 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.core.ui.common.UnittoSearchBar
|
import com.sadellie.unitto.core.ui.common.UnittoSearchBar
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.UnitGroup
|
||||||
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
||||||
|
import com.sadellie.unitto.data.model.unit.NormalUnit
|
||||||
|
import com.sadellie.unitto.data.units.MyUnitIDS
|
||||||
import com.sadellie.unitto.feature.converter.components.BasicUnitListItem
|
import com.sadellie.unitto.feature.converter.components.BasicUnitListItem
|
||||||
import com.sadellie.unitto.feature.converter.components.ChipsFlexRow
|
import com.sadellie.unitto.feature.converter.components.ChipsFlexRow
|
||||||
import com.sadellie.unitto.feature.converter.components.ChipsRow
|
import com.sadellie.unitto.feature.converter.components.ChipsRow
|
||||||
import com.sadellie.unitto.feature.converter.components.FavoritesButton
|
import com.sadellie.unitto.feature.converter.components.FavoritesButton
|
||||||
import com.sadellie.unitto.feature.converter.components.SearchPlaceholder
|
import com.sadellie.unitto.feature.converter.components.SearchPlaceholder
|
||||||
import com.sadellie.unitto.feature.converter.components.UnitGroupHeader
|
import com.sadellie.unitto.feature.converter.components.UnitGroupHeader
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun LeftSideRoute(
|
internal fun LeftSideRoute(
|
||||||
@ -63,23 +68,28 @@ internal fun LeftSideRoute(
|
|||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
navigateToUnitGroups: () -> Unit,
|
navigateToUnitGroups: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val uiState = viewModel.leftSideUIState.collectAsStateWithLifecycle()
|
when (
|
||||||
|
val uiState = viewModel.leftSideUIState.collectAsStateWithLifecycle().value
|
||||||
LeftSideScreen(
|
) {
|
||||||
uiState = uiState.value,
|
is LeftSideUIState.Loading -> {
|
||||||
onQueryChange = viewModel::queryChangeLeft,
|
Box(modifier = Modifier.fillMaxSize())
|
||||||
toggleFavoritesOnly = viewModel::favoritesOnlyChange,
|
}
|
||||||
updateUnitFrom = viewModel::updateUnitFrom,
|
is LeftSideUIState.Ready -> LeftSideScreen(
|
||||||
updateUnitGroup = viewModel::updateUnitGroupLeft,
|
uiState = uiState,
|
||||||
favoriteUnit = viewModel::favoriteUnit,
|
onQueryChange = viewModel::queryChangeLeft,
|
||||||
navigateUp = navigateUp,
|
toggleFavoritesOnly = viewModel::favoritesOnlyChange,
|
||||||
navigateToUnitGroups = navigateToUnitGroups,
|
updateUnitFrom = viewModel::updateUnitFrom,
|
||||||
)
|
updateUnitGroup = viewModel::updateUnitGroupLeft,
|
||||||
|
favoriteUnit = viewModel::favoriteUnit,
|
||||||
|
navigateUp = navigateUp,
|
||||||
|
navigateToUnitGroups = navigateToUnitGroups,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun LeftSideScreen(
|
private fun LeftSideScreen(
|
||||||
uiState: LeftSideUIState,
|
uiState: LeftSideUIState.Ready,
|
||||||
onQueryChange: (TextFieldValue) -> Unit,
|
onQueryChange: (TextFieldValue) -> Unit,
|
||||||
toggleFavoritesOnly: (Boolean) -> Unit,
|
toggleFavoritesOnly: (Boolean) -> Unit,
|
||||||
updateUnitFrom: (AbstractUnit) -> Unit,
|
updateUnitFrom: (AbstractUnit) -> Unit,
|
||||||
@ -102,13 +112,12 @@ private fun LeftSideScreen(
|
|||||||
val chipsRowLazyListState = rememberLazyListState()
|
val chipsRowLazyListState = rememberLazyListState()
|
||||||
|
|
||||||
LaunchedEffect(uiState.unitFrom, uiState.shownUnitGroups) {
|
LaunchedEffect(uiState.unitFrom, uiState.shownUnitGroups) {
|
||||||
if (uiState.unitFrom == null) return@LaunchedEffect
|
|
||||||
updateUnitGroup(uiState.unitFrom.group)
|
updateUnitGroup(uiState.unitFrom.group)
|
||||||
|
|
||||||
val groupToSelect = uiState.shownUnitGroups.indexOf(uiState.unitFrom.group)
|
kotlin.runCatching {
|
||||||
if (groupToSelect > -1) {
|
val groupToSelect = uiState.shownUnitGroups.indexOf(uiState.unitFrom.group)
|
||||||
kotlin.runCatching {
|
if (groupToSelect > -1) {
|
||||||
chipsRowLazyListState.animateScrollToItem(groupToSelect)
|
chipsRowLazyListState.scrollToItem(groupToSelect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,13 +162,13 @@ private fun LeftSideScreen(
|
|||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Crossfade(
|
Crossfade(
|
||||||
targetState = uiState.units?.isNotEmpty(),
|
targetState = uiState.units.isNotEmpty(),
|
||||||
modifier = Modifier.padding(paddingValues),
|
modifier = Modifier.padding(paddingValues),
|
||||||
label = "Units list"
|
label = "Units list"
|
||||||
) { hasUnits ->
|
) { hasUnits ->
|
||||||
when (hasUnits) {
|
when (hasUnits) {
|
||||||
true -> LazyColumn(Modifier.fillMaxSize()) {
|
true -> LazyColumn(Modifier.fillMaxSize()) {
|
||||||
uiState.units?.forEach { (unitGroup, units) ->
|
uiState.units.forEach { (unitGroup, units) ->
|
||||||
item(unitGroup.name) {
|
item(unitGroup.name) {
|
||||||
UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup)
|
UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup)
|
||||||
}
|
}
|
||||||
@ -170,7 +179,7 @@ private fun LeftSideScreen(
|
|||||||
name = stringResource(it.displayName),
|
name = stringResource(it.displayName),
|
||||||
supportLabel = stringResource(it.shortName),
|
supportLabel = stringResource(it.shortName),
|
||||||
isFavorite = it.isFavorite,
|
isFavorite = it.isFavorite,
|
||||||
isSelected = it.id == uiState.unitFrom?.id,
|
isSelected = it.id == uiState.unitFrom.id,
|
||||||
onClick = {
|
onClick = {
|
||||||
onQueryChange(TextFieldValue())
|
onQueryChange(TextFieldValue())
|
||||||
updateUnitFrom(it)
|
updateUnitFrom(it)
|
||||||
@ -183,7 +192,6 @@ private fun LeftSideScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
false -> SearchPlaceholder(navigateToSettingsAction = navigateToUnitGroups)
|
false -> SearchPlaceholder(navigateToSettingsAction = navigateToUnitGroups)
|
||||||
null -> {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,8 +200,29 @@ private fun LeftSideScreen(
|
|||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun LeftSideScreenPreview() {
|
private fun LeftSideScreenPreview() {
|
||||||
|
val units: Map<UnitGroup, List<AbstractUnit>> = mapOf(
|
||||||
|
UnitGroup.LENGTH to listOf(
|
||||||
|
NormalUnit(MyUnitIDS.meter, BigDecimal.valueOf(1.0E+18), UnitGroup.LENGTH, R.string.meter, R.string.meter_short),
|
||||||
|
NormalUnit(MyUnitIDS.kilometer, BigDecimal.valueOf(1.0E+21), UnitGroup.LENGTH, R.string.kilometer, R.string.kilometer_short),
|
||||||
|
NormalUnit(MyUnitIDS.nautical_mile, BigDecimal.valueOf(1.852E+21), UnitGroup.LENGTH, R.string.nautical_mile, R.string.nautical_mile_short),
|
||||||
|
NormalUnit(MyUnitIDS.inch, BigDecimal.valueOf(25_400_000_000_000_000), UnitGroup.LENGTH, R.string.inch, R.string.inch_short),
|
||||||
|
NormalUnit(MyUnitIDS.foot, BigDecimal.valueOf(304_800_000_000_002_200), UnitGroup.LENGTH, R.string.foot, R.string.foot_short),
|
||||||
|
NormalUnit(MyUnitIDS.yard, BigDecimal.valueOf(914_400_000_000_006_400), UnitGroup.LENGTH, R.string.yard, R.string.yard_short),
|
||||||
|
NormalUnit(MyUnitIDS.mile, BigDecimal.valueOf(1_609_344_000_000_010_500_000.0), UnitGroup.LENGTH, R.string.mile, R.string.mile_short),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
LeftSideScreen(
|
LeftSideScreen(
|
||||||
uiState = LeftSideUIState(),
|
uiState = LeftSideUIState.Ready(
|
||||||
|
unitFrom = units.values.first().first(),
|
||||||
|
units = units,
|
||||||
|
query = TextFieldValue(),
|
||||||
|
favorites = false,
|
||||||
|
shownUnitGroups = listOf(UnitGroup.LENGTH, UnitGroup.TEMPERATURE, UnitGroup.CURRENCY),
|
||||||
|
unitGroup = units.keys.toList().first(),
|
||||||
|
sorting = UnitsListSorting.USAGE,
|
||||||
|
verticalList = false
|
||||||
|
),
|
||||||
onQueryChange = {},
|
onQueryChange = {},
|
||||||
toggleFavoritesOnly = {},
|
toggleFavoritesOnly = {},
|
||||||
updateUnitFrom = {},
|
updateUnitFrom = {},
|
||||||
|
@ -23,13 +23,17 @@ import com.sadellie.unitto.data.model.UnitGroup
|
|||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
||||||
|
|
||||||
internal data class LeftSideUIState(
|
internal sealed class LeftSideUIState {
|
||||||
val unitFrom: AbstractUnit? = null,
|
data object Loading : LeftSideUIState()
|
||||||
val query: TextFieldValue = TextFieldValue(),
|
|
||||||
val units: Map<UnitGroup, List<AbstractUnit>>? = null,
|
data class Ready(
|
||||||
val favorites: Boolean = false,
|
val unitFrom: AbstractUnit,
|
||||||
val shownUnitGroups: List<UnitGroup> = emptyList(),
|
val query: TextFieldValue,
|
||||||
val unitGroup: UnitGroup? = unitFrom?.group,
|
val units: Map<UnitGroup, List<AbstractUnit>> = emptyMap(),
|
||||||
val sorting: UnitsListSorting = UnitsListSorting.USAGE,
|
val favorites: Boolean,
|
||||||
val verticalList: Boolean = false,
|
val shownUnitGroups: List<UnitGroup>,
|
||||||
)
|
val unitGroup: UnitGroup?,
|
||||||
|
val sorting: UnitsListSorting,
|
||||||
|
val verticalList: Boolean,
|
||||||
|
) : LeftSideUIState()
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package com.sadellie.unitto.feature.converter
|
package com.sadellie.unitto.feature.converter
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
@ -33,15 +34,19 @@ import androidx.compose.ui.res.stringResource
|
|||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import com.sadellie.unitto.core.base.OutputFormat
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.core.ui.common.UnittoSearchBar
|
import com.sadellie.unitto.core.ui.common.UnittoSearchBar
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.formatExpression
|
import com.sadellie.unitto.core.ui.common.textfield.formatExpression
|
||||||
import com.sadellie.unitto.data.common.format
|
import com.sadellie.unitto.data.common.format
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.UnitGroup
|
||||||
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
||||||
import com.sadellie.unitto.data.model.unit.DefaultUnit
|
import com.sadellie.unitto.data.model.unit.DefaultUnit
|
||||||
|
import com.sadellie.unitto.data.model.unit.NormalUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NumberBaseUnit
|
import com.sadellie.unitto.data.model.unit.NumberBaseUnit
|
||||||
|
import com.sadellie.unitto.data.units.MyUnitIDS
|
||||||
import com.sadellie.unitto.feature.converter.components.BasicUnitListItem
|
import com.sadellie.unitto.feature.converter.components.BasicUnitListItem
|
||||||
import com.sadellie.unitto.feature.converter.components.FavoritesButton
|
import com.sadellie.unitto.feature.converter.components.FavoritesButton
|
||||||
import com.sadellie.unitto.feature.converter.components.SearchPlaceholder
|
import com.sadellie.unitto.feature.converter.components.SearchPlaceholder
|
||||||
@ -54,22 +59,26 @@ internal fun RightSideRoute(
|
|||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
navigateToUnitGroups: () -> Unit,
|
navigateToUnitGroups: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val uiState = viewModel.rightSideUIState.collectAsStateWithLifecycle()
|
when (
|
||||||
|
val uiState = viewModel.rightSideUIState.collectAsStateWithLifecycle().value
|
||||||
RightSideScreen(
|
) {
|
||||||
uiState = uiState.value,
|
is RightSideUIState.Loading -> Box(Modifier.fillMaxSize())
|
||||||
onQueryChange = viewModel::queryChangeRight,
|
is RightSideUIState.Ready ->
|
||||||
toggleFavoritesOnly = viewModel::favoritesOnlyChange,
|
RightSideScreen(
|
||||||
updateUnitTo = viewModel::updateUnitTo,
|
uiState = uiState,
|
||||||
favoriteUnit = viewModel::favoriteUnit,
|
onQueryChange = viewModel::queryChangeRight,
|
||||||
navigateUp = navigateUp,
|
toggleFavoritesOnly = viewModel::favoritesOnlyChange,
|
||||||
navigateToUnitGroups = navigateToUnitGroups,
|
updateUnitTo = viewModel::updateUnitTo,
|
||||||
)
|
favoriteUnit = viewModel::favoriteUnit,
|
||||||
|
navigateUp = navigateUp,
|
||||||
|
navigateToUnitGroups = navigateToUnitGroups,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RightSideScreen(
|
private fun RightSideScreen(
|
||||||
uiState: RightSideUIState,
|
uiState: RightSideUIState.Ready,
|
||||||
onQueryChange: (TextFieldValue) -> Unit,
|
onQueryChange: (TextFieldValue) -> Unit,
|
||||||
toggleFavoritesOnly: (Boolean) -> Unit,
|
toggleFavoritesOnly: (Boolean) -> Unit,
|
||||||
updateUnitTo: (AbstractUnit) -> Unit,
|
updateUnitTo: (AbstractUnit) -> Unit,
|
||||||
@ -98,13 +107,13 @@ private fun RightSideScreen(
|
|||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
Crossfade(
|
Crossfade(
|
||||||
targetState = uiState.units?.isNotEmpty(),
|
targetState = uiState.units.isNotEmpty(),
|
||||||
modifier = Modifier.padding(paddingValues),
|
modifier = Modifier.padding(paddingValues),
|
||||||
label = "Units list"
|
label = "Units list"
|
||||||
) { hasUnits ->
|
) { hasUnits ->
|
||||||
when (hasUnits) {
|
when (hasUnits) {
|
||||||
true -> LazyColumn(Modifier.fillMaxSize()) {
|
true -> LazyColumn(Modifier.fillMaxSize()) {
|
||||||
uiState.units?.forEach { (unitGroup, units) ->
|
uiState.units.forEach { (unitGroup, units) ->
|
||||||
item(unitGroup.name) {
|
item(unitGroup.name) {
|
||||||
UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup)
|
UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup)
|
||||||
}
|
}
|
||||||
@ -124,7 +133,7 @@ private fun RightSideScreen(
|
|||||||
readyCurrencies = uiState.currencyRateUpdateState is CurrencyRateUpdateState.Ready,
|
readyCurrencies = uiState.currencyRateUpdateState is CurrencyRateUpdateState.Ready,
|
||||||
),
|
),
|
||||||
isFavorite = it.isFavorite,
|
isFavorite = it.isFavorite,
|
||||||
isSelected = it.id == uiState.unitTo?.id,
|
isSelected = it.id == uiState.unitTo.id,
|
||||||
onClick = {
|
onClick = {
|
||||||
onQueryChange(TextFieldValue())
|
onQueryChange(TextFieldValue())
|
||||||
updateUnitTo(it)
|
updateUnitTo(it)
|
||||||
@ -137,7 +146,6 @@ private fun RightSideScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
false -> SearchPlaceholder(navigateToSettingsAction = navigateToUnitGroups)
|
false -> SearchPlaceholder(navigateToSettingsAction = navigateToUnitGroups)
|
||||||
null -> {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -187,8 +195,32 @@ private fun formatUnitToSupportLabel(
|
|||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun RightSideScreenPreview() {
|
private fun RightSideScreenPreview() {
|
||||||
|
val units: Map<UnitGroup, List<AbstractUnit>> = mapOf(
|
||||||
|
UnitGroup.LENGTH to listOf(
|
||||||
|
NormalUnit(MyUnitIDS.meter, BigDecimal.valueOf(1.0E+18), UnitGroup.LENGTH, R.string.meter, R.string.meter_short),
|
||||||
|
NormalUnit(MyUnitIDS.kilometer, BigDecimal.valueOf(1.0E+21), UnitGroup.LENGTH, R.string.kilometer, R.string.kilometer_short),
|
||||||
|
NormalUnit(MyUnitIDS.nautical_mile, BigDecimal.valueOf(1.852E+21), UnitGroup.LENGTH, R.string.nautical_mile, R.string.nautical_mile_short),
|
||||||
|
NormalUnit(MyUnitIDS.inch, BigDecimal.valueOf(25_400_000_000_000_000), UnitGroup.LENGTH, R.string.inch, R.string.inch_short),
|
||||||
|
NormalUnit(MyUnitIDS.foot, BigDecimal.valueOf(304_800_000_000_002_200), UnitGroup.LENGTH, R.string.foot, R.string.foot_short),
|
||||||
|
NormalUnit(MyUnitIDS.yard, BigDecimal.valueOf(914_400_000_000_006_400), UnitGroup.LENGTH, R.string.yard, R.string.yard_short),
|
||||||
|
NormalUnit(MyUnitIDS.mile, BigDecimal.valueOf(1_609_344_000_000_010_500_000.0), UnitGroup.LENGTH, R.string.mile, R.string.mile_short),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
RightSideScreen(
|
RightSideScreen(
|
||||||
uiState = RightSideUIState(),
|
uiState = RightSideUIState.Ready(
|
||||||
|
unitFrom = units.values.first().first(),
|
||||||
|
units = units,
|
||||||
|
query = TextFieldValue(),
|
||||||
|
favorites = false,
|
||||||
|
sorting = UnitsListSorting.USAGE,
|
||||||
|
unitTo = units.values.first()[1],
|
||||||
|
input = "100",
|
||||||
|
scale = 3,
|
||||||
|
outputFormat = OutputFormat.PLAIN,
|
||||||
|
formatterSymbols = FormatterSymbols.Spaces,
|
||||||
|
currencyRateUpdateState = CurrencyRateUpdateState.Nothing
|
||||||
|
),
|
||||||
onQueryChange = {},
|
onQueryChange = {},
|
||||||
toggleFavoritesOnly = {},
|
toggleFavoritesOnly = {},
|
||||||
updateUnitTo = {},
|
updateUnitTo = {},
|
||||||
|
@ -19,23 +19,25 @@
|
|||||||
package com.sadellie.unitto.feature.converter
|
package com.sadellie.unitto.feature.converter
|
||||||
|
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import com.sadellie.unitto.core.base.OutputFormat
|
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
||||||
|
|
||||||
internal data class RightSideUIState(
|
internal sealed class RightSideUIState {
|
||||||
val unitFrom: AbstractUnit? = null,
|
data object Loading : RightSideUIState()
|
||||||
val unitTo: AbstractUnit? = null,
|
|
||||||
val query: TextFieldValue = TextFieldValue(),
|
data class Ready(
|
||||||
val units: Map<UnitGroup, List<AbstractUnit>>? = null,
|
val unitFrom: AbstractUnit,
|
||||||
val favorites: Boolean = false,
|
val unitTo: AbstractUnit,
|
||||||
val unitGroup: UnitGroup? = unitFrom?.group,
|
val query: TextFieldValue,
|
||||||
val sorting: UnitsListSorting = UnitsListSorting.USAGE,
|
val units: Map<UnitGroup, List<AbstractUnit>>,
|
||||||
val input: String = "",
|
val favorites: Boolean,
|
||||||
val scale: Int = 3,
|
val sorting: UnitsListSorting,
|
||||||
val outputFormat: Int = OutputFormat.PLAIN,
|
val input: String,
|
||||||
val formatterSymbols: FormatterSymbols = FormatterSymbols.Spaces,
|
val scale: Int,
|
||||||
val currencyRateUpdateState: CurrencyRateUpdateState = CurrencyRateUpdateState.Nothing
|
val outputFormat: Int,
|
||||||
)
|
val formatterSymbols: FormatterSymbols,
|
||||||
|
val currencyRateUpdateState: CurrencyRateUpdateState,
|
||||||
|
) : RightSideUIState()
|
||||||
|
}
|
||||||
|
@ -6,19 +6,19 @@ ksp = "1.9.0-1.0.13"
|
|||||||
androidxCore = "1.12.0"
|
androidxCore = "1.12.0"
|
||||||
androidGradlePlugin = "8.1.1"
|
androidGradlePlugin = "8.1.1"
|
||||||
orgJetbrainsKotlinxCoroutinesTest = "1.7.2"
|
orgJetbrainsKotlinxCoroutinesTest = "1.7.2"
|
||||||
androidxCompose = "1.6.0-alpha05"
|
androidxCompose = "1.6.0-alpha06"
|
||||||
androidxComposeCompiler = "1.5.0"
|
androidxComposeCompiler = "1.5.0"
|
||||||
androidxComposeUi = "1.6.0-alpha05"
|
androidxComposeUi = "1.6.0-alpha06"
|
||||||
androidxComposeMaterial3 = "1.2.0-alpha07"
|
androidxComposeMaterial3 = "1.2.0-alpha08"
|
||||||
androidxNavigation = "2.7.2"
|
androidxNavigation = "2.7.3"
|
||||||
androidxLifecycleRuntimeCompose = "2.6.2"
|
androidxLifecycleRuntimeCompose = "2.6.2"
|
||||||
androidxHilt = "1.0.0"
|
androidxHilt = "1.0.0"
|
||||||
androidxAppCompat = "1.6.1"
|
androidxAppCompat = "1.6.1"
|
||||||
comGoogleDagger = "2.47"
|
comGoogleDagger = "2.47"
|
||||||
androidxComposeMaterialIconsExtended = "1.6.0-alpha05"
|
androidxComposeMaterialIconsExtended = "1.6.0-alpha06"
|
||||||
androidxDatastore = "1.0.0"
|
androidxDatastore = "1.0.0"
|
||||||
comGoogleAccompanist = "0.30.1"
|
comGoogleAccompanist = "0.30.1"
|
||||||
androidxRoom = "2.6.0-beta01"
|
androidxRoom = "2.6.0-rc01"
|
||||||
comSquareupMoshi = "1.15.0"
|
comSquareupMoshi = "1.15.0"
|
||||||
comSquareupRetrofit2 = "2.9.0"
|
comSquareupRetrofit2 = "2.9.0"
|
||||||
comGithubSadellieThemmo = "1.0.0"
|
comGithubSadellieThemmo = "1.0.0"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user