mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-19 08:45:27 +02:00
Refactor Converter
- no longer abusing mapLatest and StateFlow - id-based system in UI and business layers
This commit is contained in:
parent
eb00d8a76e
commit
eb96868afc
@ -83,76 +83,5 @@ fun <T1, T2, T3, T4, T5, T6, T7, R> combine(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST", "UNUSED")
|
|
||||||
fun <T1, T2, T3, T4, T5, T6, T7, T8, 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>,
|
|
||||||
transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R,
|
|
||||||
): Flow<R> =
|
|
||||||
kotlinx.coroutines.flow.combine(
|
|
||||||
flow,
|
|
||||||
flow2,
|
|
||||||
flow3,
|
|
||||||
flow4,
|
|
||||||
flow5,
|
|
||||||
flow6,
|
|
||||||
flow7,
|
|
||||||
flow8,
|
|
||||||
) { 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,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
@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)
|
||||||
|
@ -35,11 +35,13 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
testImplementation(libs.org.robolectric.robolectric)
|
||||||
implementation(libs.com.squareup.moshi.moshi.kotlin)
|
implementation(libs.com.squareup.moshi.moshi.kotlin)
|
||||||
implementation(libs.com.squareup.retrofit2.converter.moshi)
|
implementation(libs.com.squareup.retrofit2.converter.moshi)
|
||||||
|
|
||||||
implementation(project(":core:base"))
|
implementation(project(":core:base"))
|
||||||
implementation(project(":data:common"))
|
implementation(project(":data:common"))
|
||||||
implementation(project(":data:database"))
|
implementation(project(":data:database"))
|
||||||
|
implementation(project(":data:evaluatto"))
|
||||||
implementation(project(":data:model"))
|
implementation(project(":data:model"))
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Unitto is a calculator for Android
|
* Unitto is a calculator for Android
|
||||||
* Copyright (c) 2023-2024 Elshan Agaev
|
* Copyright (c) 2024 Elshan Agaev
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -16,10 +16,18 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model.unit
|
package com.sadellie.unitto.data.converter
|
||||||
|
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
interface DefaultUnit : AbstractUnit {
|
interface BatchConvertResult
|
||||||
fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal
|
|
||||||
}
|
@JvmInline
|
||||||
|
value class DefaultBatchConvertResult(
|
||||||
|
val value: BigDecimal,
|
||||||
|
) : BatchConvertResult
|
||||||
|
|
||||||
|
@JvmInline
|
||||||
|
value class NumberBaseBatchConvertResult(
|
||||||
|
val value: String,
|
||||||
|
) : BatchConvertResult
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Unitto is a calculator for Android
|
||||||
|
* Copyright (c) 2024 Elshan Agaev
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sadellie.unitto.data.converter
|
||||||
|
|
||||||
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
sealed class ConverterResult {
|
||||||
|
|
||||||
|
sealed class Error : ConverterResult() {
|
||||||
|
data object Currency : Error()
|
||||||
|
|
||||||
|
data object BadInput : Error()
|
||||||
|
|
||||||
|
data object ConversionError : Error()
|
||||||
|
|
||||||
|
data object DivideByZero : Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Default(
|
||||||
|
val value: BigDecimal,
|
||||||
|
val calculation: BigDecimal,
|
||||||
|
) : ConverterResult()
|
||||||
|
|
||||||
|
data class NumberBase(val value: String) : ConverterResult()
|
||||||
|
|
||||||
|
data class Time(
|
||||||
|
val negative: Boolean = false,
|
||||||
|
val day: BigDecimal = BigDecimal.ZERO,
|
||||||
|
val hour: BigDecimal = BigDecimal.ZERO,
|
||||||
|
val minute: BigDecimal = BigDecimal.ZERO,
|
||||||
|
val second: BigDecimal = BigDecimal.ZERO,
|
||||||
|
val millisecond: BigDecimal = BigDecimal.ZERO,
|
||||||
|
val microsecond: BigDecimal = BigDecimal.ZERO,
|
||||||
|
val nanosecond: BigDecimal = BigDecimal.ZERO,
|
||||||
|
val attosecond: BigDecimal = BigDecimal.ZERO,
|
||||||
|
) : ConverterResult()
|
||||||
|
|
||||||
|
data class FootInch(
|
||||||
|
val foot: BigDecimal,
|
||||||
|
val inch: BigDecimal,
|
||||||
|
) : ConverterResult() {
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Creates an object for displaying formatted foot and inch output. Units are passed as objects so
|
||||||
|
* that changes in basic units don't require modifying the method. Also this method can't access
|
||||||
|
* units repository directly.
|
||||||
|
*
|
||||||
|
* @param input Input in feet.
|
||||||
|
* @param footUnit Foot unit [BasicUnit.Default].
|
||||||
|
* @param inchUnit Inch unit [BasicUnit.Default].
|
||||||
|
* @return Result where decimal places are converter into inches.
|
||||||
|
*/
|
||||||
|
fun fromBigDecimal(
|
||||||
|
input: BigDecimal,
|
||||||
|
footUnit: BasicUnit.Default,
|
||||||
|
inchUnit: BasicUnit.Default,
|
||||||
|
): FootInch {
|
||||||
|
val (integral, fractional) = input.divideAndRemainder(BigDecimal.ONE)
|
||||||
|
return FootInch(integral, footUnit.convert(inchUnit, fractional))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data object Loading : ConverterResult()
|
||||||
|
}
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unitto is a calculator for Android
|
|
||||||
* Copyright (c) 2023-2024 Elshan Agaev
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sadellie.unitto.data.converter
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.sadellie.unitto.data.database.CurrencyRatesDao
|
|
||||||
import com.sadellie.unitto.data.database.UnitsDao
|
|
||||||
import com.sadellie.unitto.data.model.repository.UnitsRepository
|
|
||||||
import dagger.Module
|
|
||||||
import dagger.Provides
|
|
||||||
import dagger.hilt.InstallIn
|
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
|
||||||
import dagger.hilt.components.SingletonComponent
|
|
||||||
|
|
||||||
@Module
|
|
||||||
@InstallIn(SingletonComponent::class)
|
|
||||||
class DataStoreModule {
|
|
||||||
@Provides
|
|
||||||
fun provideUnitsRepository(
|
|
||||||
unitsDao: UnitsDao,
|
|
||||||
currencyRatesDao: CurrencyRatesDao,
|
|
||||||
@ApplicationContext appContext: Context,
|
|
||||||
): UnitsRepository {
|
|
||||||
return UnitsRepositoryImpl(
|
|
||||||
unitsDao = unitsDao,
|
|
||||||
currencyRatesDao = currencyRatesDao,
|
|
||||||
mContext = appContext,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Unitto is a calculator for Android
|
* Unitto is a calculator for Android
|
||||||
* Copyright (c) 2023-2024 Elshan Agaev
|
* Copyright (c) 2024 Elshan Agaev
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@ -16,45 +16,32 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model.unit
|
package com.sadellie.unitto.data.converter
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.sadellie.unitto.data.common.lev
|
import com.sadellie.unitto.data.common.lev
|
||||||
import com.sadellie.unitto.data.common.normalizeSuperscript
|
import com.sadellie.unitto.data.common.normalizeSuperscript
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.database.UnitsEntity
|
||||||
import java.math.BigDecimal
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
|
|
||||||
interface AbstractUnit {
|
data class UnitSearchResultItem(
|
||||||
val id: String
|
val basicUnit: BasicUnit,
|
||||||
val basicUnit: BigDecimal
|
val stats: UnitsEntity,
|
||||||
val group: UnitGroup
|
val conversion: BatchConvertResult?,
|
||||||
val displayName: Int
|
)
|
||||||
val shortName: Int
|
|
||||||
val isFavorite: Boolean
|
|
||||||
val pairId: String?
|
|
||||||
val counter: Int
|
|
||||||
|
|
||||||
fun clone(
|
fun Sequence<UnitSearchResultItem>.filterByLev(
|
||||||
id: String = this.id,
|
stringA: String,
|
||||||
basicUnit: BigDecimal = this.basicUnit,
|
context: Context,
|
||||||
group: UnitGroup = this.group,
|
): Sequence<UnitSearchResultItem> {
|
||||||
displayName: Int = this.displayName,
|
|
||||||
shortName: Int = this.shortName,
|
|
||||||
isFavorite: Boolean = this.isFavorite,
|
|
||||||
pairId: String? = this.pairId,
|
|
||||||
counter: Int = this.counter,
|
|
||||||
): AbstractUnit
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Sequence<AbstractUnit>.filterByLev(stringA: String, context: Context): Sequence<AbstractUnit> {
|
|
||||||
val stringToCompare = stringA.trim().lowercase()
|
val stringToCompare = stringA.trim().lowercase()
|
||||||
// We don't need units where name is too different, half of the symbols is wrong in this situation
|
// We don't need units where name is too different, half of the symbols is wrong in this situation
|
||||||
val threshold: Int = stringToCompare.length / 2
|
val threshold: Int = stringToCompare.length / 2
|
||||||
// List of pair: Unit and it's levDist
|
// List of pair: Unit and it's levDist
|
||||||
val unitsWithDist = mutableListOf<Pair<AbstractUnit, Int>>()
|
val unitsWithDist = mutableListOf<Pair<UnitSearchResultItem, Int>>()
|
||||||
this.forEach { unit ->
|
this.forEach { unit ->
|
||||||
val unitShortName: String = context
|
val unitShortName: String = context
|
||||||
.getString(unit.shortName)
|
.getString(unit.basicUnit.shortName)
|
||||||
.lowercase()
|
.lowercase()
|
||||||
.normalizeSuperscript()
|
.normalizeSuperscript()
|
||||||
/**
|
/**
|
||||||
@ -67,7 +54,7 @@ fun Sequence<AbstractUnit>.filterByLev(stringA: String, context: Context): Seque
|
|||||||
}
|
}
|
||||||
|
|
||||||
val unitFullName: String = context
|
val unitFullName: String = context
|
||||||
.getString(unit.displayName)
|
.getString(unit.basicUnit.displayName)
|
||||||
.lowercase()
|
.lowercase()
|
||||||
.normalizeSuperscript()
|
.normalizeSuperscript()
|
||||||
|
|
@ -20,6 +20,10 @@ package com.sadellie.unitto.data.converter
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import com.sadellie.unitto.core.base.Token
|
||||||
|
import com.sadellie.unitto.data.common.isGreaterThan
|
||||||
|
import com.sadellie.unitto.data.common.isLessThan
|
||||||
|
import com.sadellie.unitto.data.common.trimZeros
|
||||||
import com.sadellie.unitto.data.converter.collections.accelerationCollection
|
import com.sadellie.unitto.data.converter.collections.accelerationCollection
|
||||||
import com.sadellie.unitto.data.converter.collections.angleCollection
|
import com.sadellie.unitto.data.converter.collections.angleCollection
|
||||||
import com.sadellie.unitto.data.converter.collections.areaCollection
|
import com.sadellie.unitto.data.converter.collections.areaCollection
|
||||||
@ -49,22 +53,16 @@ import com.sadellie.unitto.data.database.CurrencyRatesDao
|
|||||||
import com.sadellie.unitto.data.database.CurrencyRatesEntity
|
import com.sadellie.unitto.data.database.CurrencyRatesEntity
|
||||||
import com.sadellie.unitto.data.database.UnitsDao
|
import com.sadellie.unitto.data.database.UnitsDao
|
||||||
import com.sadellie.unitto.data.database.UnitsEntity
|
import com.sadellie.unitto.data.database.UnitsEntity
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.repository.UnitsRepository
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
|
||||||
import com.sadellie.unitto.data.model.unit.ReverseUnit
|
|
||||||
import com.sadellie.unitto.data.model.unit.filterByLev
|
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import io.github.sadellie.evaluatto.Expression
|
||||||
|
import io.github.sadellie.evaluatto.ExpressionException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.combine
|
|
||||||
import kotlinx.coroutines.flow.first
|
|
||||||
import kotlinx.coroutines.flow.flowOn
|
|
||||||
import kotlinx.coroutines.flow.update
|
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
import java.math.RoundingMode
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@ -72,9 +70,8 @@ class UnitsRepositoryImpl @Inject constructor(
|
|||||||
private val unitsDao: UnitsDao,
|
private val unitsDao: UnitsDao,
|
||||||
private val currencyRatesDao: CurrencyRatesDao,
|
private val currencyRatesDao: CurrencyRatesDao,
|
||||||
@ApplicationContext private val mContext: Context,
|
@ApplicationContext private val mContext: Context,
|
||||||
) : UnitsRepository {
|
) {
|
||||||
private val inMemoryUnits = MutableStateFlow(
|
private val inMemory = lengthCollection +
|
||||||
lengthCollection +
|
|
||||||
currencyCollection +
|
currencyCollection +
|
||||||
massCollection +
|
massCollection +
|
||||||
speedCollection +
|
speedCollection +
|
||||||
@ -97,62 +94,34 @@ class UnitsRepositoryImpl @Inject constructor(
|
|||||||
torqueCollection +
|
torqueCollection +
|
||||||
flowRateCollection +
|
flowRateCollection +
|
||||||
luminanceCollection +
|
luminanceCollection +
|
||||||
fuelConsumptionCollection,
|
fuelConsumptionCollection
|
||||||
)
|
|
||||||
|
|
||||||
override val units: Flow<List<AbstractUnit>> = combine(
|
suspend fun getById(id: String): BasicUnit = withContext(Dispatchers.Default) {
|
||||||
unitsDao.getAllFlow(),
|
return@withContext inMemory.first { it.id == id }
|
||||||
inMemoryUnits,
|
|
||||||
) { basedList, inMemoryList ->
|
|
||||||
return@combine inMemoryList.map { inMemoryUnit ->
|
|
||||||
val inBaseUnit = basedList.find { it.unitId == inMemoryUnit.id }
|
|
||||||
?: return@map inMemoryUnit
|
|
||||||
inMemoryUnit.clone(
|
|
||||||
isFavorite = inBaseUnit.isFavorite,
|
|
||||||
counter = inBaseUnit.frequency,
|
|
||||||
pairId = inBaseUnit.pairedUnitId,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.flowOn(Dispatchers.IO)
|
|
||||||
|
|
||||||
override suspend fun getById(id: String): AbstractUnit {
|
|
||||||
return units.first().first { it.id == id }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getCollection(group: UnitGroup): List<AbstractUnit> {
|
suspend fun getPairId(id: String): String = withContext(Dispatchers.IO) {
|
||||||
return units.first().filter { it.group == group }
|
val basedUnitPair = getUnitStats(id).pairedUnitId
|
||||||
|
if (basedUnitPair != null) return@withContext basedUnitPair
|
||||||
|
|
||||||
|
val inMemoryUnit = inMemory.first { it.id == id }
|
||||||
|
val collection = inMemory.filter { it.group == inMemoryUnit.group }
|
||||||
|
|
||||||
|
val pair = collection
|
||||||
|
.map { getById(it.id) to getUnitStats(it.id) }
|
||||||
|
.sortedByDescending { it.second.frequency }
|
||||||
|
.firstOrNull { it.second.isFavorite }?.first ?: collection.first()
|
||||||
|
|
||||||
|
return@withContext pair.id
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun favorite(unit: AbstractUnit) = withContext(Dispatchers.IO) {
|
suspend fun incrementCounter(id: String) = withContext(Dispatchers.IO) {
|
||||||
val basedUnit = unitsDao.getById(unit.id)
|
val basedUnit = unitsDao.getById(id)
|
||||||
|
|
||||||
if (basedUnit == null) {
|
if (basedUnit == null) {
|
||||||
unitsDao.insertUnit(
|
unitsDao.insertUnit(
|
||||||
UnitsEntity(
|
UnitsEntity(
|
||||||
unitId = unit.id,
|
unitId = id,
|
||||||
isFavorite = true,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
unitsDao.insertUnit(
|
|
||||||
UnitsEntity(
|
|
||||||
unitId = basedUnit.unitId,
|
|
||||||
isFavorite = !basedUnit.isFavorite,
|
|
||||||
pairedUnitId = basedUnit.pairedUnitId,
|
|
||||||
frequency = basedUnit.frequency,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun incrementCounter(unit: AbstractUnit) = withContext(Dispatchers.IO) {
|
|
||||||
val basedUnit = unitsDao.getById(unit.id)
|
|
||||||
|
|
||||||
if (basedUnit == null) {
|
|
||||||
unitsDao.insertUnit(
|
|
||||||
UnitsEntity(
|
|
||||||
unitId = unit.id,
|
|
||||||
frequency = 1,
|
frequency = 1,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -168,14 +137,17 @@ class UnitsRepositoryImpl @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setPair(unit: AbstractUnit, pair: AbstractUnit) = withContext(Dispatchers.IO) {
|
suspend fun setPair(
|
||||||
val basedUnit = unitsDao.getById(unit.id)
|
id: String,
|
||||||
|
pairId: String,
|
||||||
|
) = withContext(Dispatchers.IO) {
|
||||||
|
val basedUnit = unitsDao.getById(id)
|
||||||
|
|
||||||
if (basedUnit == null) {
|
if (basedUnit == null) {
|
||||||
unitsDao.insertUnit(
|
unitsDao.insertUnit(
|
||||||
UnitsEntity(
|
UnitsEntity(
|
||||||
unitId = unit.id,
|
unitId = id,
|
||||||
pairedUnitId = pair.id,
|
pairedUnitId = pairId,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
@ -183,95 +155,375 @@ class UnitsRepositoryImpl @Inject constructor(
|
|||||||
UnitsEntity(
|
UnitsEntity(
|
||||||
unitId = basedUnit.unitId,
|
unitId = basedUnit.unitId,
|
||||||
isFavorite = basedUnit.isFavorite,
|
isFavorite = basedUnit.isFavorite,
|
||||||
pairedUnitId = pair.id,
|
pairedUnitId = pairId,
|
||||||
frequency = basedUnit.frequency,
|
frequency = basedUnit.frequency,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateRates(unit: AbstractUnit): LocalDate? = withContext(Dispatchers.IO) {
|
suspend fun favorite(id: String) = withContext(Dispatchers.IO) {
|
||||||
var basedConversions = currencyRatesDao.getLatestRates(baseId = unit.id)
|
val basedUnit = unitsDao.getById(id)
|
||||||
val epochDay = LocalDate.now().toEpochDay()
|
|
||||||
|
|
||||||
if (basedConversions.firstOrNull()?.date != epochDay) {
|
if (basedUnit == null) {
|
||||||
|
unitsDao.insertUnit(
|
||||||
|
UnitsEntity(
|
||||||
|
unitId = id,
|
||||||
|
isFavorite = true,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
unitsDao.insertUnit(
|
||||||
|
UnitsEntity(
|
||||||
|
unitId = basedUnit.unitId,
|
||||||
|
isFavorite = !basedUnit.isFavorite,
|
||||||
|
pairedUnitId = basedUnit.pairedUnitId,
|
||||||
|
frequency = basedUnit.frequency,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun filterUnits(
|
||||||
|
query: String,
|
||||||
|
unitGroups: List<UnitGroup>,
|
||||||
|
favoritesOnly: Boolean,
|
||||||
|
sorting: UnitsListSorting,
|
||||||
|
): Map<UnitGroup, List<UnitSearchResultItem>> = withContext(Dispatchers.IO) {
|
||||||
|
return@withContext filterUnitCollections(
|
||||||
|
query = query,
|
||||||
|
unitGroups = unitGroups,
|
||||||
|
favoritesOnly = favoritesOnly,
|
||||||
|
sorting = sorting,
|
||||||
|
)
|
||||||
|
.groupBy { it.basicUnit.group }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun filterUnitsAndBatchConvert(
|
||||||
|
query: String,
|
||||||
|
unitGroup: UnitGroup,
|
||||||
|
favoritesOnly: Boolean,
|
||||||
|
sorting: UnitsListSorting,
|
||||||
|
unitFromId: String,
|
||||||
|
input: String?,
|
||||||
|
): Map<UnitGroup, List<UnitSearchResultItem>> = withContext(Dispatchers.IO) {
|
||||||
|
val units = filterUnitCollections(
|
||||||
|
query = query,
|
||||||
|
unitGroups = listOf(unitGroup),
|
||||||
|
favoritesOnly = favoritesOnly,
|
||||||
|
sorting = sorting,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (input == null) {
|
||||||
|
return@withContext units.groupBy { it.basicUnit.group }
|
||||||
|
}
|
||||||
|
|
||||||
|
val unitWithConversions = try {
|
||||||
|
when (unitGroup) {
|
||||||
|
UnitGroup.CURRENCY -> {
|
||||||
|
val inputBD = BigDecimal(input)
|
||||||
|
|
||||||
|
val validCurrencyPairs = withContext(Dispatchers.IO) {
|
||||||
|
currencyRatesDao.getLatestRates(unitFromId)
|
||||||
|
}
|
||||||
|
.filter { it.pairUnitValue?.isGreaterThan(BigDecimal.ZERO) ?: false }
|
||||||
|
|
||||||
|
val validIds = validCurrencyPairs.map { it.pairUnitId }
|
||||||
|
|
||||||
|
units
|
||||||
|
.filter { it.basicUnit.id in validIds }
|
||||||
|
.map { unitTo ->
|
||||||
|
unitTo.basicUnit as BasicUnit.Default
|
||||||
|
val factor = validCurrencyPairs
|
||||||
|
.first { it.pairUnitId == unitTo.basicUnit.id }
|
||||||
|
.pairUnitValue
|
||||||
|
val conversion = inputBD.multiply(factor)
|
||||||
|
|
||||||
|
unitTo.copy(
|
||||||
|
conversion = DefaultBatchConvertResult(conversion),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnitGroup.NUMBER_BASE -> {
|
||||||
|
val unitFrom = getById(unitFromId) as BasicUnit.NumberBase
|
||||||
|
|
||||||
|
units.map { unitTo ->
|
||||||
|
unitTo.basicUnit as BasicUnit.NumberBase
|
||||||
|
val conversion = unitFrom.convert(unitTo.basicUnit, input)
|
||||||
|
|
||||||
|
unitTo.copy(
|
||||||
|
conversion = NumberBaseBatchConvertResult(conversion),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val unitFrom = getById(unitFromId) as BasicUnit.Default
|
||||||
|
val inputBD = BigDecimal(input)
|
||||||
|
|
||||||
|
units.map { unitTo ->
|
||||||
|
unitTo.basicUnit as BasicUnit.Default
|
||||||
|
val conversion = unitFrom.convert(unitTo.basicUnit, inputBD)
|
||||||
|
|
||||||
|
unitTo.copy(
|
||||||
|
conversion = DefaultBatchConvertResult(conversion),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Log.e("UnitsRepositoryImpl", "Failed to batch convert: $e")
|
||||||
|
units
|
||||||
|
}
|
||||||
|
|
||||||
|
return@withContext unitWithConversions.groupBy { it.basicUnit.group }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun convertDefault(
|
||||||
|
unitFromId: String,
|
||||||
|
unitToId: String,
|
||||||
|
value1: String,
|
||||||
|
value2: String,
|
||||||
|
formatTime: Boolean,
|
||||||
|
): ConverterResult = withContext(Dispatchers.Default) {
|
||||||
|
val calculated: BigDecimal = try {
|
||||||
|
// Calculate expression in first text field
|
||||||
|
var calculated1 = Expression(value1.ifEmpty { Token.Digit._0 }).calculate()
|
||||||
|
|
||||||
|
// Calculate expression in second text field
|
||||||
|
if (unitFromId == UnitID.foot) {
|
||||||
|
val calculatedInches = Expression(value2.ifEmpty { Token.Digit._0 }).calculate()
|
||||||
|
// turn inches into feet so that it all comes down to converting from feet only
|
||||||
|
val inches = getById(UnitID.inch) as BasicUnit.Default
|
||||||
|
val feet = getById(UnitID.foot) as BasicUnit.Default
|
||||||
|
val inchesConvertedToFeet = inches.convert(feet, calculatedInches)
|
||||||
|
|
||||||
|
calculated1 += inchesConvertedToFeet
|
||||||
|
}
|
||||||
|
|
||||||
|
calculated1
|
||||||
|
} catch (e: ExpressionException.DivideByZero) {
|
||||||
|
return@withContext ConverterResult.Error.DivideByZero
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return@withContext ConverterResult.Error.BadInput
|
||||||
|
}
|
||||||
|
|
||||||
|
return@withContext try {
|
||||||
|
val unitFrom = getById(unitFromId) as BasicUnit.Default
|
||||||
|
val unitTo = getById(unitToId) as BasicUnit.Default
|
||||||
|
|
||||||
|
when {
|
||||||
|
(unitFrom.group == UnitGroup.TIME) and (formatTime) ->
|
||||||
|
convertTime(unitFrom, calculated)
|
||||||
|
|
||||||
|
unitTo.id == UnitID.foot ->
|
||||||
|
convertToFoot(unitFrom, unitTo, calculated)
|
||||||
|
|
||||||
|
unitFrom.group == UnitGroup.CURRENCY ->
|
||||||
|
convertCurrencies(unitFromId, unitToId, calculated)
|
||||||
|
|
||||||
|
else ->
|
||||||
|
convertDefault(unitFrom, unitTo, calculated)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ConverterResult.Error.ConversionError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun convertNumberBase(
|
||||||
|
unitFromId: String,
|
||||||
|
unitToId: String,
|
||||||
|
value: String,
|
||||||
|
): ConverterResult = withContext(Dispatchers.Default) {
|
||||||
|
return@withContext try {
|
||||||
|
val unitFrom = getById(unitFromId) as BasicUnit.NumberBase
|
||||||
|
val unitTo = getById(unitToId) as BasicUnit.NumberBase
|
||||||
|
val conversion = unitFrom.convert(unitTo, value)
|
||||||
|
|
||||||
|
ConverterResult.NumberBase(conversion)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
ConverterResult.Error.ConversionError
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun getUnitStats(id: String): UnitsEntity = withContext(Dispatchers.IO) {
|
||||||
|
unitsDao.getById(id) ?: UnitsEntity(unitId = id)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun convertDefault(
|
||||||
|
unitFrom: BasicUnit.Default,
|
||||||
|
unitTo: BasicUnit.Default,
|
||||||
|
value: BigDecimal,
|
||||||
|
): ConverterResult.Default = ConverterResult.Default(unitFrom.convert(unitTo, value), value)
|
||||||
|
|
||||||
|
internal fun convertTime(
|
||||||
|
unitFrom: BasicUnit.Default,
|
||||||
|
value: BigDecimal,
|
||||||
|
): ConverterResult.Time {
|
||||||
|
val input = value.multiply(unitFrom.factor)
|
||||||
|
|
||||||
|
val negative = input < BigDecimal.ZERO
|
||||||
|
val inputAbs = input.abs()
|
||||||
|
|
||||||
|
if (inputAbs.isLessThan(attosecondBasicUnit)) {
|
||||||
|
return ConverterResult.Time(
|
||||||
|
negative = negative,
|
||||||
|
day = BigDecimal.ZERO,
|
||||||
|
hour = BigDecimal.ZERO,
|
||||||
|
minute = BigDecimal.ZERO,
|
||||||
|
second = BigDecimal.ZERO,
|
||||||
|
millisecond = BigDecimal.ZERO,
|
||||||
|
microsecond = BigDecimal.ZERO,
|
||||||
|
nanosecond = BigDecimal.ZERO,
|
||||||
|
attosecond = inputAbs,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputAbs.isLessThan(nanosecondBasicUnit)) {
|
||||||
|
return ConverterResult.Time(
|
||||||
|
negative = negative,
|
||||||
|
day = BigDecimal.ZERO,
|
||||||
|
hour = BigDecimal.ZERO,
|
||||||
|
minute = BigDecimal.ZERO,
|
||||||
|
second = BigDecimal.ZERO,
|
||||||
|
millisecond = BigDecimal.ZERO,
|
||||||
|
microsecond = BigDecimal.ZERO,
|
||||||
|
nanosecond = BigDecimal.ZERO,
|
||||||
|
attosecond = inputAbs.trimZeros(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DAY
|
||||||
|
var division = inputAbs.divideAndRemainder(dayBasicUnit)
|
||||||
|
val day = division.component1().setScale(0, RoundingMode.HALF_EVEN)
|
||||||
|
var remainingSeconds = division.component2().setScale(0, RoundingMode.HALF_EVEN)
|
||||||
|
|
||||||
|
division = remainingSeconds.divideAndRemainder(hourBasicUnit)
|
||||||
|
val hour = division.component1()
|
||||||
|
remainingSeconds = division.component2()
|
||||||
|
|
||||||
|
division = remainingSeconds.divideAndRemainder(minuteBasicUnit)
|
||||||
|
val minute = division.component1()
|
||||||
|
remainingSeconds = division.component2()
|
||||||
|
|
||||||
|
division = remainingSeconds.divideAndRemainder(secondBasicUnit)
|
||||||
|
val second = division.component1()
|
||||||
|
remainingSeconds = division.component2()
|
||||||
|
|
||||||
|
division = remainingSeconds.divideAndRemainder(millisecondBasicUnit)
|
||||||
|
val millisecond = division.component1()
|
||||||
|
remainingSeconds = division.component2()
|
||||||
|
|
||||||
|
division = remainingSeconds.divideAndRemainder(microsecondBasicUnit)
|
||||||
|
val microsecond = division.component1()
|
||||||
|
remainingSeconds = division.component2()
|
||||||
|
|
||||||
|
division = remainingSeconds.divideAndRemainder(nanosecondBasicUnit)
|
||||||
|
val nanosecond = division.component1()
|
||||||
|
remainingSeconds = division.component2()
|
||||||
|
|
||||||
|
val attosecond = remainingSeconds
|
||||||
|
|
||||||
|
return ConverterResult.Time(
|
||||||
|
negative = negative,
|
||||||
|
day = day,
|
||||||
|
hour = hour,
|
||||||
|
minute = minute,
|
||||||
|
second = second,
|
||||||
|
millisecond = millisecond,
|
||||||
|
microsecond = microsecond,
|
||||||
|
nanosecond = nanosecond,
|
||||||
|
attosecond = attosecond,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun convertToFoot(
|
||||||
|
unitFrom: BasicUnit.Default,
|
||||||
|
unitTo: BasicUnit.Default,
|
||||||
|
value: BigDecimal,
|
||||||
|
): ConverterResult.FootInch = ConverterResult.FootInch.fromBigDecimal(
|
||||||
|
input = unitFrom.convert(unitTo, value),
|
||||||
|
footUnit = unitTo,
|
||||||
|
inchUnit = getById(UnitID.inch) as BasicUnit.Default,
|
||||||
|
)
|
||||||
|
|
||||||
|
private suspend fun convertCurrencies(
|
||||||
|
unitFromId: String,
|
||||||
|
unitToId: String,
|
||||||
|
value: BigDecimal,
|
||||||
|
): ConverterResult = withContext(Dispatchers.IO) {
|
||||||
|
refreshCurrencyRates(unitFromId)
|
||||||
|
|
||||||
|
val latestRate = currencyRatesDao.getLatestRate(unitFromId, unitToId)
|
||||||
|
if (latestRate?.pairUnitValue == null) return@withContext ConverterResult.Error.Currency
|
||||||
|
|
||||||
|
val conversion = value.multiply(latestRate.pairUnitValue)
|
||||||
|
|
||||||
|
return@withContext ConverterResult.Default(conversion, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun filterUnitCollections(
|
||||||
|
query: String,
|
||||||
|
unitGroups: List<UnitGroup>,
|
||||||
|
favoritesOnly: Boolean,
|
||||||
|
sorting: UnitsListSorting,
|
||||||
|
): Sequence<UnitSearchResultItem> = withContext(Dispatchers.IO) {
|
||||||
|
var units = inMemory
|
||||||
|
.filter { it.group in unitGroups }
|
||||||
|
.map { UnitSearchResultItem(it, getUnitStats(it.id), null) }
|
||||||
|
.asSequence()
|
||||||
|
|
||||||
|
if (favoritesOnly) {
|
||||||
|
units = units.filter { it.stats.isFavorite }
|
||||||
|
}
|
||||||
|
|
||||||
|
units = when (sorting) {
|
||||||
|
UnitsListSorting.USAGE -> units.sortedByDescending { it.stats.frequency }
|
||||||
|
UnitsListSorting.ALPHABETICAL -> units.sortedBy { mContext.getString(it.basicUnit.displayName) }
|
||||||
|
UnitsListSorting.SCALE_ASC -> units.sortedBy { it.basicUnit.factor }
|
||||||
|
UnitsListSorting.SCALE_DESC -> units.sortedByDescending { it.basicUnit.factor }
|
||||||
|
else -> units
|
||||||
|
}
|
||||||
|
|
||||||
|
units = if (query.isEmpty()) {
|
||||||
|
units.sortedByDescending { it.stats.isFavorite }
|
||||||
|
} else {
|
||||||
|
units.filterByLev(query, mContext)
|
||||||
|
}
|
||||||
|
return@withContext units
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun refreshCurrencyRates(unitFromId: String) = withContext(Dispatchers.IO) {
|
||||||
|
val latestUpdateDate = currencyRatesDao.getLatestRateTimeStamp(unitFromId)
|
||||||
|
val currentDate = LocalDate.now().toEpochDay()
|
||||||
|
|
||||||
|
if (latestUpdateDate != currentDate) {
|
||||||
|
// Need to update cache needed
|
||||||
try {
|
try {
|
||||||
val conversions = CurrencyApi.service.getCurrencyPairs(unit.id)
|
val conversions = CurrencyApi.service.getCurrencyPairs(unitFromId)
|
||||||
val rates = conversions.currency
|
val rates = conversions.currency
|
||||||
.map { (pairId, pairValue) ->
|
.map { (pairId, pairValue) ->
|
||||||
CurrencyRatesEntity(
|
CurrencyRatesEntity(
|
||||||
baseUnitId = unit.id,
|
baseUnitId = unitFromId,
|
||||||
date = epochDay,
|
date = currentDate,
|
||||||
pairUnitId = pairId,
|
pairUnitId = pairId,
|
||||||
pairUnitValue = BigDecimal.valueOf(pairValue),
|
pairUnitValue = BigDecimal.valueOf(pairValue),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
currencyRatesDao.insertRates(rates)
|
currencyRatesDao.insertRates(rates)
|
||||||
|
|
||||||
basedConversions = currencyRatesDao.getLatestRates(baseId = unit.id)
|
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Log.d("UnitsRepository", "Skipped update: $e")
|
Log.d("UnitsRepositoryImpl", "Skipped update: $e")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inMemoryUnits.update { units ->
|
|
||||||
units.map { localUnit ->
|
|
||||||
if (localUnit.group != UnitGroup.CURRENCY) return@map localUnit
|
|
||||||
if (localUnit !is ReverseUnit) return@map localUnit
|
|
||||||
|
|
||||||
val rate = basedConversions
|
|
||||||
.firstOrNull { localUnit.id == it.pairUnitId }
|
|
||||||
?.pairUnitValue ?: BigDecimal.ZERO
|
|
||||||
|
|
||||||
return@map if (rate > BigDecimal.ZERO) {
|
|
||||||
localUnit.copy(basicUnit = rate)
|
|
||||||
} else {
|
|
||||||
localUnit.copy(basicUnit = BigDecimal.ZERO)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return@withContext basedConversions
|
|
||||||
.firstOrNull()
|
|
||||||
?.date
|
|
||||||
?.let { LocalDate.ofEpochDay(it) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override suspend fun filterUnits(
|
|
||||||
query: String,
|
|
||||||
unitGroup: UnitGroup?,
|
|
||||||
favoritesOnly: Boolean,
|
|
||||||
hideBrokenUnits: Boolean,
|
|
||||||
sorting: UnitsListSorting,
|
|
||||||
shownUnitGroups: List<UnitGroup>,
|
|
||||||
): Map<UnitGroup, List<AbstractUnit>> {
|
|
||||||
// Leave only shown unit groups
|
|
||||||
var units: Sequence<AbstractUnit> = if (unitGroup == null) {
|
|
||||||
units.first().filter { it.group in shownUnitGroups }
|
|
||||||
} else {
|
|
||||||
getCollection(unitGroup)
|
|
||||||
}.asSequence()
|
|
||||||
|
|
||||||
if (favoritesOnly) {
|
|
||||||
units = units.filter { it.isFavorite }
|
|
||||||
}
|
|
||||||
if (hideBrokenUnits) {
|
|
||||||
units = units.filter { it.basicUnit > BigDecimal.ZERO }
|
|
||||||
}
|
|
||||||
|
|
||||||
units = when (sorting) {
|
|
||||||
UnitsListSorting.USAGE -> units.sortedByDescending { it.counter }
|
|
||||||
UnitsListSorting.ALPHABETICAL -> units.sortedBy { mContext.getString(it.displayName) }
|
|
||||||
UnitsListSorting.SCALE_ASC -> units.sortedBy { it.basicUnit }
|
|
||||||
UnitsListSorting.SCALE_DESC -> units.sortedByDescending { it.basicUnit }
|
|
||||||
else -> units
|
|
||||||
}
|
|
||||||
|
|
||||||
units = if (query.isEmpty()) {
|
|
||||||
units.sortedByDescending { it.isFavorite }
|
|
||||||
} else {
|
|
||||||
// For search we sort by popularity and Levenshtein distance (short and long name).
|
|
||||||
units.filterByLev(query, mContext)
|
|
||||||
}
|
|
||||||
return units.groupBy { it.group }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val dayBasicUnit by lazy { BigDecimal("86400000000000000000000") }
|
||||||
|
private val hourBasicUnit by lazy { BigDecimal("3600000000000000000000") }
|
||||||
|
private val minuteBasicUnit by lazy { BigDecimal("60000000000000000000") }
|
||||||
|
private val secondBasicUnit by lazy { BigDecimal("1000000000000000000") }
|
||||||
|
private val millisecondBasicUnit by lazy { BigDecimal("1000000000000000") }
|
||||||
|
private val microsecondBasicUnit by lazy { BigDecimal("1000000000000") }
|
||||||
|
private val nanosecondBasicUnit by lazy { BigDecimal("1000000000") }
|
||||||
|
private val attosecondBasicUnit by lazy { BigDecimal("1") }
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val accelerationCollection: List<AbstractUnit> by lazy {
|
internal val accelerationCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.attometer_per_square_second, BigDecimal("1"), UnitGroup.ACCELERATION, R.string.unit_attometer_per_square_second, R.string.unit_attometer_per_square_second_short),
|
NormalUnit(UnitID.attometer_per_square_second, BigDecimal("1"), UnitGroup.ACCELERATION, R.string.unit_attometer_per_square_second, R.string.unit_attometer_per_square_second_short),
|
||||||
NormalUnit(UnitID.femtometer_per_square_second, BigDecimal("1000"), UnitGroup.ACCELERATION, R.string.unit_femtometer_per_square_second, R.string.unit_femtometer_per_square_second_short),
|
NormalUnit(UnitID.femtometer_per_square_second, BigDecimal("1000"), UnitGroup.ACCELERATION, R.string.unit_femtometer_per_square_second, R.string.unit_femtometer_per_square_second_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val angleCollection: List<AbstractUnit> by lazy {
|
internal val angleCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.angle_second, BigDecimal("1"), UnitGroup.ANGLE, R.string.unit_angle_second, R.string.unit_angle_second_short),
|
NormalUnit(UnitID.angle_second, BigDecimal("1"), UnitGroup.ANGLE, R.string.unit_angle_second, R.string.unit_angle_second_short),
|
||||||
NormalUnit(UnitID.angle_minute, BigDecimal("60"), UnitGroup.ANGLE, R.string.unit_angle_minute, R.string.unit_angle_minute_short),
|
NormalUnit(UnitID.angle_minute, BigDecimal("60"), UnitGroup.ANGLE, R.string.unit_angle_minute, R.string.unit_angle_minute_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val areaCollection: List<AbstractUnit> by lazy {
|
internal val areaCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.cent, BigDecimal("6083246572000000000000000000000000"), UnitGroup.AREA, R.string.unit_cent, R.string.unit_cent_short),
|
NormalUnit(UnitID.cent, BigDecimal("6083246572000000000000000000000000"), UnitGroup.AREA, R.string.unit_cent, R.string.unit_cent_short),
|
||||||
NormalUnit(UnitID.acre, BigDecimal("60832465720000000000000000000000"), UnitGroup.AREA, R.string.unit_acre, R.string.unit_acre_short),
|
NormalUnit(UnitID.acre, BigDecimal("60832465720000000000000000000000"), UnitGroup.AREA, R.string.unit_acre, R.string.unit_acre_short),
|
||||||
|
@ -19,221 +19,221 @@
|
|||||||
package com.sadellie.unitto.data.converter.collections
|
package com.sadellie.unitto.data.converter.collections
|
||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
|
||||||
import com.sadellie.unitto.data.model.unit.ReverseUnit
|
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val currencyCollection: List<AbstractUnit> by lazy {
|
internal val currencyCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
ReverseUnit(UnitID.currency_1inch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_1inch, R.string.unit_currency_1inch_short),
|
NormalUnit(UnitID.currency_1inch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_1inch, R.string.unit_currency_1inch_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ada, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ada, R.string.unit_currency_ada_short),
|
NormalUnit(UnitID.currency_ada, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ada, R.string.unit_currency_ada_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_aed, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aed, R.string.unit_currency_aed_short),
|
NormalUnit(UnitID.currency_aed, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aed, R.string.unit_currency_aed_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_afn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_afn, R.string.unit_currency_afn_short),
|
NormalUnit(UnitID.currency_afn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_afn, R.string.unit_currency_afn_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_algo, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_algo, R.string.unit_currency_algo_short),
|
NormalUnit(UnitID.currency_algo, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_algo, R.string.unit_currency_algo_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_all, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_all, R.string.unit_currency_all_short),
|
NormalUnit(UnitID.currency_all, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_all, R.string.unit_currency_all_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_amd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_amd, R.string.unit_currency_amd_short),
|
NormalUnit(UnitID.currency_amd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_amd, R.string.unit_currency_amd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ang, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ang, R.string.unit_currency_ang_short),
|
NormalUnit(UnitID.currency_ang, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ang, R.string.unit_currency_ang_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_aoa, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aoa, R.string.unit_currency_aoa_short),
|
NormalUnit(UnitID.currency_aoa, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aoa, R.string.unit_currency_aoa_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ars, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ars, R.string.unit_currency_ars_short),
|
NormalUnit(UnitID.currency_ars, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ars, R.string.unit_currency_ars_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_atom, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_atom, R.string.unit_currency_atom_short),
|
NormalUnit(UnitID.currency_atom, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_atom, R.string.unit_currency_atom_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_aud, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aud, R.string.unit_currency_aud_short),
|
NormalUnit(UnitID.currency_aud, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_aud, R.string.unit_currency_aud_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_avax, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_avax, R.string.unit_currency_avax_short),
|
NormalUnit(UnitID.currency_avax, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_avax, R.string.unit_currency_avax_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_awg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_awg, R.string.unit_currency_awg_short),
|
NormalUnit(UnitID.currency_awg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_awg, R.string.unit_currency_awg_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_azn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_azn, R.string.unit_currency_azn_short),
|
NormalUnit(UnitID.currency_azn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_azn, R.string.unit_currency_azn_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bam, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bam, R.string.unit_currency_bam_short),
|
NormalUnit(UnitID.currency_bam, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bam, R.string.unit_currency_bam_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bbd, R.string.unit_currency_bbd_short),
|
NormalUnit(UnitID.currency_bbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bbd, R.string.unit_currency_bbd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bch, R.string.unit_currency_bch_short),
|
NormalUnit(UnitID.currency_bch, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bch, R.string.unit_currency_bch_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bdt, R.string.unit_currency_bdt_short),
|
NormalUnit(UnitID.currency_bdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bdt, R.string.unit_currency_bdt_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bgn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bgn, R.string.unit_currency_bgn_short),
|
NormalUnit(UnitID.currency_bgn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bgn, R.string.unit_currency_bgn_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bhd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bhd, R.string.unit_currency_bhd_short),
|
NormalUnit(UnitID.currency_bhd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bhd, R.string.unit_currency_bhd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bif, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bif, R.string.unit_currency_bif_short),
|
NormalUnit(UnitID.currency_bif, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bif, R.string.unit_currency_bif_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bmd, R.string.unit_currency_bmd_short),
|
NormalUnit(UnitID.currency_bmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bmd, R.string.unit_currency_bmd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bnb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnb, R.string.unit_currency_bnb_short),
|
NormalUnit(UnitID.currency_bnb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnb, R.string.unit_currency_bnb_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnd, R.string.unit_currency_bnd_short),
|
NormalUnit(UnitID.currency_bnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bnd, R.string.unit_currency_bnd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bob, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bob, R.string.unit_currency_bob_short),
|
NormalUnit(UnitID.currency_bob, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bob, R.string.unit_currency_bob_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_brl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_brl, R.string.unit_currency_brl_short),
|
NormalUnit(UnitID.currency_brl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_brl, R.string.unit_currency_brl_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bsd, R.string.unit_currency_bsd_short),
|
NormalUnit(UnitID.currency_bsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bsd, R.string.unit_currency_bsd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_btc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btc, R.string.unit_currency_btc_short),
|
NormalUnit(UnitID.currency_btc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btc, R.string.unit_currency_btc_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_btn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btn, R.string.unit_currency_btn_short),
|
NormalUnit(UnitID.currency_btn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_btn, R.string.unit_currency_btn_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_busd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_busd, R.string.unit_currency_busd_short),
|
NormalUnit(UnitID.currency_busd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_busd, R.string.unit_currency_busd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bwp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bwp, R.string.unit_currency_bwp_short),
|
NormalUnit(UnitID.currency_bwp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bwp, R.string.unit_currency_bwp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_byn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byn, R.string.unit_currency_byn_short),
|
NormalUnit(UnitID.currency_byn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byn, R.string.unit_currency_byn_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_byr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byr, R.string.unit_currency_byr_short),
|
NormalUnit(UnitID.currency_byr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_byr, R.string.unit_currency_byr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_bzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bzd, R.string.unit_currency_bzd_short),
|
NormalUnit(UnitID.currency_bzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_bzd, R.string.unit_currency_bzd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_cad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cad, R.string.unit_currency_cad_short),
|
NormalUnit(UnitID.currency_cad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cad, R.string.unit_currency_cad_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_cdf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cdf, R.string.unit_currency_cdf_short),
|
NormalUnit(UnitID.currency_cdf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cdf, R.string.unit_currency_cdf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_chf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chf, R.string.unit_currency_chf_short),
|
NormalUnit(UnitID.currency_chf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chf, R.string.unit_currency_chf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_chz, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chz, R.string.unit_currency_chz_short),
|
NormalUnit(UnitID.currency_chz, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_chz, R.string.unit_currency_chz_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_clf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clf, R.string.unit_currency_clf_short),
|
NormalUnit(UnitID.currency_clf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clf, R.string.unit_currency_clf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_clp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clp, R.string.unit_currency_clp_short),
|
NormalUnit(UnitID.currency_clp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_clp, R.string.unit_currency_clp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_cny, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cny, R.string.unit_currency_cny_short),
|
NormalUnit(UnitID.currency_cny, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cny, R.string.unit_currency_cny_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_cop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cop, R.string.unit_currency_cop_short),
|
NormalUnit(UnitID.currency_cop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cop, R.string.unit_currency_cop_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_crc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_crc, R.string.unit_currency_crc_short),
|
NormalUnit(UnitID.currency_crc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_crc, R.string.unit_currency_crc_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_cro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cro, R.string.unit_currency_cro_short),
|
NormalUnit(UnitID.currency_cro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cro, R.string.unit_currency_cro_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_cuc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cuc, R.string.unit_currency_cuc_short),
|
NormalUnit(UnitID.currency_cuc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cuc, R.string.unit_currency_cuc_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_cup, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cup, R.string.unit_currency_cup_short),
|
NormalUnit(UnitID.currency_cup, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cup, R.string.unit_currency_cup_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_cve, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cve, R.string.unit_currency_cve_short),
|
NormalUnit(UnitID.currency_cve, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_cve, R.string.unit_currency_cve_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_czk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_czk, R.string.unit_currency_czk_short),
|
NormalUnit(UnitID.currency_czk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_czk, R.string.unit_currency_czk_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_dai, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dai, R.string.unit_currency_dai_short),
|
NormalUnit(UnitID.currency_dai, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dai, R.string.unit_currency_dai_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_djf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_djf, R.string.unit_currency_djf_short),
|
NormalUnit(UnitID.currency_djf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_djf, R.string.unit_currency_djf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_dkk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dkk, R.string.unit_currency_dkk_short),
|
NormalUnit(UnitID.currency_dkk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dkk, R.string.unit_currency_dkk_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_doge, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_doge, R.string.unit_currency_doge_short),
|
NormalUnit(UnitID.currency_doge, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_doge, R.string.unit_currency_doge_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_dop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dop, R.string.unit_currency_dop_short),
|
NormalUnit(UnitID.currency_dop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dop, R.string.unit_currency_dop_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_dot, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dot, R.string.unit_currency_dot_short),
|
NormalUnit(UnitID.currency_dot, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dot, R.string.unit_currency_dot_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_dzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dzd, R.string.unit_currency_dzd_short),
|
NormalUnit(UnitID.currency_dzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_dzd, R.string.unit_currency_dzd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_egld, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egld, R.string.unit_currency_egld_short),
|
NormalUnit(UnitID.currency_egld, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egld, R.string.unit_currency_egld_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_egp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egp, R.string.unit_currency_egp_short),
|
NormalUnit(UnitID.currency_egp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_egp, R.string.unit_currency_egp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_enj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_enj, R.string.unit_currency_enj_short),
|
NormalUnit(UnitID.currency_enj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_enj, R.string.unit_currency_enj_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ern, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ern, R.string.unit_currency_ern_short),
|
NormalUnit(UnitID.currency_ern, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ern, R.string.unit_currency_ern_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_etb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etb, R.string.unit_currency_etb_short),
|
NormalUnit(UnitID.currency_etb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etb, R.string.unit_currency_etb_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_etc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etc, R.string.unit_currency_etc_short),
|
NormalUnit(UnitID.currency_etc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_etc, R.string.unit_currency_etc_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_eth, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eth, R.string.unit_currency_eth_short),
|
NormalUnit(UnitID.currency_eth, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eth, R.string.unit_currency_eth_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_eur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eur, R.string.unit_currency_eur_short),
|
NormalUnit(UnitID.currency_eur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_eur, R.string.unit_currency_eur_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_fil, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fil, R.string.unit_currency_fil_short),
|
NormalUnit(UnitID.currency_fil, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fil, R.string.unit_currency_fil_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_fjd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fjd, R.string.unit_currency_fjd_short),
|
NormalUnit(UnitID.currency_fjd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fjd, R.string.unit_currency_fjd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_fkp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fkp, R.string.unit_currency_fkp_short),
|
NormalUnit(UnitID.currency_fkp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_fkp, R.string.unit_currency_fkp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ftt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ftt, R.string.unit_currency_ftt_short),
|
NormalUnit(UnitID.currency_ftt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ftt, R.string.unit_currency_ftt_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_gbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gbp, R.string.unit_currency_gbp_short),
|
NormalUnit(UnitID.currency_gbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gbp, R.string.unit_currency_gbp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_gel, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gel, R.string.unit_currency_gel_short),
|
NormalUnit(UnitID.currency_gel, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gel, R.string.unit_currency_gel_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ggp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ggp, R.string.unit_currency_ggp_short),
|
NormalUnit(UnitID.currency_ggp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ggp, R.string.unit_currency_ggp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ghs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ghs, R.string.unit_currency_ghs_short),
|
NormalUnit(UnitID.currency_ghs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ghs, R.string.unit_currency_ghs_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_gip, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gip, R.string.unit_currency_gip_short),
|
NormalUnit(UnitID.currency_gip, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gip, R.string.unit_currency_gip_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_gmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gmd, R.string.unit_currency_gmd_short),
|
NormalUnit(UnitID.currency_gmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gmd, R.string.unit_currency_gmd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_gnf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gnf, R.string.unit_currency_gnf_short),
|
NormalUnit(UnitID.currency_gnf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gnf, R.string.unit_currency_gnf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_grt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_grt, R.string.unit_currency_grt_short),
|
NormalUnit(UnitID.currency_grt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_grt, R.string.unit_currency_grt_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_gtq, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gtq, R.string.unit_currency_gtq_short),
|
NormalUnit(UnitID.currency_gtq, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gtq, R.string.unit_currency_gtq_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_gyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gyd, R.string.unit_currency_gyd_short),
|
NormalUnit(UnitID.currency_gyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_gyd, R.string.unit_currency_gyd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_hkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hkd, R.string.unit_currency_hkd_short),
|
NormalUnit(UnitID.currency_hkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hkd, R.string.unit_currency_hkd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_hnl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hnl, R.string.unit_currency_hnl_short),
|
NormalUnit(UnitID.currency_hnl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hnl, R.string.unit_currency_hnl_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_hrk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hrk, R.string.unit_currency_hrk_short),
|
NormalUnit(UnitID.currency_hrk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_hrk, R.string.unit_currency_hrk_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_htg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_htg, R.string.unit_currency_htg_short),
|
NormalUnit(UnitID.currency_htg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_htg, R.string.unit_currency_htg_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_huf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_huf, R.string.unit_currency_huf_short),
|
NormalUnit(UnitID.currency_huf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_huf, R.string.unit_currency_huf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_icp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_icp, R.string.unit_currency_icp_short),
|
NormalUnit(UnitID.currency_icp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_icp, R.string.unit_currency_icp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_idr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_idr, R.string.unit_currency_idr_short),
|
NormalUnit(UnitID.currency_idr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_idr, R.string.unit_currency_idr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ils, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ils, R.string.unit_currency_ils_short),
|
NormalUnit(UnitID.currency_ils, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ils, R.string.unit_currency_ils_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_imp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_imp, R.string.unit_currency_imp_short),
|
NormalUnit(UnitID.currency_imp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_imp, R.string.unit_currency_imp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_inj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inj, R.string.unit_currency_inj_short),
|
NormalUnit(UnitID.currency_inj, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inj, R.string.unit_currency_inj_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_inr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inr, R.string.unit_currency_inr_short),
|
NormalUnit(UnitID.currency_inr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_inr, R.string.unit_currency_inr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_iqd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_iqd, R.string.unit_currency_iqd_short),
|
NormalUnit(UnitID.currency_iqd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_iqd, R.string.unit_currency_iqd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_irr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_irr, R.string.unit_currency_irr_short),
|
NormalUnit(UnitID.currency_irr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_irr, R.string.unit_currency_irr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_isk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_isk, R.string.unit_currency_isk_short),
|
NormalUnit(UnitID.currency_isk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_isk, R.string.unit_currency_isk_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_jep, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jep, R.string.unit_currency_jep_short),
|
NormalUnit(UnitID.currency_jep, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jep, R.string.unit_currency_jep_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_jmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jmd, R.string.unit_currency_jmd_short),
|
NormalUnit(UnitID.currency_jmd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jmd, R.string.unit_currency_jmd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_jod, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jod, R.string.unit_currency_jod_short),
|
NormalUnit(UnitID.currency_jod, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jod, R.string.unit_currency_jod_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_jpy, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jpy, R.string.unit_currency_jpy_short),
|
NormalUnit(UnitID.currency_jpy, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_jpy, R.string.unit_currency_jpy_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_kes, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kes, R.string.unit_currency_kes_short),
|
NormalUnit(UnitID.currency_kes, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kes, R.string.unit_currency_kes_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_kgs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kgs, R.string.unit_currency_kgs_short),
|
NormalUnit(UnitID.currency_kgs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kgs, R.string.unit_currency_kgs_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_khr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_khr, R.string.unit_currency_khr_short),
|
NormalUnit(UnitID.currency_khr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_khr, R.string.unit_currency_khr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_kmf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kmf, R.string.unit_currency_kmf_short),
|
NormalUnit(UnitID.currency_kmf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kmf, R.string.unit_currency_kmf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_kpw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kpw, R.string.unit_currency_kpw_short),
|
NormalUnit(UnitID.currency_kpw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kpw, R.string.unit_currency_kpw_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_krw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_krw, R.string.unit_currency_krw_short),
|
NormalUnit(UnitID.currency_krw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_krw, R.string.unit_currency_krw_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ksm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ksm, R.string.unit_currency_ksm_short),
|
NormalUnit(UnitID.currency_ksm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ksm, R.string.unit_currency_ksm_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_kwd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kwd, R.string.unit_currency_kwd_short),
|
NormalUnit(UnitID.currency_kwd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kwd, R.string.unit_currency_kwd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_kyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kyd, R.string.unit_currency_kyd_short),
|
NormalUnit(UnitID.currency_kyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kyd, R.string.unit_currency_kyd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_kzt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kzt, R.string.unit_currency_kzt_short),
|
NormalUnit(UnitID.currency_kzt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_kzt, R.string.unit_currency_kzt_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_lak, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lak, R.string.unit_currency_lak_short),
|
NormalUnit(UnitID.currency_lak, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lak, R.string.unit_currency_lak_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_lbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lbp, R.string.unit_currency_lbp_short),
|
NormalUnit(UnitID.currency_lbp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lbp, R.string.unit_currency_lbp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_link, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_link, R.string.unit_currency_link_short),
|
NormalUnit(UnitID.currency_link, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_link, R.string.unit_currency_link_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_lkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lkr, R.string.unit_currency_lkr_short),
|
NormalUnit(UnitID.currency_lkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lkr, R.string.unit_currency_lkr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_lrd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lrd, R.string.unit_currency_lrd_short),
|
NormalUnit(UnitID.currency_lrd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lrd, R.string.unit_currency_lrd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_lsl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lsl, R.string.unit_currency_lsl_short),
|
NormalUnit(UnitID.currency_lsl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lsl, R.string.unit_currency_lsl_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ltc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltc, R.string.unit_currency_ltc_short),
|
NormalUnit(UnitID.currency_ltc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltc, R.string.unit_currency_ltc_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ltl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltl, R.string.unit_currency_ltl_short),
|
NormalUnit(UnitID.currency_ltl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ltl, R.string.unit_currency_ltl_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_luna, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_luna, R.string.unit_currency_luna_short),
|
NormalUnit(UnitID.currency_luna, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_luna, R.string.unit_currency_luna_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_lvl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lvl, R.string.unit_currency_lvl_short),
|
NormalUnit(UnitID.currency_lvl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lvl, R.string.unit_currency_lvl_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_lyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lyd, R.string.unit_currency_lyd_short),
|
NormalUnit(UnitID.currency_lyd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_lyd, R.string.unit_currency_lyd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mad, R.string.unit_currency_mad_short),
|
NormalUnit(UnitID.currency_mad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mad, R.string.unit_currency_mad_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_matic, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_matic, R.string.unit_currency_matic_short),
|
NormalUnit(UnitID.currency_matic, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_matic, R.string.unit_currency_matic_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mdl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mdl, R.string.unit_currency_mdl_short),
|
NormalUnit(UnitID.currency_mdl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mdl, R.string.unit_currency_mdl_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mga, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mga, R.string.unit_currency_mga_short),
|
NormalUnit(UnitID.currency_mga, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mga, R.string.unit_currency_mga_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mkd, R.string.unit_currency_mkd_short),
|
NormalUnit(UnitID.currency_mkd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mkd, R.string.unit_currency_mkd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mmk, R.string.unit_currency_mmk_short),
|
NormalUnit(UnitID.currency_mmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mmk, R.string.unit_currency_mmk_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mnt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mnt, R.string.unit_currency_mnt_short),
|
NormalUnit(UnitID.currency_mnt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mnt, R.string.unit_currency_mnt_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mop, R.string.unit_currency_mop_short),
|
NormalUnit(UnitID.currency_mop, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mop, R.string.unit_currency_mop_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mro, R.string.unit_currency_mro_short),
|
NormalUnit(UnitID.currency_mro, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mro, R.string.unit_currency_mro_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mur, R.string.unit_currency_mur_short),
|
NormalUnit(UnitID.currency_mur, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mur, R.string.unit_currency_mur_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mvr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mvr, R.string.unit_currency_mvr_short),
|
NormalUnit(UnitID.currency_mvr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mvr, R.string.unit_currency_mvr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mwk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mwk, R.string.unit_currency_mwk_short),
|
NormalUnit(UnitID.currency_mwk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mwk, R.string.unit_currency_mwk_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mxn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mxn, R.string.unit_currency_mxn_short),
|
NormalUnit(UnitID.currency_mxn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mxn, R.string.unit_currency_mxn_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_myr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_myr, R.string.unit_currency_myr_short),
|
NormalUnit(UnitID.currency_myr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_myr, R.string.unit_currency_myr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_mzn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mzn, R.string.unit_currency_mzn_short),
|
NormalUnit(UnitID.currency_mzn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_mzn, R.string.unit_currency_mzn_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_nad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nad, R.string.unit_currency_nad_short),
|
NormalUnit(UnitID.currency_nad, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nad, R.string.unit_currency_nad_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ngn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ngn, R.string.unit_currency_ngn_short),
|
NormalUnit(UnitID.currency_ngn, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ngn, R.string.unit_currency_ngn_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_nio, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nio, R.string.unit_currency_nio_short),
|
NormalUnit(UnitID.currency_nio, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nio, R.string.unit_currency_nio_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_nok, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nok, R.string.unit_currency_nok_short),
|
NormalUnit(UnitID.currency_nok, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nok, R.string.unit_currency_nok_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_npr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_npr, R.string.unit_currency_npr_short),
|
NormalUnit(UnitID.currency_npr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_npr, R.string.unit_currency_npr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_nzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nzd, R.string.unit_currency_nzd_short),
|
NormalUnit(UnitID.currency_nzd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_nzd, R.string.unit_currency_nzd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_omr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_omr, R.string.unit_currency_omr_short),
|
NormalUnit(UnitID.currency_omr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_omr, R.string.unit_currency_omr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_one, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_one, R.string.unit_currency_one_short),
|
NormalUnit(UnitID.currency_one, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_one, R.string.unit_currency_one_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_pab, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pab, R.string.unit_currency_pab_short),
|
NormalUnit(UnitID.currency_pab, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pab, R.string.unit_currency_pab_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_pen, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pen, R.string.unit_currency_pen_short),
|
NormalUnit(UnitID.currency_pen, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pen, R.string.unit_currency_pen_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_pgk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pgk, R.string.unit_currency_pgk_short),
|
NormalUnit(UnitID.currency_pgk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pgk, R.string.unit_currency_pgk_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_php, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_php, R.string.unit_currency_php_short),
|
NormalUnit(UnitID.currency_php, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_php, R.string.unit_currency_php_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_pkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pkr, R.string.unit_currency_pkr_short),
|
NormalUnit(UnitID.currency_pkr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pkr, R.string.unit_currency_pkr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_pln, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pln, R.string.unit_currency_pln_short),
|
NormalUnit(UnitID.currency_pln, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pln, R.string.unit_currency_pln_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_pyg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pyg, R.string.unit_currency_pyg_short),
|
NormalUnit(UnitID.currency_pyg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_pyg, R.string.unit_currency_pyg_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_qar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_qar, R.string.unit_currency_qar_short),
|
NormalUnit(UnitID.currency_qar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_qar, R.string.unit_currency_qar_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ron, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ron, R.string.unit_currency_ron_short),
|
NormalUnit(UnitID.currency_ron, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ron, R.string.unit_currency_ron_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_rsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rsd, R.string.unit_currency_rsd_short),
|
NormalUnit(UnitID.currency_rsd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rsd, R.string.unit_currency_rsd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_rub, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rub, R.string.unit_currency_rub_short),
|
NormalUnit(UnitID.currency_rub, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rub, R.string.unit_currency_rub_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_rwf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rwf, R.string.unit_currency_rwf_short),
|
NormalUnit(UnitID.currency_rwf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_rwf, R.string.unit_currency_rwf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_sar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sar, R.string.unit_currency_sar_short),
|
NormalUnit(UnitID.currency_sar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sar, R.string.unit_currency_sar_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_sbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sbd, R.string.unit_currency_sbd_short),
|
NormalUnit(UnitID.currency_sbd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sbd, R.string.unit_currency_sbd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_scr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_scr, R.string.unit_currency_scr_short),
|
NormalUnit(UnitID.currency_scr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_scr, R.string.unit_currency_scr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_sdg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sdg, R.string.unit_currency_sdg_short),
|
NormalUnit(UnitID.currency_sdg, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sdg, R.string.unit_currency_sdg_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_sek, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sek, R.string.unit_currency_sek_short),
|
NormalUnit(UnitID.currency_sek, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sek, R.string.unit_currency_sek_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_sgd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sgd, R.string.unit_currency_sgd_short),
|
NormalUnit(UnitID.currency_sgd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sgd, R.string.unit_currency_sgd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_shib, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shib, R.string.unit_currency_shib_short),
|
NormalUnit(UnitID.currency_shib, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shib, R.string.unit_currency_shib_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_shp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shp, R.string.unit_currency_shp_short),
|
NormalUnit(UnitID.currency_shp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_shp, R.string.unit_currency_shp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_sll, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sll, R.string.unit_currency_sll_short),
|
NormalUnit(UnitID.currency_sll, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sll, R.string.unit_currency_sll_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_sol, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sol, R.string.unit_currency_sol_short),
|
NormalUnit(UnitID.currency_sol, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sol, R.string.unit_currency_sol_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_sos, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sos, R.string.unit_currency_sos_short),
|
NormalUnit(UnitID.currency_sos, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_sos, R.string.unit_currency_sos_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_srd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_srd, R.string.unit_currency_srd_short),
|
NormalUnit(UnitID.currency_srd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_srd, R.string.unit_currency_srd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_std, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_std, R.string.unit_currency_std_short),
|
NormalUnit(UnitID.currency_std, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_std, R.string.unit_currency_std_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_svc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_svc, R.string.unit_currency_svc_short),
|
NormalUnit(UnitID.currency_svc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_svc, R.string.unit_currency_svc_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_syp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_syp, R.string.unit_currency_syp_short),
|
NormalUnit(UnitID.currency_syp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_syp, R.string.unit_currency_syp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_szl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_szl, R.string.unit_currency_szl_short),
|
NormalUnit(UnitID.currency_szl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_szl, R.string.unit_currency_szl_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_thb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_thb, R.string.unit_currency_thb_short),
|
NormalUnit(UnitID.currency_thb, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_thb, R.string.unit_currency_thb_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_theta, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_theta, R.string.unit_currency_theta_short),
|
NormalUnit(UnitID.currency_theta, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_theta, R.string.unit_currency_theta_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_tjs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tjs, R.string.unit_currency_tjs_short),
|
NormalUnit(UnitID.currency_tjs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tjs, R.string.unit_currency_tjs_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_tmt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tmt, R.string.unit_currency_tmt_short),
|
NormalUnit(UnitID.currency_tmt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tmt, R.string.unit_currency_tmt_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_tnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tnd, R.string.unit_currency_tnd_short),
|
NormalUnit(UnitID.currency_tnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tnd, R.string.unit_currency_tnd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_top, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_top, R.string.unit_currency_top_short),
|
NormalUnit(UnitID.currency_top, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_top, R.string.unit_currency_top_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_trx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_trx, R.string.unit_currency_trx_short),
|
NormalUnit(UnitID.currency_trx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_trx, R.string.unit_currency_trx_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_try, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_try, R.string.unit_currency_try_short),
|
NormalUnit(UnitID.currency_try, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_try, R.string.unit_currency_try_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ttd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ttd, R.string.unit_currency_ttd_short),
|
NormalUnit(UnitID.currency_ttd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ttd, R.string.unit_currency_ttd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_twd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_twd, R.string.unit_currency_twd_short),
|
NormalUnit(UnitID.currency_twd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_twd, R.string.unit_currency_twd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_tzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tzs, R.string.unit_currency_tzs_short),
|
NormalUnit(UnitID.currency_tzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_tzs, R.string.unit_currency_tzs_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_uah, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uah, R.string.unit_currency_uah_short),
|
NormalUnit(UnitID.currency_uah, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uah, R.string.unit_currency_uah_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_ugx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ugx, R.string.unit_currency_ugx_short),
|
NormalUnit(UnitID.currency_ugx, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_ugx, R.string.unit_currency_ugx_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_uni, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uni, R.string.unit_currency_uni_short),
|
NormalUnit(UnitID.currency_uni, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uni, R.string.unit_currency_uni_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_usd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usd, R.string.unit_currency_usd_short),
|
NormalUnit(UnitID.currency_usd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usd, R.string.unit_currency_usd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_usdc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdc, R.string.unit_currency_usdc_short),
|
NormalUnit(UnitID.currency_usdc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdc, R.string.unit_currency_usdc_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_usdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdt, R.string.unit_currency_usdt_short),
|
NormalUnit(UnitID.currency_usdt, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_usdt, R.string.unit_currency_usdt_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_uyu, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uyu, R.string.unit_currency_uyu_short),
|
NormalUnit(UnitID.currency_uyu, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uyu, R.string.unit_currency_uyu_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_uzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uzs, R.string.unit_currency_uzs_short),
|
NormalUnit(UnitID.currency_uzs, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_uzs, R.string.unit_currency_uzs_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_vef, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vef, R.string.unit_currency_vef_short),
|
NormalUnit(UnitID.currency_vef, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vef, R.string.unit_currency_vef_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_vet, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vet, R.string.unit_currency_vet_short),
|
NormalUnit(UnitID.currency_vet, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vet, R.string.unit_currency_vet_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_vnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vnd, R.string.unit_currency_vnd_short),
|
NormalUnit(UnitID.currency_vnd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vnd, R.string.unit_currency_vnd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_vuv, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vuv, R.string.unit_currency_vuv_short),
|
NormalUnit(UnitID.currency_vuv, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_vuv, R.string.unit_currency_vuv_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_wbtc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wbtc, R.string.unit_currency_wbtc_short),
|
NormalUnit(UnitID.currency_wbtc, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wbtc, R.string.unit_currency_wbtc_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_wst, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wst, R.string.unit_currency_wst_short),
|
NormalUnit(UnitID.currency_wst, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_wst, R.string.unit_currency_wst_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xaf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xaf, R.string.unit_currency_xaf_short),
|
NormalUnit(UnitID.currency_xaf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xaf, R.string.unit_currency_xaf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xag, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xag, R.string.unit_currency_xag_short),
|
NormalUnit(UnitID.currency_xag, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xag, R.string.unit_currency_xag_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xau, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xau, R.string.unit_currency_xau_short),
|
NormalUnit(UnitID.currency_xau, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xau, R.string.unit_currency_xau_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xcd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xcd, R.string.unit_currency_xcd_short),
|
NormalUnit(UnitID.currency_xcd, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xcd, R.string.unit_currency_xcd_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xdr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xdr, R.string.unit_currency_xdr_short),
|
NormalUnit(UnitID.currency_xdr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xdr, R.string.unit_currency_xdr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xlm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xlm, R.string.unit_currency_xlm_short),
|
NormalUnit(UnitID.currency_xlm, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xlm, R.string.unit_currency_xlm_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xmr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xmr, R.string.unit_currency_xmr_short),
|
NormalUnit(UnitID.currency_xmr, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xmr, R.string.unit_currency_xmr_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xof, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xof, R.string.unit_currency_xof_short),
|
NormalUnit(UnitID.currency_xof, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xof, R.string.unit_currency_xof_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xpf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xpf, R.string.unit_currency_xpf_short),
|
NormalUnit(UnitID.currency_xpf, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xpf, R.string.unit_currency_xpf_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_xrp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xrp, R.string.unit_currency_xrp_short),
|
NormalUnit(UnitID.currency_xrp, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_xrp, R.string.unit_currency_xrp_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_yer, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_yer, R.string.unit_currency_yer_short),
|
NormalUnit(UnitID.currency_yer, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_yer, R.string.unit_currency_yer_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_zar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zar, R.string.unit_currency_zar_short),
|
NormalUnit(UnitID.currency_zar, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zar, R.string.unit_currency_zar_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_zmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmk, R.string.unit_currency_zmk_short),
|
NormalUnit(UnitID.currency_zmk, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmk, R.string.unit_currency_zmk_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_zmw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmw, R.string.unit_currency_zmw_short),
|
NormalUnit(UnitID.currency_zmw, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zmw, R.string.unit_currency_zmw_short, backward = true),
|
||||||
ReverseUnit(UnitID.currency_zwl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zwl, R.string.unit_currency_zwl_short),
|
NormalUnit(UnitID.currency_zwl, BigDecimal.ZERO, UnitGroup.CURRENCY, R.string.unit_currency_zwl, R.string.unit_currency_zwl_short, backward = true),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val dataCollection: List<AbstractUnit> by lazy {
|
internal val dataCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.bit, BigDecimal("1"), UnitGroup.DATA, R.string.unit_bit, R.string.unit_bit_short),
|
NormalUnit(UnitID.bit, BigDecimal("1"), UnitGroup.DATA, R.string.unit_bit, R.string.unit_bit_short),
|
||||||
NormalUnit(UnitID.kibibit, BigDecimal("1024"), UnitGroup.DATA, R.string.unit_kibibit, R.string.unit_kibibit_short),
|
NormalUnit(UnitID.kibibit, BigDecimal("1024"), UnitGroup.DATA, R.string.unit_kibibit, R.string.unit_kibibit_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val dataTransferCollection: List<AbstractUnit> by lazy {
|
internal val dataTransferCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.bit_per_second, BigDecimal("1"), UnitGroup.DATA_TRANSFER, R.string.unit_bit_per_second, R.string.unit_bit_per_second_short),
|
NormalUnit(UnitID.bit_per_second, BigDecimal("1"), UnitGroup.DATA_TRANSFER, R.string.unit_bit_per_second, R.string.unit_bit_per_second_short),
|
||||||
NormalUnit(UnitID.kibibit_per_second, BigDecimal("1024"), UnitGroup.DATA_TRANSFER, R.string.unit_kibibit_per_second, R.string.unit_kibibit_per_second_short),
|
NormalUnit(UnitID.kibibit_per_second, BigDecimal("1024"), UnitGroup.DATA_TRANSFER, R.string.unit_kibibit_per_second, R.string.unit_kibibit_per_second_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val electrostaticCapacitance: List<AbstractUnit> by lazy {
|
internal val electrostaticCapacitance: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.attofarad, BigDecimal("1"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_attofarad, R.string.unit_attofarad_short),
|
NormalUnit(UnitID.attofarad, BigDecimal("1"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_attofarad, R.string.unit_attofarad_short),
|
||||||
NormalUnit(UnitID.picofarad, BigDecimal("1000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_picofarad, R.string.unit_picofarad_short),
|
NormalUnit(UnitID.picofarad, BigDecimal("1000000"), UnitGroup.ELECTROSTATIC_CAPACITANCE, R.string.unit_picofarad, R.string.unit_picofarad_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val energyCollection: List<AbstractUnit> by lazy {
|
internal val energyCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.electron_volt, BigDecimal("0.160217733"), UnitGroup.ENERGY, R.string.unit_electron_volt, R.string.unit_electron_volt_short),
|
NormalUnit(UnitID.electron_volt, BigDecimal("0.160217733"), UnitGroup.ENERGY, R.string.unit_electron_volt, R.string.unit_electron_volt_short),
|
||||||
NormalUnit(UnitID.attojoule, BigDecimal("1.00"), UnitGroup.ENERGY, R.string.unit_attojoule, R.string.unit_attojoule_short),
|
NormalUnit(UnitID.attojoule, BigDecimal("1.00"), UnitGroup.ENERGY, R.string.unit_attojoule, R.string.unit_attojoule_short),
|
||||||
|
@ -20,33 +20,33 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.ReverseUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
val flowRateCollection: List<AbstractUnit> by lazy {
|
val flowRateCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
ReverseUnit(UnitID.liter_per_hour, BigDecimal("3600000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_hour, R.string.unit_liter_per_hour_short),
|
NormalUnit(UnitID.liter_per_hour, BigDecimal("3600000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_hour, R.string.unit_liter_per_hour_short, true),
|
||||||
ReverseUnit(UnitID.liter_per_minute, BigDecimal("60000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_minute, R.string.unit_liter_per_minute_short),
|
NormalUnit(UnitID.liter_per_minute, BigDecimal("60000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_minute, R.string.unit_liter_per_minute_short, true),
|
||||||
ReverseUnit(UnitID.liter_per_second, BigDecimal("1000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_second, R.string.unit_liter_per_second_short),
|
NormalUnit(UnitID.liter_per_second, BigDecimal("1000"), UnitGroup.FLOW_RATE, R.string.unit_liter_per_second, R.string.unit_liter_per_second_short, true),
|
||||||
ReverseUnit(UnitID.milliliter_per_hour, BigDecimal("3600000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_hour, R.string.unit_milliliter_per_hour_short),
|
NormalUnit(UnitID.milliliter_per_hour, BigDecimal("3600000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_hour, R.string.unit_milliliter_per_hour_short, true),
|
||||||
ReverseUnit(UnitID.milliliter_per_minute, BigDecimal("60000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_minute, R.string.unit_milliliter_per_minute_short),
|
NormalUnit(UnitID.milliliter_per_minute, BigDecimal("60000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_minute, R.string.unit_milliliter_per_minute_short, true),
|
||||||
ReverseUnit(UnitID.milliliter_per_second, BigDecimal("1000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_second, R.string.unit_milliliter_per_second_short),
|
NormalUnit(UnitID.milliliter_per_second, BigDecimal("1000000"), UnitGroup.FLOW_RATE, R.string.unit_milliliter_per_second, R.string.unit_milliliter_per_second_short, true),
|
||||||
ReverseUnit(UnitID.cubic_meter_per_hour, BigDecimal("3600"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_hour, R.string.unit_cubic_meter_per_hour_short),
|
NormalUnit(UnitID.cubic_meter_per_hour, BigDecimal("3600"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_hour, R.string.unit_cubic_meter_per_hour_short, true),
|
||||||
ReverseUnit(UnitID.cubic_meter_per_minute, BigDecimal("60"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_minute, R.string.unit_cubic_meter_per_minute_short),
|
NormalUnit(UnitID.cubic_meter_per_minute, BigDecimal("60"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_minute, R.string.unit_cubic_meter_per_minute_short, true),
|
||||||
ReverseUnit(UnitID.cubic_meter_per_second, BigDecimal("1"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_second, R.string.unit_cubic_meter_per_second_short),
|
NormalUnit(UnitID.cubic_meter_per_second, BigDecimal("1"), UnitGroup.FLOW_RATE, R.string.unit_cubic_meter_per_second, R.string.unit_cubic_meter_per_second_short, true),
|
||||||
ReverseUnit(UnitID.cubic_millimeter_per_hour, BigDecimal("3600000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_hour, R.string.unit_cubic_millimeter_per_hour_short),
|
NormalUnit(UnitID.cubic_millimeter_per_hour, BigDecimal("3600000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_hour, R.string.unit_cubic_millimeter_per_hour_short, true),
|
||||||
ReverseUnit(UnitID.cubic_millimeter_per_minute, BigDecimal("60000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_minute, R.string.unit_cubic_millimeter_per_minute_short),
|
NormalUnit(UnitID.cubic_millimeter_per_minute, BigDecimal("60000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_minute, R.string.unit_cubic_millimeter_per_minute_short, true),
|
||||||
ReverseUnit(UnitID.cubic_millimeter_per_second, BigDecimal("1000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_second, R.string.unit_cubic_millimeter_per_second_short),
|
NormalUnit(UnitID.cubic_millimeter_per_second, BigDecimal("1000000000"), UnitGroup.FLOW_RATE, R.string.unit_cubic_millimeter_per_second, R.string.unit_cubic_millimeter_per_second_short, true),
|
||||||
ReverseUnit(UnitID.cubic_foot_per_hour, BigDecimal("127132.80019736"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_hour, R.string.unit_cubic_foot_per_hour_short),
|
NormalUnit(UnitID.cubic_foot_per_hour, BigDecimal("127132.80019736"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_hour, R.string.unit_cubic_foot_per_hour_short, true),
|
||||||
ReverseUnit(UnitID.cubic_foot_per_minute, BigDecimal("2118.8800032893"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_minute, R.string.unit_cubic_foot_per_minute_short),
|
NormalUnit(UnitID.cubic_foot_per_minute, BigDecimal("2118.8800032893"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_minute, R.string.unit_cubic_foot_per_minute_short, true),
|
||||||
ReverseUnit(UnitID.cubic_foot_per_second, BigDecimal("35.314666721489"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_second, R.string.unit_cubic_foot_per_second_short),
|
NormalUnit(UnitID.cubic_foot_per_second, BigDecimal("35.314666721489"), UnitGroup.FLOW_RATE, R.string.unit_cubic_foot_per_second, R.string.unit_cubic_foot_per_second_short, true),
|
||||||
ReverseUnit(UnitID.gallons_per_hour_us, BigDecimal("951019.38848933"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_us, R.string.unit_gallon_per_hour_us_short),
|
NormalUnit(UnitID.gallons_per_hour_us, BigDecimal("951019.38848933"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_us, R.string.unit_gallon_per_hour_us_short, true),
|
||||||
ReverseUnit(UnitID.gallons_per_minute_us, BigDecimal("15850.323141489"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_us, R.string.unit_gallon_per_minute_us_short),
|
NormalUnit(UnitID.gallons_per_minute_us, BigDecimal("15850.323141489"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_us, R.string.unit_gallon_per_minute_us_short, true),
|
||||||
ReverseUnit(UnitID.gallons_per_second_us, BigDecimal("264.17205235815"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_us, R.string.unit_gallon_per_second_us_short),
|
NormalUnit(UnitID.gallons_per_second_us, BigDecimal("264.17205235815"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_us, R.string.unit_gallon_per_second_us_short, true),
|
||||||
ReverseUnit(UnitID.gallons_per_hour_imperial, BigDecimal("791889.29387672"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_imperial, R.string.unit_gallon_per_hour_imperial_short),
|
NormalUnit(UnitID.gallons_per_hour_imperial, BigDecimal("791889.29387672"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_hour_imperial, R.string.unit_gallon_per_hour_imperial_short, true),
|
||||||
ReverseUnit(UnitID.gallons_per_minute_imperial, BigDecimal("13198.154897945"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_imperial, R.string.unit_gallon_per_minute_imperial_short),
|
NormalUnit(UnitID.gallons_per_minute_imperial, BigDecimal("13198.154897945"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_minute_imperial, R.string.unit_gallon_per_minute_imperial_short, true),
|
||||||
ReverseUnit(UnitID.gallons_per_second_imperial, BigDecimal("219.96924829909"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_imperial, R.string.unit_gallon_per_second_imperial_short),
|
NormalUnit(UnitID.gallons_per_second_imperial, BigDecimal("219.96924829909"), UnitGroup.FLOW_RATE, R.string.unit_gallon_per_second_imperial, R.string.unit_gallon_per_second_imperial_short, true),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val fluxCollection: List<AbstractUnit> by lazy {
|
internal val fluxCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.maxwell, BigDecimal("1"), UnitGroup.FLUX, R.string.unit_maxwell, R.string.unit_maxwell_short),
|
NormalUnit(UnitID.maxwell, BigDecimal("1"), UnitGroup.FLUX, R.string.unit_maxwell, R.string.unit_maxwell_short),
|
||||||
NormalUnit(UnitID.microweber, BigDecimal("100"), UnitGroup.FLUX, R.string.unit_microweber, R.string.unit_microweber_short),
|
NormalUnit(UnitID.microweber, BigDecimal("100"), UnitGroup.FLUX, R.string.unit_microweber, R.string.unit_microweber_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
val forceCollection: List<AbstractUnit> by lazy {
|
val forceCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.attonewton, BigDecimal("1"), UnitGroup.FORCE, R.string.unit_attonewton, R.string.unit_attonewton_short),
|
NormalUnit(UnitID.attonewton, BigDecimal("1"), UnitGroup.FORCE, R.string.unit_attonewton, R.string.unit_attonewton_short),
|
||||||
NormalUnit(UnitID.dyne, BigDecimal("10000000000000"), UnitGroup.FORCE, R.string.unit_dyne, R.string.unit_dyne_short),
|
NormalUnit(UnitID.dyne, BigDecimal("10000000000000"), UnitGroup.FORCE, R.string.unit_dyne, R.string.unit_dyne_short),
|
||||||
|
@ -20,23 +20,22 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.BackwardUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
val fuelConsumptionCollection: List<AbstractUnit> by lazy {
|
val fuelConsumptionCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit( UnitID.kilometer_per_liter, BigDecimal("1"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_km_per_l, R.string.unit_km_per_l_short),
|
NormalUnit( UnitID.kilometer_per_liter, BigDecimal("1"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_km_per_l, R.string.unit_km_per_l_short),
|
||||||
BackwardUnit(UnitID.liter_per_kilometer, BigDecimal("1"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_km, R.string.unit_l_per_km_short),
|
NormalUnit(UnitID.liter_per_kilometer, BigDecimal("1"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_km, R.string.unit_l_per_km_short, true),
|
||||||
BackwardUnit(UnitID.liter_per_100_kilometer, BigDecimal("100"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_100_km, R.string.unit_l_per_100_km_short),
|
NormalUnit(UnitID.liter_per_100_kilometer, BigDecimal("100"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_l_per_100_km, R.string.unit_l_per_100_km_short, true),
|
||||||
NormalUnit( UnitID.mile_per_gallon_uk, BigDecimal("0.35400619"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_uk, R.string.unit_mi_per_gallon_uk_short),
|
NormalUnit( UnitID.mile_per_gallon_uk, BigDecimal("0.35400619"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_uk, R.string.unit_mi_per_gallon_uk_short),
|
||||||
NormalUnit( UnitID.mile_per_gallon_us, BigDecimal("0.4251437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_us, R.string.unit_mi_per_gallon_us_short),
|
NormalUnit( UnitID.mile_per_gallon_us, BigDecimal("0.4251437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_per_gallon_us, R.string.unit_mi_per_gallon_us_short),
|
||||||
NormalUnit( UnitID.mile_us_per_liter, BigDecimal("1.609344"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_us_per_l, R.string.unit_mi_us_per_l_short),
|
NormalUnit( UnitID.mile_us_per_liter, BigDecimal("1.609344"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_mi_us_per_l, R.string.unit_mi_us_per_l_short),
|
||||||
BackwardUnit(UnitID.gallon_us_per_mile, BigDecimal("0.4251437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_mile, R.string.unit_gallon_us_per_mile_short),
|
NormalUnit(UnitID.gallon_us_per_mile, BigDecimal("0.4251437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_mile, R.string.unit_gallon_us_per_mile_short, true),
|
||||||
BackwardUnit(UnitID.gallon_uk_per_mile, BigDecimal("0.35400619"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_mile, R.string.unit_gallon_uk_per_mile_short),
|
NormalUnit(UnitID.gallon_uk_per_mile, BigDecimal("0.35400619"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_mile, R.string.unit_gallon_uk_per_mile_short, true),
|
||||||
BackwardUnit(UnitID.gallon_us_per_100_mile, BigDecimal("42.51437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_100_mile, R.string.unit_gallon_us_per_100_mile_short),
|
NormalUnit(UnitID.gallon_us_per_100_mile, BigDecimal("42.51437075"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_us_per_100_mile, R.string.unit_gallon_us_per_100_mile_short, true),
|
||||||
BackwardUnit(UnitID.gallon_uk_per_100_mile, BigDecimal("35.400618996"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_100_mile, R.string.unit_gallon_uk_per_100_mile_short),
|
NormalUnit(UnitID.gallon_uk_per_100_mile, BigDecimal("35.400618996"), UnitGroup.FUEL_CONSUMPTION, R.string.unit_gallon_uk_per_100_mile, R.string.unit_gallon_uk_per_100_mile_short, true),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val lengthCollection: List<AbstractUnit> by lazy {
|
internal val lengthCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.attometer, BigDecimal("1"), UnitGroup.LENGTH, R.string.unit_attometer, R.string.unit_attometer_short),
|
NormalUnit(UnitID.attometer, BigDecimal("1"), UnitGroup.LENGTH, R.string.unit_attometer, R.string.unit_attometer_short),
|
||||||
NormalUnit(UnitID.nanometer, BigDecimal("1000000000"), UnitGroup.LENGTH, R.string.unit_nanometer, R.string.unit_nanometer_short),
|
NormalUnit(UnitID.nanometer, BigDecimal("1000000000"), UnitGroup.LENGTH, R.string.unit_nanometer, R.string.unit_nanometer_short),
|
||||||
@ -55,3 +55,4 @@ internal val lengthCollection: List<AbstractUnit> by lazy {
|
|||||||
NormalUnit(UnitID.sun_equatorial_radius, BigDecimal("695508000000000000000000000"), UnitGroup.LENGTH, R.string.unit_sun_equatorial_radius, R.string.unit_sun_equatorial_radius_short),
|
NormalUnit(UnitID.sun_equatorial_radius, BigDecimal("695508000000000000000000000"), UnitGroup.LENGTH, R.string.unit_sun_equatorial_radius, R.string.unit_sun_equatorial_radius_short),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
val luminanceCollection: List<AbstractUnit> by lazy {
|
val luminanceCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.candela_per_square_meter, BigDecimal("31415926.5359"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_meter, R.string.unit_candela_per_square_meter_short),
|
NormalUnit(UnitID.candela_per_square_meter, BigDecimal("31415926.5359"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_meter, R.string.unit_candela_per_square_meter_short),
|
||||||
NormalUnit(UnitID.candela_per_square_centimeter, BigDecimal("314159265359"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_centimeter, R.string.unit_candela_per_square_centimeter_short),
|
NormalUnit(UnitID.candela_per_square_centimeter, BigDecimal("314159265359"), UnitGroup.LUMINANCE, R.string.unit_candela_per_square_centimeter, R.string.unit_candela_per_square_centimeter_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val massCollection: List<AbstractUnit> by lazy {
|
internal val massCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.electron_mass_rest, BigDecimal("0.00000000000000000000000000091093897"), UnitGroup.MASS, R.string.unit_electron_mass_rest, R.string.unit_electron_mass_rest_short),
|
NormalUnit(UnitID.electron_mass_rest, BigDecimal("0.00000000000000000000000000091093897"), UnitGroup.MASS, R.string.unit_electron_mass_rest, R.string.unit_electron_mass_rest_short),
|
||||||
NormalUnit(UnitID.atomic_mass_unit, BigDecimal("0.0000000000000000000000016605402"), UnitGroup.MASS, R.string.unit_atomic_mass_unit, R.string.unit_atomic_mass_unit_short),
|
NormalUnit(UnitID.atomic_mass_unit, BigDecimal("0.0000000000000000000000016605402"), UnitGroup.MASS, R.string.unit_atomic_mass_unit, R.string.unit_atomic_mass_unit_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NumberBaseUnit
|
import com.sadellie.unitto.data.model.converter.unit.NumberBaseUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val numberBaseCollection: List<AbstractUnit> by lazy {
|
internal val numberBaseCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NumberBaseUnit(UnitID.binary, BigDecimal("2.0"), UnitGroup.NUMBER_BASE, R.string.unit_binary, R.string.unit_binary_short),
|
NumberBaseUnit(UnitID.binary, BigDecimal("2.0"), UnitGroup.NUMBER_BASE, R.string.unit_binary, R.string.unit_binary_short),
|
||||||
NumberBaseUnit(UnitID.ternary, BigDecimal("3.0"), UnitGroup.NUMBER_BASE, R.string.unit_ternary, R.string.unit_ternary_short),
|
NumberBaseUnit(UnitID.ternary, BigDecimal("3.0"), UnitGroup.NUMBER_BASE, R.string.unit_ternary, R.string.unit_ternary_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val powerCollection: List<AbstractUnit> by lazy {
|
internal val powerCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.attowatt, BigDecimal("1"), UnitGroup.POWER, R.string.unit_attowatt, R.string.unit_attowatt_short),
|
NormalUnit(UnitID.attowatt, BigDecimal("1"), UnitGroup.POWER, R.string.unit_attowatt, R.string.unit_attowatt_short),
|
||||||
NormalUnit(UnitID.watt, BigDecimal("1000000000000000000"), UnitGroup.POWER, R.string.unit_watt, R.string.unit_watt_short),
|
NormalUnit(UnitID.watt, BigDecimal("1000000000000000000"), UnitGroup.POWER, R.string.unit_watt, R.string.unit_watt_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
val prefixCollection: List<AbstractUnit> by lazy {
|
val prefixCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.prefix_quetta, BigDecimal("1000000000000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_quetta, R.string.unit_prefix_quetta_short),
|
NormalUnit(UnitID.prefix_quetta, BigDecimal("1000000000000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_quetta, R.string.unit_prefix_quetta_short),
|
||||||
NormalUnit(UnitID.prefix_ronna, BigDecimal("1000000000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_ronna, R.string.unit_prefix_ronna_short),
|
NormalUnit(UnitID.prefix_ronna, BigDecimal("1000000000000000000000000000"), UnitGroup.PREFIX, R.string.unit_prefix_ronna, R.string.unit_prefix_ronna_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val pressureCollection: List<AbstractUnit> by lazy {
|
internal val pressureCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.attopascal, BigDecimal("1"), UnitGroup.PRESSURE, R.string.unit_attopascal, R.string.unit_attopascal_short),
|
NormalUnit(UnitID.attopascal, BigDecimal("1"), UnitGroup.PRESSURE, R.string.unit_attopascal, R.string.unit_attopascal_short),
|
||||||
NormalUnit(UnitID.femtopascal, BigDecimal("1000"), UnitGroup.PRESSURE, R.string.unit_femtopascal, R.string.unit_femtopascal_short),
|
NormalUnit(UnitID.femtopascal, BigDecimal("1000"), UnitGroup.PRESSURE, R.string.unit_femtopascal, R.string.unit_femtopascal_short),
|
||||||
|
@ -20,13 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.BackwardUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val speedCollection: List<AbstractUnit> by lazy {
|
internal val speedCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit( UnitID.millimeter_per_hour, BigDecimal("1"), UnitGroup.SPEED, R.string.unit_millimeter_per_hour, R.string.unit_millimeter_per_hour_short),
|
NormalUnit( UnitID.millimeter_per_hour, BigDecimal("1"), UnitGroup.SPEED, R.string.unit_millimeter_per_hour, R.string.unit_millimeter_per_hour_short),
|
||||||
NormalUnit( UnitID.millimeter_per_minute, BigDecimal("60"), UnitGroup.SPEED, R.string.unit_millimeter_per_minute, R.string.unit_millimeter_per_minute_short),
|
NormalUnit( UnitID.millimeter_per_minute, BigDecimal("60"), UnitGroup.SPEED, R.string.unit_millimeter_per_minute, R.string.unit_millimeter_per_minute_short),
|
||||||
@ -49,10 +48,10 @@ internal val speedCollection: List<AbstractUnit> by lazy {
|
|||||||
NormalUnit( UnitID.mile_per_hour, BigDecimal("1609344"), UnitGroup.SPEED, R.string.unit_mile_per_hour, R.string.unit_mile_per_hour_short),
|
NormalUnit( UnitID.mile_per_hour, BigDecimal("1609344"), UnitGroup.SPEED, R.string.unit_mile_per_hour, R.string.unit_mile_per_hour_short),
|
||||||
NormalUnit( UnitID.mile_per_minute, BigDecimal("96560640"), UnitGroup.SPEED, R.string.unit_mile_per_minute, R.string.unit_mile_per_minute_short),
|
NormalUnit( UnitID.mile_per_minute, BigDecimal("96560640"), UnitGroup.SPEED, R.string.unit_mile_per_minute, R.string.unit_mile_per_minute_short),
|
||||||
NormalUnit( UnitID.mile_per_second, BigDecimal("5793638400"), UnitGroup.SPEED, R.string.unit_mile_per_second, R.string.unit_mile_per_second_short),
|
NormalUnit( UnitID.mile_per_second, BigDecimal("5793638400"), UnitGroup.SPEED, R.string.unit_mile_per_second, R.string.unit_mile_per_second_short),
|
||||||
BackwardUnit(UnitID.minute_per_kilometer, BigDecimal("60000000"), UnitGroup.SPEED, R.string.unit_minute_per_kilometer, R.string.unit_minute_per_kilometer_short),
|
NormalUnit(UnitID.minute_per_kilometer, BigDecimal("60000000"), UnitGroup.SPEED, R.string.unit_minute_per_kilometer, R.string.unit_minute_per_kilometer_short, true),
|
||||||
BackwardUnit(UnitID.minute_per_mile, BigDecimal("96560640"), UnitGroup.SPEED, R.string.unit_minute_per_mile, R.string.unit_minute_per_mile_short),
|
NormalUnit(UnitID.minute_per_mile, BigDecimal("96560640"), UnitGroup.SPEED, R.string.unit_minute_per_mile, R.string.unit_minute_per_mile_short, true),
|
||||||
BackwardUnit(UnitID.hour_per_kilometer, BigDecimal("1000000"), UnitGroup.SPEED, R.string.unit_hour_per_kilometer, R.string.unit_hour_per_kilometer_short),
|
NormalUnit(UnitID.hour_per_kilometer, BigDecimal("1000000"), UnitGroup.SPEED, R.string.unit_hour_per_kilometer, R.string.unit_hour_per_kilometer_short, true),
|
||||||
BackwardUnit(UnitID.hour_per_mile, BigDecimal("1609344"), UnitGroup.SPEED, R.string.unit_hour_per_mile, R.string.unit_hour_per_mile_short),
|
NormalUnit(UnitID.hour_per_mile, BigDecimal("1609344"), UnitGroup.SPEED, R.string.unit_hour_per_mile, R.string.unit_hour_per_mile_short, true),
|
||||||
NormalUnit( UnitID.knot, BigDecimal("1852000"), UnitGroup.SPEED, R.string.unit_knot, R.string.unit_knot_short),
|
NormalUnit( UnitID.knot, BigDecimal("1852000"), UnitGroup.SPEED, R.string.unit_knot, R.string.unit_knot_short),
|
||||||
NormalUnit( UnitID.velocity_of_light_in_vacuum, BigDecimal("1079252848799998"), UnitGroup.SPEED, R.string.unit_velocity_of_light_in_vacuum, R.string.unit_velocity_of_light_in_vacuum_short),
|
NormalUnit( UnitID.velocity_of_light_in_vacuum, BigDecimal("1079252848799998"), UnitGroup.SPEED, R.string.unit_velocity_of_light_in_vacuum, R.string.unit_velocity_of_light_in_vacuum_short),
|
||||||
NormalUnit( UnitID.cosmic_velocity_first, BigDecimal("28440000000"), UnitGroup.SPEED, R.string.unit_cosmic_velocity_first, R.string.unit_cosmic_velocity_first_short),
|
NormalUnit( UnitID.cosmic_velocity_first, BigDecimal("28440000000"), UnitGroup.SPEED, R.string.unit_cosmic_velocity_first, R.string.unit_cosmic_velocity_first_short),
|
||||||
|
@ -21,22 +21,21 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
import com.sadellie.unitto.core.base.MAX_PRECISION
|
import com.sadellie.unitto.core.base.MAX_PRECISION
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.TemperatureUnit
|
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
|
|
||||||
internal val temperatureCollection: List<AbstractUnit> by lazy {
|
internal val temperatureCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
val celsius = object : BasicUnit.Default {
|
||||||
TemperatureUnit(
|
override val id: String = UnitID.celsius
|
||||||
id = UnitID.celsius,
|
override val group: UnitGroup = UnitGroup.TEMPERATURE
|
||||||
basicUnit = BigDecimal.ONE,
|
override val displayName: Int = R.string.unit_celsius
|
||||||
group = UnitGroup.TEMPERATURE,
|
override val shortName: Int = R.string.unit_celsius_short
|
||||||
displayName = R.string.unit_celsius,
|
override val factor: BigDecimal = BigDecimal.ONE
|
||||||
shortName = R.string.unit_celsius_short,
|
override val backward: Boolean = false
|
||||||
customConvert = { unitTo, value ->
|
|
||||||
when (unitTo.id) {
|
override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal = when (unitTo.id) {
|
||||||
UnitID.fahrenheit -> {
|
UnitID.fahrenheit -> {
|
||||||
value
|
value
|
||||||
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
||||||
@ -53,15 +52,16 @@ internal val temperatureCollection: List<AbstractUnit> by lazy {
|
|||||||
else -> value
|
else -> value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
|
||||||
TemperatureUnit(
|
val fahrenheit = object : BasicUnit.Default {
|
||||||
id = UnitID.fahrenheit,
|
override val id: String = UnitID.fahrenheit
|
||||||
basicUnit = BigDecimal.ONE,
|
override val group: UnitGroup = UnitGroup.TEMPERATURE
|
||||||
group = UnitGroup.TEMPERATURE,
|
override val displayName: Int = R.string.unit_fahrenheit
|
||||||
displayName = R.string.unit_fahrenheit,
|
override val shortName: Int = R.string.unit_fahrenheit_short
|
||||||
shortName = R.string.unit_fahrenheit_short,
|
override val factor: BigDecimal = BigDecimal.ONE
|
||||||
customConvert = { unitTo, value ->
|
override val backward: Boolean = false
|
||||||
when (unitTo.id) {
|
|
||||||
|
override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal = when (unitTo.id) {
|
||||||
UnitID.celsius -> {
|
UnitID.celsius -> {
|
||||||
value
|
value
|
||||||
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
||||||
@ -80,15 +80,16 @@ internal val temperatureCollection: List<AbstractUnit> by lazy {
|
|||||||
else -> value
|
else -> value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
|
||||||
TemperatureUnit(
|
val kelvin = object : BasicUnit.Default {
|
||||||
id = UnitID.kelvin,
|
override val id: String = UnitID.kelvin
|
||||||
basicUnit = BigDecimal.ONE,
|
override val group: UnitGroup = UnitGroup.TEMPERATURE
|
||||||
group = UnitGroup.TEMPERATURE,
|
override val displayName: Int = R.string.unit_kelvin
|
||||||
displayName = R.string.unit_kelvin,
|
override val shortName: Int = R.string.unit_kelvin_short
|
||||||
shortName = R.string.unit_kelvin_short,
|
override val factor: BigDecimal = BigDecimal.ONE
|
||||||
customConvert = { unitTo, value ->
|
override val backward: Boolean = false
|
||||||
when (unitTo.id) {
|
|
||||||
|
override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal = when (unitTo.id) {
|
||||||
UnitID.celsius -> {
|
UnitID.celsius -> {
|
||||||
value
|
value
|
||||||
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
||||||
@ -104,6 +105,6 @@ internal val temperatureCollection: List<AbstractUnit> by lazy {
|
|||||||
else -> value
|
else -> value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
),
|
|
||||||
)
|
listOf(celsius, fahrenheit, kelvin)
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val timeCollection: List<AbstractUnit> by lazy {
|
internal val timeCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.attosecond, BigDecimal("1"), UnitGroup.TIME, R.string.unit_attosecond, R.string.unit_attosecond_short),
|
NormalUnit(UnitID.attosecond, BigDecimal("1"), UnitGroup.TIME, R.string.unit_attosecond, R.string.unit_attosecond_short),
|
||||||
NormalUnit(UnitID.nanosecond, BigDecimal("1000000000"), UnitGroup.TIME, R.string.unit_nanosecond, R.string.unit_nanosecond_short),
|
NormalUnit(UnitID.nanosecond, BigDecimal("1000000000"), UnitGroup.TIME, R.string.unit_nanosecond, R.string.unit_nanosecond_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
val torqueCollection: List<AbstractUnit> by lazy {
|
val torqueCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.dyne_millimeter, BigDecimal("1"), UnitGroup.TORQUE, R.string.unit_dyne_millimeter, R.string.unit_dyne_millimeter_short),
|
NormalUnit(UnitID.dyne_millimeter, BigDecimal("1"), UnitGroup.TORQUE, R.string.unit_dyne_millimeter, R.string.unit_dyne_millimeter_short),
|
||||||
NormalUnit(UnitID.dyne_centimeter, BigDecimal("10"), UnitGroup.TORQUE, R.string.unit_dyne_centimeter, R.string.unit_dyne_centimeter_short),
|
NormalUnit(UnitID.dyne_centimeter, BigDecimal("10"), UnitGroup.TORQUE, R.string.unit_dyne_centimeter, R.string.unit_dyne_centimeter_short),
|
||||||
|
@ -20,12 +20,12 @@ package com.sadellie.unitto.data.converter.collections
|
|||||||
|
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
internal val volumeCollection: List<AbstractUnit> by lazy {
|
internal val volumeCollection: List<BasicUnit> by lazy {
|
||||||
listOf(
|
listOf(
|
||||||
NormalUnit(UnitID.attoliter, BigDecimal("1"), UnitGroup.VOLUME, R.string.unit_attoliter, R.string.unit_attoliter_short),
|
NormalUnit(UnitID.attoliter, BigDecimal("1"), UnitGroup.VOLUME, R.string.unit_attoliter, R.string.unit_attoliter_short),
|
||||||
NormalUnit(UnitID.milliliter, BigDecimal("1000000000000000"), UnitGroup.VOLUME, R.string.unit_milliliter, R.string.unit_milliliter_short),
|
NormalUnit(UnitID.milliliter, BigDecimal("1000000000000000"), UnitGroup.VOLUME, R.string.unit_milliliter, R.string.unit_milliliter_short),
|
||||||
|
@ -44,10 +44,9 @@ import com.sadellie.unitto.data.converter.collections.temperatureCollection
|
|||||||
import com.sadellie.unitto.data.converter.collections.timeCollection
|
import com.sadellie.unitto.data.converter.collections.timeCollection
|
||||||
import com.sadellie.unitto.data.converter.collections.torqueCollection
|
import com.sadellie.unitto.data.converter.collections.torqueCollection
|
||||||
import com.sadellie.unitto.data.converter.collections.volumeCollection
|
import com.sadellie.unitto.data.converter.collections.volumeCollection
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.DefaultUnit
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NumberBaseUnit
|
import com.sadellie.unitto.data.model.converter.unit.NumberBaseUnit
|
||||||
import com.sadellie.unitto.data.model.unit.ReverseUnit
|
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
@ -595,13 +594,11 @@ class AllUnitsTest {
|
|||||||
|
|
||||||
val actual = when (unitFrom.group) {
|
val actual = when (unitFrom.group) {
|
||||||
UnitGroup.NUMBER_BASE -> (unitFrom as NumberBaseUnit).convert((unitTo as NumberBaseUnit), value)
|
UnitGroup.NUMBER_BASE -> (unitFrom as NumberBaseUnit).convert((unitTo as NumberBaseUnit), value)
|
||||||
UnitGroup.FLOW_RATE -> (unitFrom as ReverseUnit)
|
else -> (unitFrom as BasicUnit.Default)
|
||||||
.convert((unitTo as DefaultUnit), BigDecimal(value))
|
.convert((unitTo as BasicUnit.Default), BigDecimal(value))
|
||||||
.format(5, OutputFormat.PLAIN)
|
|
||||||
else -> (unitFrom as DefaultUnit)
|
|
||||||
.convert((unitTo as DefaultUnit), BigDecimal(value))
|
|
||||||
.format(5, OutputFormat.PLAIN)
|
.format(5, OutputFormat.PLAIN)
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals("Failed at $this to $checkingId", expected, actual)
|
assertEquals("Failed at $this to $checkingId", expected, actual)
|
||||||
println("PASSED: $this -> $expected == $actual")
|
println("PASSED: $this -> $expected == $actual")
|
||||||
val content: Set<String> = history.getOrDefault(unitFrom.group, setOf())
|
val content: Set<String> = history.getOrDefault(unitFrom.group, setOf())
|
||||||
|
@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* Unitto is a calculator for Android
|
||||||
|
* Copyright (c) 2023-2024 Elshan Agaev
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sadellie.unitto.data.converter
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.sadellie.unitto.data.database.CurrencyRatesDao
|
||||||
|
import com.sadellie.unitto.data.database.CurrencyRatesEntity
|
||||||
|
import com.sadellie.unitto.data.database.UnitsDao
|
||||||
|
import com.sadellie.unitto.data.database.UnitsEntity
|
||||||
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.emptyFlow
|
||||||
|
import org.junit.Assert.assertEquals
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.robolectric.RobolectricTestRunner
|
||||||
|
import org.robolectric.RuntimeEnvironment
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
@RunWith(RobolectricTestRunner::class)
|
||||||
|
class ConverterUIStateKtTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun convertTime() {
|
||||||
|
var basicValue = BigDecimal("1")
|
||||||
|
val mContext: Context = RuntimeEnvironment.getApplication().applicationContext
|
||||||
|
val repo = UnitsRepositoryImpl(
|
||||||
|
unitsDao = object : UnitsDao {
|
||||||
|
override fun getAllFlow(): Flow<List<UnitsEntity>> = emptyFlow()
|
||||||
|
override suspend fun insertUnit(unit: UnitsEntity) {}
|
||||||
|
override suspend fun getById(unitId: String): UnitsEntity? = null
|
||||||
|
override suspend fun clear() {}
|
||||||
|
},
|
||||||
|
currencyRatesDao = object : CurrencyRatesDao {
|
||||||
|
override suspend fun insertRates(currencyRates: List<CurrencyRatesEntity>) {}
|
||||||
|
override suspend fun getLatestRateTimeStamp(baseId: String): Long? = null
|
||||||
|
override suspend fun getLatestRates(baseId: String): List<CurrencyRatesEntity> = emptyList()
|
||||||
|
override suspend fun getLatestRate(baseId: String, pairId: String): CurrencyRatesEntity? = null
|
||||||
|
override fun size(): Flow<Int> = emptyFlow()
|
||||||
|
override suspend fun clear() {}
|
||||||
|
},
|
||||||
|
mContext = mContext,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun String.formatTime(): ConverterResult.Time {
|
||||||
|
val unitFrom = NormalUnit(
|
||||||
|
id = "",
|
||||||
|
factor = basicValue,
|
||||||
|
group = UnitGroup.TIME,
|
||||||
|
displayName = 0,
|
||||||
|
shortName = 0,
|
||||||
|
backward = false,
|
||||||
|
)
|
||||||
|
|
||||||
|
return repo.convertTime(unitFrom, BigDecimal(this))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edgy things (minus, decimals and zeros)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
negative = true,
|
||||||
|
attosecond = BigDecimal("28"),
|
||||||
|
),
|
||||||
|
"-28".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
negative = true,
|
||||||
|
attosecond = BigDecimal("0.05"),
|
||||||
|
),
|
||||||
|
"-0.05".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(),
|
||||||
|
"0".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
basicValue = BigDecimal("86400000000000000000000")
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
negative = true,
|
||||||
|
day = BigDecimal("28"),
|
||||||
|
),
|
||||||
|
"-28".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
negative = true,
|
||||||
|
hour = BigDecimal("1"),
|
||||||
|
minute = BigDecimal("12"),
|
||||||
|
),
|
||||||
|
"-0.05".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(),
|
||||||
|
"0".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(),
|
||||||
|
"-0".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// DAYS
|
||||||
|
basicValue = BigDecimal("86400000000000000000000")
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
hour = BigDecimal("12"),
|
||||||
|
),
|
||||||
|
"0.5".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
day = BigDecimal("90"),
|
||||||
|
minute = BigDecimal("7"),
|
||||||
|
second = BigDecimal("12"),
|
||||||
|
),
|
||||||
|
"90.005".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// HOURS
|
||||||
|
basicValue = BigDecimal("3600000000000000000000")
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
minute = BigDecimal("30"),
|
||||||
|
),
|
||||||
|
"0.5".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
day = BigDecimal("3"),
|
||||||
|
hour = BigDecimal("18"),
|
||||||
|
second = BigDecimal("18"),
|
||||||
|
),
|
||||||
|
"90.005".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// MINUTES
|
||||||
|
basicValue = BigDecimal("60000000000000000000")
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
second = BigDecimal("30"),
|
||||||
|
),
|
||||||
|
"0.5".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
hour = BigDecimal("1"),
|
||||||
|
minute = BigDecimal("30"),
|
||||||
|
millisecond = BigDecimal("300"),
|
||||||
|
),
|
||||||
|
"90.005".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// SECONDS
|
||||||
|
basicValue = BigDecimal("1000000000000000000")
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
millisecond = BigDecimal("500"),
|
||||||
|
),
|
||||||
|
"0.5".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
minute = BigDecimal("1"),
|
||||||
|
second = BigDecimal("30"),
|
||||||
|
millisecond = BigDecimal("5"),
|
||||||
|
),
|
||||||
|
"90.005".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// MILLISECONDS
|
||||||
|
basicValue = BigDecimal("1000000000000000")
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
microsecond = BigDecimal("500"),
|
||||||
|
),
|
||||||
|
"0.5".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
millisecond = BigDecimal("90"),
|
||||||
|
microsecond = BigDecimal("5"),
|
||||||
|
),
|
||||||
|
"90.005".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// MICROSECONDS
|
||||||
|
basicValue = BigDecimal("1000000000000")
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
nanosecond = BigDecimal("500"),
|
||||||
|
),
|
||||||
|
"0.5".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
microsecond = BigDecimal("90"),
|
||||||
|
nanosecond = BigDecimal("5"),
|
||||||
|
),
|
||||||
|
"90.005".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// NANOSECONDS
|
||||||
|
basicValue = BigDecimal("1000000000")
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
nanosecond = BigDecimal("90"),
|
||||||
|
attosecond = BigDecimal("5000000"),
|
||||||
|
),
|
||||||
|
"90.005".formatTime(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// ATTOSECONDS
|
||||||
|
basicValue = BigDecimal("1")
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
attosecond = BigDecimal("0.5"),
|
||||||
|
),
|
||||||
|
"0.5".formatTime(),
|
||||||
|
)
|
||||||
|
assertEquals(
|
||||||
|
ConverterResult.Time(
|
||||||
|
attosecond = BigDecimal("90.005"),
|
||||||
|
),
|
||||||
|
"90.005".formatTime(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -30,9 +30,15 @@ interface CurrencyRatesDao {
|
|||||||
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
@Insert(onConflict = OnConflictStrategy.REPLACE)
|
||||||
suspend fun insertRates(currencyRates: List<CurrencyRatesEntity>)
|
suspend fun insertRates(currencyRates: List<CurrencyRatesEntity>)
|
||||||
|
|
||||||
|
@Query("SELECT DISTINCT timestamp FROM currency_rates WHERE base_unit_id = :baseId")
|
||||||
|
suspend fun getLatestRateTimeStamp(baseId: String): Long?
|
||||||
|
|
||||||
@Query("SELECT DISTINCT * FROM currency_rates WHERE timestamp = (SELECT MAX(timestamp) FROM currency_rates) AND base_unit_id = :baseId")
|
@Query("SELECT DISTINCT * FROM currency_rates WHERE timestamp = (SELECT MAX(timestamp) FROM currency_rates) AND base_unit_id = :baseId")
|
||||||
suspend fun getLatestRates(baseId: String): List<CurrencyRatesEntity>
|
suspend fun getLatestRates(baseId: String): List<CurrencyRatesEntity>
|
||||||
|
|
||||||
|
@Query("SELECT DISTINCT * FROM currency_rates WHERE timestamp = (SELECT MAX(timestamp) FROM currency_rates) AND base_unit_id = :baseId AND pair_unit_id = :pairId")
|
||||||
|
suspend fun getLatestRate(baseId: String, pairId: String): CurrencyRatesEntity?
|
||||||
|
|
||||||
@Query("SELECT COUNT(*) from currency_rates")
|
@Query("SELECT COUNT(*) from currency_rates")
|
||||||
fun size(): Flow<Int>
|
fun size(): Flow<Int>
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ import androidx.room.PrimaryKey
|
|||||||
* @param frequency Show the amount of time this unit was used
|
* @param frequency Show the amount of time this unit was used
|
||||||
*/
|
*/
|
||||||
@Entity(tableName = "units")
|
@Entity(tableName = "units")
|
||||||
class UnitsEntity(
|
data class UnitsEntity(
|
||||||
@PrimaryKey val unitId: String,
|
@PrimaryKey val unitId: String,
|
||||||
@ColumnInfo(name = "is_favorite") val isFavorite: Boolean = false,
|
@ColumnInfo(name = "is_favorite") val isFavorite: Boolean = false,
|
||||||
@ColumnInfo(name = "paired_unit_id") val pairedUnitId: String? = null,
|
@ColumnInfo(name = "paired_unit_id") val pairedUnitId: String? = null,
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model
|
package com.sadellie.unitto.data.model.converter
|
||||||
|
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
@ -16,6 +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/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model
|
package com.sadellie.unitto.data.model.converter
|
||||||
|
|
||||||
enum class UnitsListSorting { USAGE, ALPHABETICAL, SCALE_DESC, SCALE_ASC }
|
enum class UnitsListSorting { USAGE, ALPHABETICAL, SCALE_DESC, SCALE_ASC }
|
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* Unitto is a calculator for Android
|
||||||
|
* Copyright (c) 2023-2024 Elshan Agaev
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sadellie.unitto.data.model.converter.unit
|
||||||
|
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
sealed interface BasicUnit {
|
||||||
|
|
||||||
|
val id: String
|
||||||
|
|
||||||
|
val group: UnitGroup
|
||||||
|
|
||||||
|
@get:StringRes
|
||||||
|
val displayName: Int
|
||||||
|
|
||||||
|
@get:StringRes val shortName: Int
|
||||||
|
|
||||||
|
val factor: BigDecimal
|
||||||
|
|
||||||
|
interface NumberBase : BasicUnit {
|
||||||
|
fun convert(unitTo: NumberBase, value: String): String
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Default : BasicUnit {
|
||||||
|
val backward: Boolean
|
||||||
|
|
||||||
|
fun convert(unitTo: Default, value: BigDecimal): BigDecimal
|
||||||
|
}
|
||||||
|
}
|
@ -16,64 +16,56 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model.unit
|
package com.sadellie.unitto.data.model.converter.unit
|
||||||
|
|
||||||
import com.sadellie.unitto.core.base.MAX_PRECISION
|
import com.sadellie.unitto.core.base.MAX_PRECISION
|
||||||
import com.sadellie.unitto.data.common.isEqualTo
|
import com.sadellie.unitto.data.common.isEqualTo
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.RoundingMode
|
import java.math.RoundingMode
|
||||||
|
|
||||||
data class BackwardUnit(
|
data class NormalUnit(
|
||||||
override val id: String,
|
override val id: String,
|
||||||
override val basicUnit: BigDecimal,
|
override val factor: BigDecimal,
|
||||||
override val group: UnitGroup,
|
override val group: UnitGroup,
|
||||||
override val displayName: Int,
|
override val displayName: Int,
|
||||||
override val shortName: Int,
|
override val shortName: Int,
|
||||||
override val isFavorite: Boolean = false,
|
override val backward: Boolean = false,
|
||||||
override val pairId: String? = null,
|
) : BasicUnit.Default {
|
||||||
override val counter: Int = 0,
|
override fun convert(unitTo: BasicUnit.Default, value: BigDecimal): BigDecimal {
|
||||||
) : DefaultUnit {
|
if (value.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO
|
||||||
override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal {
|
return when {
|
||||||
// Avoid division by zero
|
// BACKWARD -> BACKWARD
|
||||||
if (unitTo.basicUnit.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO
|
backward and unitTo.backward ->
|
||||||
|
|
||||||
return when (unitTo) {
|
|
||||||
is NormalUnit ->
|
|
||||||
this
|
|
||||||
.basicUnit
|
|
||||||
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
|
||||||
.div(unitTo.basicUnit)
|
|
||||||
.div(value)
|
|
||||||
|
|
||||||
is BackwardUnit ->
|
|
||||||
unitTo
|
unitTo
|
||||||
.basicUnit
|
.factor
|
||||||
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
||||||
.multiply(value)
|
.multiply(value)
|
||||||
.div(this.basicUnit)
|
.div(this.factor)
|
||||||
|
|
||||||
else -> BigDecimal.ZERO
|
// BACKWARD -> FORWARD
|
||||||
|
backward and !unitTo.backward ->
|
||||||
|
this
|
||||||
|
.factor
|
||||||
|
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
||||||
|
.div(unitTo.factor)
|
||||||
|
.div(value)
|
||||||
|
|
||||||
|
// FORWARD -> BACKWARD
|
||||||
|
!backward and unitTo.backward ->
|
||||||
|
unitTo
|
||||||
|
.factor
|
||||||
|
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
||||||
|
.div(this.factor)
|
||||||
|
.div(value)
|
||||||
|
|
||||||
|
// FORWARD -> FORWARD
|
||||||
|
else ->
|
||||||
|
this
|
||||||
|
.factor
|
||||||
|
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
||||||
|
.multiply(value)
|
||||||
|
.div(unitTo.factor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clone(
|
|
||||||
id: String,
|
|
||||||
basicUnit: BigDecimal,
|
|
||||||
group: UnitGroup,
|
|
||||||
displayName: Int,
|
|
||||||
shortName: Int,
|
|
||||||
isFavorite: Boolean,
|
|
||||||
pairId: String?,
|
|
||||||
counter: Int,
|
|
||||||
): BackwardUnit = copy(
|
|
||||||
id = id,
|
|
||||||
basicUnit = basicUnit,
|
|
||||||
group = group,
|
|
||||||
displayName = displayName,
|
|
||||||
shortName = shortName,
|
|
||||||
isFavorite = isFavorite,
|
|
||||||
pairId = pairId,
|
|
||||||
counter = counter,
|
|
||||||
)
|
|
||||||
}
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* Unitto is a calculator for Android
|
||||||
|
* Copyright (c) 2024 Elshan Agaev
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sadellie.unitto.data.model.converter.unit
|
||||||
|
|
||||||
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
|
import java.math.BigDecimal
|
||||||
|
|
||||||
|
data class NumberBaseUnit(
|
||||||
|
override val id: String,
|
||||||
|
override val factor: BigDecimal,
|
||||||
|
override val group: UnitGroup,
|
||||||
|
override val displayName: Int,
|
||||||
|
override val shortName: Int,
|
||||||
|
) : BasicUnit.NumberBase {
|
||||||
|
override fun convert(unitTo: BasicUnit.NumberBase, value: String): String = value
|
||||||
|
.toBigInteger(factor.intValueExact())
|
||||||
|
.toString(unitTo.factor.intValueExact())
|
||||||
|
}
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unitto is a calculator for Android
|
|
||||||
* Copyright (c) 2023-2024 Elshan Agaev
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model.repository
|
|
||||||
|
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import java.time.LocalDate
|
|
||||||
|
|
||||||
interface UnitsRepository {
|
|
||||||
val units: Flow<List<AbstractUnit>>
|
|
||||||
|
|
||||||
suspend fun getById(id: String): AbstractUnit
|
|
||||||
|
|
||||||
suspend fun getCollection(group: UnitGroup): List<AbstractUnit>
|
|
||||||
|
|
||||||
suspend fun favorite(unit: AbstractUnit)
|
|
||||||
|
|
||||||
suspend fun incrementCounter(unit: AbstractUnit)
|
|
||||||
|
|
||||||
suspend fun setPair(unit: AbstractUnit, pair: AbstractUnit)
|
|
||||||
|
|
||||||
suspend fun updateRates(unit: AbstractUnit): LocalDate?
|
|
||||||
|
|
||||||
suspend fun filterUnits(
|
|
||||||
query: String,
|
|
||||||
unitGroup: UnitGroup?,
|
|
||||||
favoritesOnly: Boolean,
|
|
||||||
hideBrokenUnits: Boolean,
|
|
||||||
sorting: UnitsListSorting,
|
|
||||||
shownUnitGroups: List<UnitGroup> = emptyList(),
|
|
||||||
): Map<UnitGroup, List<AbstractUnit>>
|
|
||||||
}
|
|
@ -18,9 +18,8 @@
|
|||||||
|
|
||||||
package com.sadellie.unitto.data.model.repository
|
package com.sadellie.unitto.data.model.repository
|
||||||
|
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
|
||||||
import com.sadellie.unitto.data.model.userprefs.AboutPreferences
|
import com.sadellie.unitto.data.model.userprefs.AboutPreferences
|
||||||
import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences
|
import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences
|
||||||
import com.sadellie.unitto.data.model.userprefs.AppPreferences
|
import com.sadellie.unitto.data.model.userprefs.AppPreferences
|
||||||
@ -55,7 +54,7 @@ interface UserPreferencesRepository {
|
|||||||
|
|
||||||
suspend fun updateOutputFormat(outputFormat: Int)
|
suspend fun updateOutputFormat(outputFormat: Int)
|
||||||
|
|
||||||
suspend fun updateLatestPairOfUnits(unitFrom: AbstractUnit, unitTo: AbstractUnit)
|
suspend fun updateLatestPairOfUnits(unitFrom: String, unitTo: String)
|
||||||
|
|
||||||
suspend fun updateThemingMode(themingMode: ThemingMode)
|
suspend fun updateThemingMode(themingMode: ThemingMode)
|
||||||
|
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unitto is a calculator for Android
|
|
||||||
* Copyright (c) 2023-2024 Elshan Agaev
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model.unit
|
|
||||||
|
|
||||||
import com.sadellie.unitto.core.base.MAX_PRECISION
|
|
||||||
import com.sadellie.unitto.data.common.isEqualTo
|
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
|
||||||
import java.math.BigDecimal
|
|
||||||
import java.math.RoundingMode
|
|
||||||
|
|
||||||
data class NormalUnit(
|
|
||||||
override val id: String,
|
|
||||||
override val basicUnit: BigDecimal,
|
|
||||||
override val group: UnitGroup,
|
|
||||||
override val displayName: Int,
|
|
||||||
override val shortName: Int,
|
|
||||||
override val isFavorite: Boolean = false,
|
|
||||||
override val pairId: String? = null,
|
|
||||||
override val counter: Int = 0,
|
|
||||||
) : DefaultUnit {
|
|
||||||
override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal {
|
|
||||||
// Avoid division by zero
|
|
||||||
if (unitTo.basicUnit.isEqualTo(BigDecimal.ZERO)) return BigDecimal.ZERO
|
|
||||||
|
|
||||||
return when (unitTo) {
|
|
||||||
is NormalUnit ->
|
|
||||||
this
|
|
||||||
.basicUnit
|
|
||||||
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
|
||||||
.multiply(value)
|
|
||||||
.div(unitTo.basicUnit)
|
|
||||||
|
|
||||||
is BackwardUnit ->
|
|
||||||
unitTo
|
|
||||||
.basicUnit
|
|
||||||
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
|
||||||
.div(this.basicUnit)
|
|
||||||
.div(value)
|
|
||||||
|
|
||||||
else -> BigDecimal.ZERO
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(
|
|
||||||
id: String,
|
|
||||||
basicUnit: BigDecimal,
|
|
||||||
group: UnitGroup,
|
|
||||||
displayName: Int,
|
|
||||||
shortName: Int,
|
|
||||||
isFavorite: Boolean,
|
|
||||||
pairId: String?,
|
|
||||||
counter: Int,
|
|
||||||
): NormalUnit = copy(
|
|
||||||
id = id,
|
|
||||||
basicUnit = basicUnit,
|
|
||||||
group = group,
|
|
||||||
displayName = displayName,
|
|
||||||
shortName = shortName,
|
|
||||||
isFavorite = isFavorite,
|
|
||||||
pairId = pairId,
|
|
||||||
counter = counter,
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unitto is a calculator for Android
|
|
||||||
* Copyright (c) 2023-2024 Elshan Agaev
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model.unit
|
|
||||||
|
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
|
||||||
import java.math.BigDecimal
|
|
||||||
|
|
||||||
data class NumberBaseUnit(
|
|
||||||
override val id: String,
|
|
||||||
override val basicUnit: BigDecimal,
|
|
||||||
override val group: UnitGroup,
|
|
||||||
override val displayName: Int,
|
|
||||||
override val shortName: Int,
|
|
||||||
override val isFavorite: Boolean = false,
|
|
||||||
override val pairId: String? = null,
|
|
||||||
override val counter: Int = 0,
|
|
||||||
) : AbstractUnit {
|
|
||||||
fun convert(toBase: NumberBaseUnit, input: String): String {
|
|
||||||
return input.toBigInteger(basicUnit.intValueExact()).toString(toBase.basicUnit.intValueExact())
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(
|
|
||||||
id: String,
|
|
||||||
basicUnit: BigDecimal,
|
|
||||||
group: UnitGroup,
|
|
||||||
displayName: Int,
|
|
||||||
shortName: Int,
|
|
||||||
isFavorite: Boolean,
|
|
||||||
pairId: String?,
|
|
||||||
counter: Int,
|
|
||||||
): NumberBaseUnit = copy(
|
|
||||||
id = id,
|
|
||||||
basicUnit = basicUnit,
|
|
||||||
group = group,
|
|
||||||
displayName = displayName,
|
|
||||||
shortName = shortName,
|
|
||||||
isFavorite = isFavorite,
|
|
||||||
pairId = pairId,
|
|
||||||
counter = counter,
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unitto is a calculator for Android
|
|
||||||
* Copyright (c) 2023-2024 Elshan Agaev
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model.unit
|
|
||||||
|
|
||||||
import com.sadellie.unitto.core.base.MAX_PRECISION
|
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
|
||||||
import java.math.BigDecimal
|
|
||||||
import java.math.RoundingMode
|
|
||||||
|
|
||||||
data class ReverseUnit(
|
|
||||||
override val id: String,
|
|
||||||
override val basicUnit: BigDecimal,
|
|
||||||
override val group: UnitGroup,
|
|
||||||
override val displayName: Int,
|
|
||||||
override val shortName: Int,
|
|
||||||
override val isFavorite: Boolean = false,
|
|
||||||
override val pairId: String? = null,
|
|
||||||
override val counter: Int = 0,
|
|
||||||
) : DefaultUnit {
|
|
||||||
override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal {
|
|
||||||
return unitTo
|
|
||||||
.basicUnit
|
|
||||||
.setScale(MAX_PRECISION, RoundingMode.HALF_EVEN)
|
|
||||||
.div(this.basicUnit)
|
|
||||||
.multiply(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun clone(
|
|
||||||
id: String,
|
|
||||||
basicUnit: BigDecimal,
|
|
||||||
group: UnitGroup,
|
|
||||||
displayName: Int,
|
|
||||||
shortName: Int,
|
|
||||||
isFavorite: Boolean,
|
|
||||||
pairId: String?,
|
|
||||||
counter: Int,
|
|
||||||
): ReverseUnit = copy(
|
|
||||||
id = id,
|
|
||||||
basicUnit = basicUnit,
|
|
||||||
group = group,
|
|
||||||
displayName = displayName,
|
|
||||||
shortName = shortName,
|
|
||||||
isFavorite = isFavorite,
|
|
||||||
pairId = pairId,
|
|
||||||
counter = counter,
|
|
||||||
)
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unitto is a calculator for Android
|
|
||||||
* Copyright (c) 2023-2024 Elshan Agaev
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sadellie.unitto.data.model.unit
|
|
||||||
|
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
|
||||||
import java.math.BigDecimal
|
|
||||||
|
|
||||||
data class TemperatureUnit(
|
|
||||||
override val id: String,
|
|
||||||
override val basicUnit: BigDecimal,
|
|
||||||
override val group: UnitGroup,
|
|
||||||
override val displayName: Int,
|
|
||||||
override val shortName: Int,
|
|
||||||
override val isFavorite: Boolean = false,
|
|
||||||
override val pairId: String? = null,
|
|
||||||
override val counter: Int = 0,
|
|
||||||
val customConvert: (unitTo: DefaultUnit, value: BigDecimal) -> BigDecimal,
|
|
||||||
) : DefaultUnit {
|
|
||||||
override fun convert(unitTo: DefaultUnit, value: BigDecimal): BigDecimal = customConvert(unitTo, value)
|
|
||||||
|
|
||||||
override fun clone(
|
|
||||||
id: String,
|
|
||||||
basicUnit: BigDecimal,
|
|
||||||
group: UnitGroup,
|
|
||||||
displayName: Int,
|
|
||||||
shortName: Int,
|
|
||||||
isFavorite: Boolean,
|
|
||||||
pairId: String?,
|
|
||||||
counter: Int,
|
|
||||||
): TemperatureUnit = copy(
|
|
||||||
id = id,
|
|
||||||
basicUnit = basicUnit,
|
|
||||||
group = group,
|
|
||||||
displayName = displayName,
|
|
||||||
shortName = shortName,
|
|
||||||
isFavorite = isFavorite,
|
|
||||||
pairId = pairId,
|
|
||||||
counter = counter,
|
|
||||||
)
|
|
||||||
}
|
|
@ -19,8 +19,8 @@
|
|||||||
package com.sadellie.unitto.data.model.userprefs
|
package com.sadellie.unitto.data.model.userprefs
|
||||||
|
|
||||||
import com.sadellie.unitto.core.base.FormatterSymbols
|
import com.sadellie.unitto.core.base.FormatterSymbols
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
|
|
||||||
interface ConverterPreferences {
|
interface ConverterPreferences {
|
||||||
val formatterSymbols: FormatterSymbols
|
val formatterSymbols: FormatterSymbols
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
package com.sadellie.unitto.data.model.userprefs
|
package com.sadellie.unitto.data.model.userprefs
|
||||||
|
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
|
|
||||||
interface UnitGroupsPreferences {
|
interface UnitGroupsPreferences {
|
||||||
val shownUnitGroups: List<UnitGroup>
|
val shownUnitGroups: List<UnitGroup>
|
||||||
|
@ -24,8 +24,8 @@ import com.sadellie.unitto.core.base.OutputFormat
|
|||||||
import com.sadellie.unitto.core.base.Token
|
import com.sadellie.unitto.core.base.Token
|
||||||
import com.sadellie.unitto.core.base.TopLevelDestinations
|
import com.sadellie.unitto.core.base.TopLevelDestinations
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
import io.github.sadellie.themmo.core.MonetMode
|
import io.github.sadellie.themmo.core.MonetMode
|
||||||
import io.github.sadellie.themmo.core.ThemingMode
|
import io.github.sadellie.themmo.core.ThemingMode
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@
|
|||||||
package com.sadellie.unitto.data.userprefs
|
package com.sadellie.unitto.data.userprefs
|
||||||
|
|
||||||
import com.sadellie.unitto.core.base.FormatterSymbols
|
import com.sadellie.unitto.core.base.FormatterSymbols
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.userprefs.AboutPreferences
|
import com.sadellie.unitto.data.model.userprefs.AboutPreferences
|
||||||
import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences
|
import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences
|
||||||
import com.sadellie.unitto.data.model.userprefs.AppPreferences
|
import com.sadellie.unitto.data.model.userprefs.AppPreferences
|
||||||
|
@ -22,10 +22,9 @@ import androidx.datastore.core.DataStore
|
|||||||
import androidx.datastore.preferences.core.Preferences
|
import androidx.datastore.preferences.core.Preferences
|
||||||
import androidx.datastore.preferences.core.edit
|
import androidx.datastore.preferences.core.edit
|
||||||
import androidx.datastore.preferences.core.emptyPreferences
|
import androidx.datastore.preferences.core.emptyPreferences
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
|
||||||
import com.sadellie.unitto.data.model.userprefs.AboutPreferences
|
import com.sadellie.unitto.data.model.userprefs.AboutPreferences
|
||||||
import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences
|
import com.sadellie.unitto.data.model.userprefs.AddSubtractPreferences
|
||||||
import com.sadellie.unitto.data.model.userprefs.AppPreferences
|
import com.sadellie.unitto.data.model.userprefs.AppPreferences
|
||||||
@ -182,10 +181,10 @@ class UserPreferencesRepositoryImpl @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun updateLatestPairOfUnits(unitFrom: AbstractUnit, unitTo: AbstractUnit) {
|
override suspend fun updateLatestPairOfUnits(unitFrom: String, unitTo: String) {
|
||||||
dataStore.edit { preferences ->
|
dataStore.edit { preferences ->
|
||||||
preferences[PrefsKeys.LATEST_LEFT_SIDE] = unitFrom.id
|
preferences[PrefsKeys.LATEST_LEFT_SIDE] = unitFrom
|
||||||
preferences[PrefsKeys.LATEST_RIGHT_SIDE] = unitTo.id
|
preferences[PrefsKeys.LATEST_RIGHT_SIDE] = unitTo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,6 +55,7 @@ import androidx.compose.runtime.derivedStateOf
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
@ -83,24 +84,30 @@ import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar
|
|||||||
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField
|
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.NumberBaseTextField
|
import com.sadellie.unitto.core.ui.common.textfield.NumberBaseTextField
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.SimpleTextField
|
import com.sadellie.unitto.core.ui.common.textfield.SimpleTextField
|
||||||
|
import com.sadellie.unitto.core.ui.common.textfield.addBracket
|
||||||
|
import com.sadellie.unitto.core.ui.common.textfield.addTokens
|
||||||
|
import com.sadellie.unitto.core.ui.common.textfield.deleteTokens
|
||||||
import com.sadellie.unitto.core.ui.datetime.formatDateWeekDayMonthYear
|
import com.sadellie.unitto.core.ui.datetime.formatDateWeekDayMonthYear
|
||||||
import com.sadellie.unitto.data.common.format
|
import com.sadellie.unitto.data.common.format
|
||||||
|
import com.sadellie.unitto.data.common.isEqualTo
|
||||||
|
import com.sadellie.unitto.data.common.isExpression
|
||||||
|
import com.sadellie.unitto.data.converter.ConverterResult
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
|
||||||
import com.sadellie.unitto.feature.converter.components.DefaultKeyboard
|
import com.sadellie.unitto.feature.converter.components.DefaultKeyboard
|
||||||
import com.sadellie.unitto.feature.converter.components.NumberBaseKeyboard
|
import com.sadellie.unitto.feature.converter.components.NumberBaseKeyboard
|
||||||
import com.sadellie.unitto.feature.converter.components.UnitSelectionButton
|
import com.sadellie.unitto.feature.converter.components.UnitSelectionButton
|
||||||
|
import java.math.BigDecimal
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun ConverterRoute(
|
internal fun ConverterRoute(
|
||||||
viewModel: ConverterViewModel = hiltViewModel(),
|
viewModel: ConverterViewModel = hiltViewModel(),
|
||||||
navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit,
|
navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit,
|
||||||
navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit,
|
navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit,
|
||||||
openDrawer: () -> Unit,
|
openDrawer: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val uiState = viewModel.converterUiState.collectAsStateWithLifecycle()
|
val uiState = viewModel.converterUIState.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
ConverterScreen(
|
ConverterScreen(
|
||||||
uiState = uiState.value,
|
uiState = uiState.value,
|
||||||
@ -108,30 +115,24 @@ internal fun ConverterRoute(
|
|||||||
navigateToRightScreen = navigateToRightScreen,
|
navigateToRightScreen = navigateToRightScreen,
|
||||||
openDrawer = openDrawer,
|
openDrawer = openDrawer,
|
||||||
swapUnits = viewModel::swapUnits,
|
swapUnits = viewModel::swapUnits,
|
||||||
processInput = viewModel::addTokens,
|
updateInput1 = viewModel::updateInput1,
|
||||||
deleteDigit = viewModel::deleteTokens,
|
updateInput2 = viewModel::updateInput2,
|
||||||
clearInput = viewModel::clearInput,
|
convertDefault = viewModel::convertDefault,
|
||||||
onValueChange = viewModel::updateInput,
|
convertNumberBase = viewModel::convertNumberBase,
|
||||||
onFocusOnInput2 = viewModel::updateFocused,
|
|
||||||
onErrorClick = viewModel::updateCurrencyRates,
|
|
||||||
addBracket = viewModel::addBracket,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ConverterScreen(
|
private fun ConverterScreen(
|
||||||
uiState: UnitConverterUIState,
|
uiState: UnitConverterUIState,
|
||||||
navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit,
|
navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit,
|
||||||
navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit,
|
navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit,
|
||||||
openDrawer: () -> Unit,
|
openDrawer: () -> Unit,
|
||||||
swapUnits: () -> Unit,
|
swapUnits: (String, String) -> Unit,
|
||||||
processInput: (String) -> Unit,
|
updateInput1: (TextFieldValue) -> Unit,
|
||||||
deleteDigit: () -> Unit,
|
updateInput2: (TextFieldValue) -> Unit,
|
||||||
clearInput: () -> Unit,
|
convertDefault: () -> Unit,
|
||||||
onValueChange: (TextFieldValue) -> Unit,
|
convertNumberBase: () -> Unit,
|
||||||
onFocusOnInput2: (Boolean) -> Unit,
|
|
||||||
onErrorClick: (AbstractUnit) -> Unit,
|
|
||||||
addBracket: () -> Unit,
|
|
||||||
) {
|
) {
|
||||||
when (uiState) {
|
when (uiState) {
|
||||||
UnitConverterUIState.Loading -> EmptyScreen()
|
UnitConverterUIState.Loading -> EmptyScreen()
|
||||||
@ -143,13 +144,11 @@ private fun ConverterScreen(
|
|||||||
NumberBase(
|
NumberBase(
|
||||||
modifier = Modifier.padding(it),
|
modifier = Modifier.padding(it),
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
onValueChange = onValueChange,
|
updateInput1 = updateInput1,
|
||||||
processInput = processInput,
|
|
||||||
deleteDigit = deleteDigit,
|
|
||||||
navigateToLeftScreen = navigateToLeftScreen,
|
navigateToLeftScreen = navigateToLeftScreen,
|
||||||
swapUnits = swapUnits,
|
swapUnits = swapUnits,
|
||||||
navigateToRightScreen = navigateToRightScreen,
|
navigateToRightScreen = navigateToRightScreen,
|
||||||
clearInput = clearInput,
|
convert = convertNumberBase,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -161,16 +160,12 @@ private fun ConverterScreen(
|
|||||||
Default(
|
Default(
|
||||||
modifier = Modifier.padding(it),
|
modifier = Modifier.padding(it),
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
onValueChange = onValueChange,
|
updateInput1 = updateInput1,
|
||||||
onFocusOnInput2 = onFocusOnInput2,
|
updateInput2 = updateInput2,
|
||||||
processInput = processInput,
|
|
||||||
deleteDigit = deleteDigit,
|
|
||||||
navigateToLeftScreen = navigateToLeftScreen,
|
navigateToLeftScreen = navigateToLeftScreen,
|
||||||
swapUnits = swapUnits,
|
swapUnits = swapUnits,
|
||||||
navigateToRightScreen = navigateToRightScreen,
|
navigateToRightScreen = navigateToRightScreen,
|
||||||
clearInput = clearInput,
|
convert = convertDefault,
|
||||||
refreshCurrencyRates = onErrorClick,
|
|
||||||
addBracket = addBracket,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,14 +189,20 @@ private fun UnitConverterTopBar(
|
|||||||
private fun NumberBase(
|
private fun NumberBase(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
uiState: UnitConverterUIState.NumberBase,
|
uiState: UnitConverterUIState.NumberBase,
|
||||||
onValueChange: (TextFieldValue) -> Unit,
|
updateInput1: (TextFieldValue) -> Unit,
|
||||||
processInput: (String) -> Unit,
|
navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit,
|
||||||
deleteDigit: () -> Unit,
|
swapUnits: (String, String) -> Unit,
|
||||||
navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit,
|
navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit,
|
||||||
swapUnits: () -> Unit,
|
convert: () -> Unit,
|
||||||
navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit,
|
|
||||||
clearInput: () -> Unit,
|
|
||||||
) {
|
) {
|
||||||
|
LaunchedEffect(
|
||||||
|
uiState.input.text,
|
||||||
|
uiState.unitFrom.id,
|
||||||
|
uiState.unitTo.id,
|
||||||
|
) {
|
||||||
|
convert()
|
||||||
|
}
|
||||||
|
|
||||||
PortraitLandscape(
|
PortraitLandscape(
|
||||||
modifier = modifier.fillMaxSize(),
|
modifier = modifier.fillMaxSize(),
|
||||||
content1 = { contentModifier ->
|
content1 = { contentModifier ->
|
||||||
@ -213,7 +214,7 @@ private fun NumberBase(
|
|||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
placeholder = Token.Digit._0,
|
placeholder = Token.Digit._0,
|
||||||
value = uiState.input,
|
value = uiState.input,
|
||||||
onValueChange = onValueChange,
|
onValueChange = updateInput1,
|
||||||
)
|
)
|
||||||
AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName))
|
AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName))
|
||||||
|
|
||||||
@ -228,18 +229,27 @@ private fun NumberBase(
|
|||||||
UnitSelectionButtons(
|
UnitSelectionButtons(
|
||||||
unitFromLabel = stringResource(uiState.unitFrom.displayName),
|
unitFromLabel = stringResource(uiState.unitFrom.displayName),
|
||||||
unitToLabel = stringResource(uiState.unitTo.displayName),
|
unitToLabel = stringResource(uiState.unitTo.displayName),
|
||||||
swapUnits = swapUnits,
|
swapUnits = { swapUnits(uiState.unitTo.id, uiState.unitFrom.id) },
|
||||||
navigateToLeftScreen = { navigateToLeftScreen(uiState) },
|
navigateToLeftScreen = {
|
||||||
navigateToRightScreen = { navigateToRightScreen(uiState) },
|
navigateToLeftScreen(uiState.unitFrom.id, uiState.unitFrom.group)
|
||||||
|
},
|
||||||
|
navigateToRightScreen = {
|
||||||
|
navigateToRightScreen(
|
||||||
|
uiState.unitFrom.id,
|
||||||
|
uiState.unitTo.id,
|
||||||
|
uiState.unitFrom.group,
|
||||||
|
uiState.input.text,
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
content2 = {
|
content2 = { modifier2 ->
|
||||||
NumberBaseKeyboard(
|
NumberBaseKeyboard(
|
||||||
modifier = it,
|
modifier = modifier2,
|
||||||
addDigit = processInput,
|
addDigit = { updateInput1(uiState.input.addTokens(it)) },
|
||||||
deleteDigit = deleteDigit,
|
deleteDigit = { updateInput1(uiState.input.deleteTokens()) },
|
||||||
clearInput = clearInput,
|
clearInput = { updateInput1(TextFieldValue()) },
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -249,22 +259,21 @@ private fun NumberBase(
|
|||||||
private fun Default(
|
private fun Default(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
uiState: UnitConverterUIState.Default,
|
uiState: UnitConverterUIState.Default,
|
||||||
onValueChange: (TextFieldValue) -> Unit,
|
updateInput1: (TextFieldValue) -> Unit,
|
||||||
onFocusOnInput2: (Boolean) -> Unit,
|
updateInput2: (TextFieldValue) -> Unit,
|
||||||
processInput: (String) -> Unit,
|
navigateToLeftScreen: (unitFromId: String, group: UnitGroup) -> Unit,
|
||||||
deleteDigit: () -> Unit,
|
swapUnits: (String, String) -> Unit,
|
||||||
navigateToLeftScreen: (uiState: UnitConverterUIState) -> Unit,
|
navigateToRightScreen: (unitFromId: String, unitToId: String, group: UnitGroup, input: String) -> Unit,
|
||||||
swapUnits: () -> Unit,
|
convert: () -> Unit,
|
||||||
navigateToRightScreen: (uiState: UnitConverterUIState) -> Unit,
|
|
||||||
clearInput: () -> Unit,
|
|
||||||
refreshCurrencyRates: (AbstractUnit) -> Unit,
|
|
||||||
addBracket: () -> Unit,
|
|
||||||
) {
|
) {
|
||||||
val locale: Locale = LocalLocale.current
|
val locale: Locale = LocalLocale.current
|
||||||
var calculation by remember(uiState.calculation) {
|
val showCalculation = remember(uiState.input1.text, uiState.result) {
|
||||||
mutableStateOf(
|
if (uiState.input1.text.isExpression()) {
|
||||||
TextFieldValue(uiState.calculation?.format(uiState.scale, uiState.outputFormat) ?: ""),
|
if (uiState.result is ConverterResult.Default) {
|
||||||
)
|
return@remember !uiState.result.calculation.isEqualTo(BigDecimal.ZERO)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
}
|
}
|
||||||
val connection by connectivityState()
|
val connection by connectivityState()
|
||||||
val lastUpdate by remember(uiState.currencyRateUpdateState) {
|
val lastUpdate by remember(uiState.currencyRateUpdateState) {
|
||||||
@ -273,14 +282,25 @@ private fun Default(
|
|||||||
uiState.currencyRateUpdateState.date.formatDateWeekDayMonthYear(locale)
|
uiState.currencyRateUpdateState.date.formatDateWeekDayMonthYear(locale)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var focusedOnInput1 by rememberSaveable { mutableStateOf(true) }
|
||||||
|
|
||||||
LaunchedEffect(connection) {
|
LaunchedEffect(connection) {
|
||||||
if ((connection == ConnectionState.Available) and (uiState.result == ConverterResult.Error)) {
|
if ((connection == ConnectionState.Available) and (uiState.result is ConverterResult.Error)) {
|
||||||
val unitFrom = uiState.unitFrom
|
val unitFrom = uiState.unitFrom
|
||||||
if (unitFrom.group == UnitGroup.CURRENCY) refreshCurrencyRates(unitFrom)
|
if (unitFrom.group == UnitGroup.CURRENCY) convert()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(
|
||||||
|
uiState.input1.text,
|
||||||
|
uiState.input2.text,
|
||||||
|
uiState.unitFrom.id,
|
||||||
|
uiState.unitTo.id,
|
||||||
|
uiState.formatTime,
|
||||||
|
) {
|
||||||
|
convert()
|
||||||
|
}
|
||||||
|
|
||||||
PortraitLandscape(
|
PortraitLandscape(
|
||||||
modifier = modifier.fillMaxSize(),
|
modifier = modifier.fillMaxSize(),
|
||||||
content1 = { contentModifier ->
|
content1 = { contentModifier ->
|
||||||
@ -322,7 +342,7 @@ private fun Default(
|
|||||||
.weight(1f),
|
.weight(1f),
|
||||||
value = uiState.input1,
|
value = uiState.input1,
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
onValueChange = onValueChange,
|
onValueChange = updateInput1,
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
placeholder = Token.Digit._0,
|
placeholder = Token.Digit._0,
|
||||||
)
|
)
|
||||||
@ -340,10 +360,10 @@ private fun Default(
|
|||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.weight(1f)
|
.weight(1f)
|
||||||
.onFocusEvent { state -> onFocusOnInput2(state.hasFocus) },
|
.onFocusEvent { state -> focusedOnInput1 = !state.hasFocus },
|
||||||
value = uiState.input2,
|
value = uiState.input2,
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
onValueChange = onValueChange,
|
onValueChange = updateInput2,
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
placeholder = Token.Digit._0,
|
placeholder = Token.Digit._0,
|
||||||
)
|
)
|
||||||
@ -355,21 +375,30 @@ private fun Default(
|
|||||||
modifier = textFieldModifier,
|
modifier = textFieldModifier,
|
||||||
value = uiState.input1,
|
value = uiState.input1,
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
onValueChange = onValueChange,
|
onValueChange = updateInput1,
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
placeholder = Token.Digit._0,
|
placeholder = Token.Digit._0,
|
||||||
)
|
)
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = calculation.text.isNotEmpty(),
|
visible = showCalculation,
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
enter = expandVertically(clip = false),
|
enter = expandVertically(clip = false),
|
||||||
exit = shrinkVertically(clip = false),
|
exit = shrinkVertically(clip = false),
|
||||||
) {
|
) {
|
||||||
|
var calculationTextField by remember(uiState.result) {
|
||||||
|
val text = if (uiState.result is ConverterResult.Default) {
|
||||||
|
uiState.result.calculation
|
||||||
|
.format(uiState.scale, uiState.outputFormat)
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
mutableStateOf(TextFieldValue(text))
|
||||||
|
}
|
||||||
ExpressionTextField(
|
ExpressionTextField(
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
value = calculation,
|
value = calculationTextField,
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
onValueChange = { calculation = it },
|
onValueChange = { calculationTextField = it },
|
||||||
textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
|
textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
@ -384,14 +413,14 @@ private fun Default(
|
|||||||
scale = uiState.scale,
|
scale = uiState.scale,
|
||||||
outputFormat = uiState.outputFormat,
|
outputFormat = uiState.outputFormat,
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
onErrorClick = { refreshCurrencyRates(uiState.unitFrom) },
|
onErrorClick = convert,
|
||||||
)
|
)
|
||||||
AnimatedUnitShortName(
|
AnimatedUnitShortName(
|
||||||
stringResource(
|
stringResource(
|
||||||
if (uiState.result is ConverterResult.Error) {
|
when (uiState.result) {
|
||||||
R.string.click_to_try_again_label
|
// Currency conversion can be retried
|
||||||
} else {
|
is ConverterResult.Error.Currency -> R.string.click_to_try_again_label
|
||||||
uiState.unitTo.shortName
|
else -> uiState.unitTo.shortName
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
@ -401,22 +430,58 @@ private fun Default(
|
|||||||
UnitSelectionButtons(
|
UnitSelectionButtons(
|
||||||
unitFromLabel = stringResource(uiState.unitFrom.displayName),
|
unitFromLabel = stringResource(uiState.unitFrom.displayName),
|
||||||
unitToLabel = stringResource(uiState.unitTo.displayName),
|
unitToLabel = stringResource(uiState.unitTo.displayName),
|
||||||
swapUnits = swapUnits,
|
swapUnits = { swapUnits(uiState.unitTo.id, uiState.unitFrom.id) },
|
||||||
navigateToLeftScreen = { navigateToLeftScreen(uiState) },
|
navigateToLeftScreen = {
|
||||||
navigateToRightScreen = { navigateToRightScreen(uiState) },
|
navigateToLeftScreen(uiState.unitFrom.id, uiState.unitFrom.group)
|
||||||
|
},
|
||||||
|
navigateToRightScreen = {
|
||||||
|
val input = if (uiState.result is ConverterResult.Default) {
|
||||||
|
uiState.result.calculation.toPlainString()
|
||||||
|
} else {
|
||||||
|
uiState.input1.text
|
||||||
|
}
|
||||||
|
|
||||||
|
navigateToRightScreen(
|
||||||
|
uiState.unitFrom.id,
|
||||||
|
uiState.unitTo.id,
|
||||||
|
uiState.unitFrom.group,
|
||||||
|
input,
|
||||||
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
content2 = {
|
content2 = { modifier2 ->
|
||||||
DefaultKeyboard(
|
DefaultKeyboard(
|
||||||
modifier = it,
|
modifier = modifier2,
|
||||||
addDigit = processInput,
|
addDigit = {
|
||||||
deleteDigit = deleteDigit,
|
if (focusedOnInput1) {
|
||||||
clearInput = clearInput,
|
updateInput1(uiState.input1.addTokens(it))
|
||||||
|
} else {
|
||||||
|
updateInput2(uiState.input2.addTokens(it))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deleteDigit = {
|
||||||
|
if (focusedOnInput1) {
|
||||||
|
updateInput1(uiState.input1.deleteTokens())
|
||||||
|
} else {
|
||||||
|
updateInput2(uiState.input2.deleteTokens())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
clearInput = {
|
||||||
|
updateInput1(TextFieldValue())
|
||||||
|
updateInput2(TextFieldValue())
|
||||||
|
},
|
||||||
fractional = uiState.formatterSymbols.fractional,
|
fractional = uiState.formatterSymbols.fractional,
|
||||||
middleZero = uiState.middleZero,
|
middleZero = uiState.middleZero,
|
||||||
acButton = uiState.acButton,
|
acButton = uiState.acButton,
|
||||||
addBracket = addBracket,
|
addBracket = {
|
||||||
|
if (focusedOnInput1) {
|
||||||
|
updateInput1(uiState.input1.addBracket())
|
||||||
|
} else {
|
||||||
|
updateInput2(uiState.input2.addBracket())
|
||||||
|
}
|
||||||
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -454,6 +519,17 @@ private fun ConverterResultTextField(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is ConverterResult.Error.DivideByZero -> {
|
||||||
|
SimpleTextField(
|
||||||
|
modifier = modifier,
|
||||||
|
value = TextFieldValue(stringResource(R.string.calculator_divide_by_zero_error)),
|
||||||
|
onValueChange = { onErrorClick() },
|
||||||
|
minRatio = 0.7f,
|
||||||
|
readOnly = true,
|
||||||
|
textColor = MaterialTheme.colorScheme.error,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
is ConverterResult.Error -> {
|
is ConverterResult.Error -> {
|
||||||
SimpleTextField(
|
SimpleTextField(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
@ -578,16 +654,13 @@ private fun UnitSelectionButtons(
|
|||||||
private fun PreviewConverterScreen() {
|
private fun PreviewConverterScreen() {
|
||||||
ConverterScreen(
|
ConverterScreen(
|
||||||
uiState = UnitConverterUIState.Loading,
|
uiState = UnitConverterUIState.Loading,
|
||||||
navigateToLeftScreen = {},
|
navigateToLeftScreen = { _, _ -> },
|
||||||
navigateToRightScreen = {},
|
navigateToRightScreen = { _, _, _, _ -> },
|
||||||
openDrawer = {},
|
openDrawer = {},
|
||||||
swapUnits = {},
|
swapUnits = { _, _ -> },
|
||||||
processInput = {},
|
updateInput1 = {},
|
||||||
deleteDigit = {},
|
updateInput2 = {},
|
||||||
clearInput = {},
|
convertDefault = {},
|
||||||
onValueChange = {},
|
convertNumberBase = {},
|
||||||
onFocusOnInput2 = {},
|
|
||||||
onErrorClick = {},
|
|
||||||
addBracket = {},
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -25,14 +25,10 @@ import com.sadellie.unitto.core.base.R
|
|||||||
import com.sadellie.unitto.core.base.Token
|
import com.sadellie.unitto.core.base.Token
|
||||||
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.common.isEqualTo
|
|
||||||
import com.sadellie.unitto.data.common.isGreaterThan
|
import com.sadellie.unitto.data.common.isGreaterThan
|
||||||
import com.sadellie.unitto.data.common.isLessThan
|
import com.sadellie.unitto.data.converter.ConverterResult
|
||||||
import com.sadellie.unitto.data.common.trimZeros
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.unit.DefaultUnit
|
|
||||||
import com.sadellie.unitto.data.model.unit.NumberBaseUnit
|
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
import java.math.RoundingMode
|
|
||||||
|
|
||||||
internal sealed class UnitConverterUIState {
|
internal sealed class UnitConverterUIState {
|
||||||
data object Loading : UnitConverterUIState()
|
data object Loading : UnitConverterUIState()
|
||||||
@ -40,10 +36,9 @@ internal sealed class UnitConverterUIState {
|
|||||||
data class Default(
|
data class Default(
|
||||||
val input1: TextFieldValue,
|
val input1: TextFieldValue,
|
||||||
val input2: TextFieldValue,
|
val input2: TextFieldValue,
|
||||||
val calculation: BigDecimal?,
|
|
||||||
val result: ConverterResult,
|
val result: ConverterResult,
|
||||||
val unitFrom: DefaultUnit,
|
val unitFrom: BasicUnit.Default,
|
||||||
val unitTo: DefaultUnit,
|
val unitTo: BasicUnit.Default,
|
||||||
val middleZero: Boolean,
|
val middleZero: Boolean,
|
||||||
val formatterSymbols: FormatterSymbols,
|
val formatterSymbols: FormatterSymbols,
|
||||||
val scale: Int,
|
val scale: Int,
|
||||||
@ -56,45 +51,11 @@ internal sealed class UnitConverterUIState {
|
|||||||
data class NumberBase(
|
data class NumberBase(
|
||||||
val input: TextFieldValue,
|
val input: TextFieldValue,
|
||||||
val result: ConverterResult,
|
val result: ConverterResult,
|
||||||
val unitFrom: NumberBaseUnit,
|
val unitFrom: BasicUnit.NumberBase,
|
||||||
val unitTo: NumberBaseUnit,
|
val unitTo: BasicUnit.NumberBase,
|
||||||
) : UnitConverterUIState()
|
) : UnitConverterUIState()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class ConverterResult {
|
|
||||||
data class Default(val value: BigDecimal) : ConverterResult() {
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (other !is Default) return false
|
|
||||||
return this.value.isEqualTo(other.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hashCode(): Int = value.hashCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
data class NumberBase(val value: String) : ConverterResult()
|
|
||||||
|
|
||||||
data class Time(
|
|
||||||
val negative: Boolean,
|
|
||||||
val day: BigDecimal,
|
|
||||||
val hour: BigDecimal,
|
|
||||||
val minute: BigDecimal,
|
|
||||||
val second: BigDecimal,
|
|
||||||
val millisecond: BigDecimal,
|
|
||||||
val microsecond: BigDecimal,
|
|
||||||
val nanosecond: BigDecimal,
|
|
||||||
val attosecond: BigDecimal,
|
|
||||||
) : ConverterResult()
|
|
||||||
|
|
||||||
data class FootInch(
|
|
||||||
val foot: BigDecimal,
|
|
||||||
val inch: BigDecimal,
|
|
||||||
) : ConverterResult()
|
|
||||||
|
|
||||||
data object Loading : ConverterResult()
|
|
||||||
|
|
||||||
data object Error : ConverterResult()
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun ConverterResult.Time.format(
|
internal fun ConverterResult.Time.format(
|
||||||
mContext: Context,
|
mContext: Context,
|
||||||
formatterSymbols: FormatterSymbols,
|
formatterSymbols: FormatterSymbols,
|
||||||
@ -154,110 +115,3 @@ internal fun ConverterResult.FootInch.format(
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun formatTime(
|
|
||||||
input: BigDecimal,
|
|
||||||
): ConverterResult.Time {
|
|
||||||
val negative = input < BigDecimal.ZERO
|
|
||||||
val inputAbs = input.abs()
|
|
||||||
|
|
||||||
if (inputAbs.isLessThan(attosecondBasicUnit)) {
|
|
||||||
return ConverterResult.Time(
|
|
||||||
negative = negative,
|
|
||||||
day = BigDecimal.ZERO,
|
|
||||||
hour = BigDecimal.ZERO,
|
|
||||||
minute = BigDecimal.ZERO,
|
|
||||||
second = BigDecimal.ZERO,
|
|
||||||
millisecond = BigDecimal.ZERO,
|
|
||||||
microsecond = BigDecimal.ZERO,
|
|
||||||
nanosecond = BigDecimal.ZERO,
|
|
||||||
attosecond = inputAbs,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputAbs.isLessThan(nanosecondBasicUnit)) {
|
|
||||||
return ConverterResult.Time(
|
|
||||||
negative = negative,
|
|
||||||
day = BigDecimal.ZERO,
|
|
||||||
hour = BigDecimal.ZERO,
|
|
||||||
minute = BigDecimal.ZERO,
|
|
||||||
second = BigDecimal.ZERO,
|
|
||||||
millisecond = BigDecimal.ZERO,
|
|
||||||
microsecond = BigDecimal.ZERO,
|
|
||||||
nanosecond = BigDecimal.ZERO,
|
|
||||||
attosecond = inputAbs.trimZeros(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DAY
|
|
||||||
var division = inputAbs.divideAndRemainder(dayBasicUnit)
|
|
||||||
val day = division.component1().setScale(0, RoundingMode.HALF_EVEN)
|
|
||||||
var remainingSeconds = division.component2().setScale(0, RoundingMode.HALF_EVEN)
|
|
||||||
|
|
||||||
division = remainingSeconds.divideAndRemainder(hourBasicUnit)
|
|
||||||
val hour = division.component1()
|
|
||||||
remainingSeconds = division.component2()
|
|
||||||
|
|
||||||
division = remainingSeconds.divideAndRemainder(minuteBasicUnit)
|
|
||||||
val minute = division.component1()
|
|
||||||
remainingSeconds = division.component2()
|
|
||||||
|
|
||||||
division = remainingSeconds.divideAndRemainder(secondBasicUnit)
|
|
||||||
val second = division.component1()
|
|
||||||
remainingSeconds = division.component2()
|
|
||||||
|
|
||||||
division = remainingSeconds.divideAndRemainder(millisecondBasicUnit)
|
|
||||||
val millisecond = division.component1()
|
|
||||||
remainingSeconds = division.component2()
|
|
||||||
|
|
||||||
division = remainingSeconds.divideAndRemainder(microsecondBasicUnit)
|
|
||||||
val microsecond = division.component1()
|
|
||||||
remainingSeconds = division.component2()
|
|
||||||
|
|
||||||
division = remainingSeconds.divideAndRemainder(nanosecondBasicUnit)
|
|
||||||
val nanosecond = division.component1()
|
|
||||||
remainingSeconds = division.component2()
|
|
||||||
|
|
||||||
val attosecond = remainingSeconds
|
|
||||||
|
|
||||||
return ConverterResult.Time(
|
|
||||||
negative = negative,
|
|
||||||
day = day,
|
|
||||||
hour = hour,
|
|
||||||
minute = minute,
|
|
||||||
second = second,
|
|
||||||
millisecond = millisecond,
|
|
||||||
microsecond = microsecond,
|
|
||||||
nanosecond = nanosecond,
|
|
||||||
attosecond = attosecond,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates an object for displaying formatted foot and inch output. Units are passed as objects so
|
|
||||||
* that changes in basic units don't require modifying the method. Also this method can't access
|
|
||||||
* units repository directly.
|
|
||||||
*
|
|
||||||
* @param input Input in feet.
|
|
||||||
* @param footUnit Foot unit [DefaultUnit].
|
|
||||||
* @param inchUnit Inch unit [DefaultUnit].
|
|
||||||
* @return Result where decimal places are converter into inches.
|
|
||||||
*/
|
|
||||||
internal fun formatFootInch(
|
|
||||||
input: BigDecimal,
|
|
||||||
footUnit: DefaultUnit,
|
|
||||||
inchUnit: DefaultUnit,
|
|
||||||
): ConverterResult.FootInch {
|
|
||||||
val (integral, fractional) = input.divideAndRemainder(BigDecimal.ONE)
|
|
||||||
|
|
||||||
return ConverterResult.FootInch(integral, footUnit.convert(inchUnit, fractional))
|
|
||||||
}
|
|
||||||
|
|
||||||
private val dayBasicUnit by lazy { BigDecimal("86400000000000000000000") }
|
|
||||||
private val hourBasicUnit by lazy { BigDecimal("3600000000000000000000") }
|
|
||||||
private val minuteBasicUnit by lazy { BigDecimal("60000000000000000000") }
|
|
||||||
private val secondBasicUnit by lazy { BigDecimal("1000000000000000000") }
|
|
||||||
private val millisecondBasicUnit by lazy { BigDecimal("1000000000000000") }
|
|
||||||
private val microsecondBasicUnit by lazy { BigDecimal("1000000000000") }
|
|
||||||
private val nanosecondBasicUnit by lazy { BigDecimal("1000000000") }
|
|
||||||
private val attosecondBasicUnit by lazy { BigDecimal("1") }
|
|
||||||
|
@ -22,365 +22,210 @@ import androidx.compose.ui.text.input.TextFieldValue
|
|||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.core.base.Token
|
import com.sadellie.unitto.core.base.OutputFormat
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.addBracket
|
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.addTokens
|
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.deleteTokens
|
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.getTextField
|
import com.sadellie.unitto.core.ui.common.textfield.getTextField
|
||||||
import com.sadellie.unitto.data.common.combine
|
import com.sadellie.unitto.data.common.combine
|
||||||
import com.sadellie.unitto.data.common.isExpression
|
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.ConverterResult
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.converter.UnitsRepositoryImpl
|
||||||
import com.sadellie.unitto.data.model.repository.UnitsRepository
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
|
||||||
import com.sadellie.unitto.data.model.unit.DefaultUnit
|
|
||||||
import com.sadellie.unitto.data.model.unit.NumberBaseUnit
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import io.github.sadellie.evaluatto.Expression
|
|
||||||
import io.github.sadellie.evaluatto.ExpressionException
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.getAndUpdate
|
import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.flow.mapLatest
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import java.math.BigDecimal
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class ConverterViewModel @Inject constructor(
|
internal class ConverterViewModel @Inject constructor(
|
||||||
private val userPrefsRepository: UserPreferencesRepository,
|
private val userPrefsRepository: UserPreferencesRepository,
|
||||||
private val unitsRepo: UnitsRepository,
|
private val unitsRepo: UnitsRepositoryImpl,
|
||||||
private val savedStateHandle: SavedStateHandle,
|
private val savedStateHandle: SavedStateHandle,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
private var conversionJob: Job? = null
|
||||||
|
|
||||||
private val converterInputKey1 = "CONVERTER_INPUT_1"
|
private val converterInputKey1 = "CONVERTER_INPUT_1"
|
||||||
private val converterInputKey2 = "CONVERTER_INPUT_2"
|
private val converterInputKey2 = "CONVERTER_INPUT_2"
|
||||||
private val input1 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey1))
|
private val input1 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey1))
|
||||||
private val input2 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey2))
|
private val input2 = MutableStateFlow(savedStateHandle.getTextField(converterInputKey2))
|
||||||
private val focusedOnInput2 = MutableStateFlow(false)
|
private val output = MutableStateFlow<ConverterResult>(ConverterResult.Loading)
|
||||||
private val calculation = MutableStateFlow<BigDecimal?>(null)
|
|
||||||
private val result = MutableStateFlow<ConverterResult>(ConverterResult.Loading)
|
|
||||||
private val unitFrom = MutableStateFlow<AbstractUnit?>(null)
|
|
||||||
private val unitTo = MutableStateFlow<AbstractUnit?>(null)
|
|
||||||
|
|
||||||
private val currenciesState = MutableStateFlow<CurrencyRateUpdateState>(CurrencyRateUpdateState.Nothing)
|
private val unitFromId = MutableStateFlow<String?>(null)
|
||||||
private var loadCurrenciesJob: Job? = null
|
private val unitToId = MutableStateFlow<String?>(null)
|
||||||
|
|
||||||
val converterUiState: StateFlow<UnitConverterUIState> = combine(
|
private val unitFrom = unitFromId
|
||||||
|
.mapLatest { it?.let { unitsRepo.getById(it) } }
|
||||||
|
.flowOn(Dispatchers.Default)
|
||||||
|
.stateIn(viewModelScope, null)
|
||||||
|
|
||||||
|
private val unitTo = unitToId
|
||||||
|
.mapLatest { it?.let { unitsRepo.getById(it) } }
|
||||||
|
.flowOn(Dispatchers.Default)
|
||||||
|
.stateIn(viewModelScope, null)
|
||||||
|
|
||||||
|
val converterUIState: StateFlow<UnitConverterUIState> = combine(
|
||||||
input1,
|
input1,
|
||||||
input2,
|
input2,
|
||||||
calculation,
|
output,
|
||||||
result,
|
|
||||||
unitFrom,
|
unitFrom,
|
||||||
unitTo,
|
unitTo,
|
||||||
userPrefsRepository.converterPrefs,
|
userPrefsRepository.converterPrefs,
|
||||||
currenciesState,
|
) { input1Value, input2Value, outputValue, unitFromValue, unitToValue, prefs ->
|
||||||
) { input1, input2, calculation, result, unitFrom, unitTo, prefs, currenciesState ->
|
if (unitFromValue == null) return@combine UnitConverterUIState.Loading
|
||||||
return@combine when {
|
if (unitToValue == null) return@combine UnitConverterUIState.Loading
|
||||||
(unitFrom is DefaultUnit) and (unitTo is DefaultUnit) -> {
|
|
||||||
UnitConverterUIState.Default(
|
whenBothAre<BasicUnit.Default>(
|
||||||
input1 = input1,
|
value1 = unitFromValue,
|
||||||
input2 = input2,
|
value2 = unitToValue,
|
||||||
calculation = calculation,
|
) { unitFrom, unitTo ->
|
||||||
result = result,
|
return@combine UnitConverterUIState.Default(
|
||||||
unitFrom = unitFrom as DefaultUnit,
|
input1 = input1Value,
|
||||||
unitTo = unitTo as DefaultUnit,
|
input2 = input2Value,
|
||||||
|
result = outputValue,
|
||||||
|
unitFrom = unitFrom,
|
||||||
|
unitTo = unitTo,
|
||||||
middleZero = prefs.middleZero,
|
middleZero = prefs.middleZero,
|
||||||
formatterSymbols = prefs.formatterSymbols,
|
formatterSymbols = prefs.formatterSymbols,
|
||||||
scale = prefs.precision,
|
scale = prefs.precision,
|
||||||
outputFormat = prefs.outputFormat,
|
outputFormat = OutputFormat.PLAIN,
|
||||||
formatTime = prefs.unitConverterFormatTime,
|
formatTime = prefs.unitConverterFormatTime,
|
||||||
currencyRateUpdateState = currenciesState,
|
currencyRateUpdateState = CurrencyRateUpdateState.Nothing,
|
||||||
acButton = prefs.acButton,
|
acButton = prefs.acButton,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(unitFrom is NumberBaseUnit) and (unitTo is NumberBaseUnit) -> {
|
|
||||||
UnitConverterUIState.NumberBase(
|
whenBothAre<BasicUnit.NumberBase>(
|
||||||
input = input1,
|
value1 = unitFromValue,
|
||||||
result = result,
|
value2 = unitToValue,
|
||||||
unitFrom = unitFrom as NumberBaseUnit,
|
) { unitFrom, unitTo ->
|
||||||
unitTo = unitTo as NumberBaseUnit,
|
return@combine UnitConverterUIState.NumberBase(
|
||||||
|
input = input1Value,
|
||||||
|
result = outputValue,
|
||||||
|
unitFrom = unitFrom,
|
||||||
|
unitTo = unitTo,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
else -> UnitConverterUIState.Loading
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.mapLatest { ui ->
|
|
||||||
when (currenciesState.value) {
|
|
||||||
is CurrencyRateUpdateState.Loading -> {
|
|
||||||
result.update { ConverterResult.Loading }
|
|
||||||
return@mapLatest ui
|
|
||||||
}
|
|
||||||
is CurrencyRateUpdateState.Error -> {
|
|
||||||
result.update { ConverterResult.Error }
|
|
||||||
return@mapLatest ui
|
|
||||||
}
|
|
||||||
is CurrencyRateUpdateState.Ready, is CurrencyRateUpdateState.Nothing -> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
when (ui) {
|
return@combine UnitConverterUIState.Loading
|
||||||
is UnitConverterUIState.Default -> {
|
|
||||||
convertDefault(
|
|
||||||
unitFrom = ui.unitFrom,
|
|
||||||
unitTo = ui.unitTo,
|
|
||||||
input1 = ui.input1,
|
|
||||||
input2 = ui.input2,
|
|
||||||
formatTime = ui.formatTime,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is UnitConverterUIState.NumberBase -> {
|
|
||||||
convertNumberBase(
|
|
||||||
unitFrom = ui.unitFrom,
|
|
||||||
unitTo = ui.unitTo,
|
|
||||||
input = ui.input,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
is UnitConverterUIState.Loading -> {}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui
|
|
||||||
}
|
}
|
||||||
.stateIn(viewModelScope, UnitConverterUIState.Loading)
|
.stateIn(viewModelScope, UnitConverterUIState.Loading)
|
||||||
|
|
||||||
fun swapUnits() {
|
fun updateInput1(value: TextFieldValue) {
|
||||||
unitFrom
|
input1.update { value }
|
||||||
.getAndUpdate { unitTo.value }
|
savedStateHandle[converterInputKey1] = value.text
|
||||||
.also { oldUnitFrom -> unitTo.update { oldUnitFrom } }
|
|
||||||
|
|
||||||
loadCurrenciesJob?.cancel()
|
|
||||||
currenciesState.update { CurrencyRateUpdateState.Nothing }
|
|
||||||
unitFrom.value?.let {
|
|
||||||
if (it.group == UnitGroup.CURRENCY) updateCurrencyRates(it)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModelScope.launch {
|
fun updateInput2(value: TextFieldValue) {
|
||||||
val unitTo = unitTo.value ?: return@launch
|
input2.update { value }
|
||||||
val unitFrom = unitFrom.value ?: return@launch
|
savedStateHandle[converterInputKey2] = value.text
|
||||||
|
|
||||||
userPrefsRepository.updateLatestPairOfUnits(unitFrom = unitFrom, unitTo = unitTo)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateUnitFromId(id: String) = viewModelScope.launch {
|
||||||
|
val pairId = unitsRepo.getPairId(id)
|
||||||
|
|
||||||
|
unitFromId.update { id }
|
||||||
|
unitToId.update { pairId }
|
||||||
|
|
||||||
|
unitsRepo.incrementCounter(id)
|
||||||
|
updateLatestPairOfUnits()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateUnitToId(id: String) = viewModelScope.launch {
|
||||||
|
unitToId.update { id }
|
||||||
|
unitsRepo.incrementCounter(id)
|
||||||
|
setPair()
|
||||||
|
updateLatestPairOfUnits()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun swapUnits(
|
||||||
|
newUnitFromId: String,
|
||||||
|
newInputToId: String,
|
||||||
|
) = viewModelScope.launch {
|
||||||
|
unitFromId.update { newUnitFromId }
|
||||||
|
unitToId.update { newInputToId }
|
||||||
|
setPair()
|
||||||
|
updateLatestPairOfUnits()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun convertDefault() {
|
||||||
|
conversionJob?.cancel()
|
||||||
|
conversionJob = viewModelScope.launch {
|
||||||
|
val result = unitsRepo.convertDefault(
|
||||||
|
unitFromId = unitFromId.value ?: return@launch,
|
||||||
|
unitToId = unitToId.value ?: return@launch,
|
||||||
|
value1 = input1.value.text,
|
||||||
|
value2 = input2.value.text,
|
||||||
|
formatTime = userPrefsRepository.converterPrefs.first().unitConverterFormatTime,
|
||||||
|
)
|
||||||
|
|
||||||
|
when (result) {
|
||||||
|
is ConverterResult.Error.BadInput -> Unit
|
||||||
|
else -> output.update { result }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun convertNumberBase() {
|
||||||
|
conversionJob?.cancel()
|
||||||
|
conversionJob = viewModelScope.launch {
|
||||||
|
unitsRepo.convertNumberBase(
|
||||||
|
unitFromId = unitFromId.value ?: return@launch,
|
||||||
|
unitToId = unitToId.value ?: return@launch,
|
||||||
|
value = input1.value.text,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadInitialUnits() = viewModelScope.launch {
|
||||||
|
val prefs = userPrefsRepository.converterPrefs.first()
|
||||||
|
unitFromId.update { prefs.latestLeftSideUnit }
|
||||||
|
unitToId.update { prefs.latestRightSideUnit }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setPair() = viewModelScope.launch {
|
||||||
|
unitsRepo.setPair(
|
||||||
|
id = unitFromId.value ?: return@launch,
|
||||||
|
pairId = unitToId.value ?: return@launch,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateLatestPairOfUnits() = viewModelScope.launch {
|
||||||
|
userPrefsRepository
|
||||||
|
.updateLatestPairOfUnits(
|
||||||
|
unitFrom = unitFromId.value ?: return@launch,
|
||||||
|
unitTo = unitToId.value ?: return@launch,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change currently focused text field. For feet and inches input
|
* Will call [block] if both [value1] and [value2] are [T].
|
||||||
*
|
*
|
||||||
* @param focusOnInput2 `true` if focus is on inches input. `false`if focus on feet input.
|
* @param T What to check against.
|
||||||
|
* @param value1 Value to check.
|
||||||
|
* @param value2 Value to check.
|
||||||
|
* @param block Block that will be called if the has passed.
|
||||||
*/
|
*/
|
||||||
fun updateFocused(focusOnInput2: Boolean) = focusedOnInput2.update { focusOnInput2 }
|
private inline fun <reified T> whenBothAre(
|
||||||
|
value1: Any?,
|
||||||
fun addTokens(tokens: String) {
|
value2: Any?,
|
||||||
if (focusedOnInput2.value) {
|
block: (v1: T, v2: T) -> Unit,
|
||||||
input2.update {
|
) {
|
||||||
val newValue = it.addTokens(tokens)
|
if ((value1 is T) and (value2 is T)) block(value1 as T, value2 as T)
|
||||||
savedStateHandle[converterInputKey2] = newValue.text
|
|
||||||
newValue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
input1.update {
|
|
||||||
val newValue = it.addTokens(tokens)
|
|
||||||
savedStateHandle[converterInputKey1] = newValue.text
|
|
||||||
newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addBracket() {
|
|
||||||
if (focusedOnInput2.value) {
|
|
||||||
input2.update {
|
|
||||||
val newValue = it.addBracket()
|
|
||||||
savedStateHandle[converterInputKey2] = newValue.text
|
|
||||||
newValue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
input1.update {
|
|
||||||
val newValue = it.addBracket()
|
|
||||||
savedStateHandle[converterInputKey1] = newValue.text
|
|
||||||
newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun deleteTokens() {
|
|
||||||
if (focusedOnInput2.value) {
|
|
||||||
input2.update {
|
|
||||||
val newValue = it.deleteTokens()
|
|
||||||
savedStateHandle[converterInputKey2] = newValue.text
|
|
||||||
newValue
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
input1.update {
|
|
||||||
val newValue = it.deleteTokens()
|
|
||||||
savedStateHandle[converterInputKey1] = newValue.text
|
|
||||||
newValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun clearInput() {
|
|
||||||
input1.update {
|
|
||||||
savedStateHandle[converterInputKey1] = ""
|
|
||||||
TextFieldValue()
|
|
||||||
}
|
|
||||||
input2.update {
|
|
||||||
savedStateHandle[converterInputKey2] = ""
|
|
||||||
TextFieldValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateInput(value: TextFieldValue) = input1.update { value }
|
|
||||||
|
|
||||||
fun updateCurrencyRates(unit: AbstractUnit) {
|
|
||||||
loadCurrenciesJob = viewModelScope.launch(Dispatchers.IO) {
|
|
||||||
try {
|
|
||||||
currenciesState.update { CurrencyRateUpdateState.Loading }
|
|
||||||
val updateDate = unitsRepo.updateRates(unit) ?: throw Exception("Empty cache")
|
|
||||||
|
|
||||||
// Set to fresh objects with updated basic unit values
|
|
||||||
unitFrom.update { unitFrom -> unitFrom?.id?.let { unitsRepo.getById(it) } }
|
|
||||||
unitTo.update { unitTo -> unitTo?.id?.let { unitsRepo.getById(it) } }
|
|
||||||
currenciesState.update { CurrencyRateUpdateState.Ready(updateDate) }
|
|
||||||
} catch (e: Exception) {
|
|
||||||
currenciesState.update { CurrencyRateUpdateState.Error }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateUnitFrom(unit: AbstractUnit) = viewModelScope.launch {
|
|
||||||
val pairId = unit.pairId
|
|
||||||
val pair: AbstractUnit = if (pairId == null) {
|
|
||||||
val collection = unitsRepo.getCollection(unit.group).sortedByDescending { it.counter }
|
|
||||||
collection.firstOrNull { it.isFavorite } ?: collection.first()
|
|
||||||
} else {
|
|
||||||
unitsRepo.getById(pairId)
|
|
||||||
}
|
|
||||||
|
|
||||||
withContext(Dispatchers.Default) {
|
|
||||||
unitsRepo.incrementCounter(unit)
|
|
||||||
userPrefsRepository.updateLatestPairOfUnits(unitFrom = unit, unitTo = pair)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadCurrenciesJob?.cancel()
|
|
||||||
currenciesState.update { CurrencyRateUpdateState.Nothing }
|
|
||||||
if (unit.group == UnitGroup.CURRENCY) updateCurrencyRates(unit)
|
|
||||||
|
|
||||||
unitFrom.update {
|
|
||||||
// We change from something to base converter or the other way around
|
|
||||||
if ((it?.group == UnitGroup.NUMBER_BASE) xor (unit.group == UnitGroup.NUMBER_BASE)) {
|
|
||||||
clearInput()
|
|
||||||
}
|
|
||||||
|
|
||||||
unit
|
|
||||||
}
|
|
||||||
unitTo.update { pair }
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateUnitTo(unit: AbstractUnit) {
|
|
||||||
unitTo.update { unit }
|
|
||||||
|
|
||||||
viewModelScope.launch {
|
|
||||||
val unitTo = unitTo.value ?: return@launch
|
|
||||||
val unitFrom = unitFrom.value ?: return@launch
|
|
||||||
|
|
||||||
unitsRepo.incrementCounter(unitTo)
|
|
||||||
|
|
||||||
unitsRepo.setPair(unitFrom, unitTo)
|
|
||||||
userPrefsRepository.updateLatestPairOfUnits(unitFrom = unitFrom, unitTo = unitTo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun convertDefault(
|
|
||||||
unitFrom: DefaultUnit,
|
|
||||||
unitTo: DefaultUnit,
|
|
||||||
input1: TextFieldValue,
|
|
||||||
input2: TextFieldValue,
|
|
||||||
formatTime: Boolean,
|
|
||||||
) = viewModelScope.launch(Dispatchers.Default) {
|
|
||||||
val footInchInput = unitFrom.id == UnitID.foot
|
|
||||||
|
|
||||||
if (footInchInput) {
|
|
||||||
calculation.update { null }
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculate
|
|
||||||
val calculated1 = try {
|
|
||||||
Expression(input1.text.ifEmpty { Token.Digit._0 }).calculate()
|
|
||||||
} catch (e: ExpressionException.DivideByZero) {
|
|
||||||
calculation.update { null }
|
|
||||||
return@launch
|
|
||||||
} catch (e: Exception) {
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update calculation
|
|
||||||
calculation.update { if (input1.text.isExpression()) calculated1 else null }
|
|
||||||
|
|
||||||
// Convert
|
|
||||||
val result: ConverterResult = try {
|
|
||||||
var conversion = unitFrom.convert(unitTo, calculated1)
|
|
||||||
if (footInchInput) {
|
|
||||||
// Converted from second text field too
|
|
||||||
val inches = unitsRepo.getById(UnitID.inch) as DefaultUnit
|
|
||||||
val calculated2 = try {
|
|
||||||
Expression(input2.text.ifEmpty { Token.Digit._0 }).calculate()
|
|
||||||
} catch (e: ExpressionException.DivideByZero) {
|
|
||||||
calculation.update { null }
|
|
||||||
return@launch
|
|
||||||
} catch (e: Exception) {
|
|
||||||
return@launch
|
|
||||||
}
|
|
||||||
conversion += inches.convert(unitTo, calculated2)
|
|
||||||
}
|
|
||||||
when {
|
|
||||||
(unitFrom.group == UnitGroup.TIME) and (formatTime) -> formatTime(calculated1.multiply(unitFrom.basicUnit))
|
|
||||||
unitTo.id == UnitID.foot -> formatFootInch(conversion, unitTo, unitsRepo.getById(UnitID.inch) as DefaultUnit)
|
|
||||||
else -> ConverterResult.Default(conversion)
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
ConverterResult.Default(BigDecimal.ZERO)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update result
|
|
||||||
this@ConverterViewModel.result.update { result }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun convertNumberBase(
|
|
||||||
unitFrom: NumberBaseUnit,
|
|
||||||
unitTo: NumberBaseUnit,
|
|
||||||
input: TextFieldValue,
|
|
||||||
) = viewModelScope.launch(Dispatchers.Default) {
|
|
||||||
val conversion = try {
|
|
||||||
unitFrom.convert(unitTo, input.text.ifEmpty { Token.Digit._0 })
|
|
||||||
} catch (e: Exception) {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
|
|
||||||
result.update { ConverterResult.NumberBase(conversion) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch(Dispatchers.Default) {
|
loadInitialUnits()
|
||||||
try {
|
|
||||||
val userPrefs = userPrefsRepository.converterPrefs.first()
|
|
||||||
val unitFrom = unitsRepo.getById(userPrefs.latestLeftSideUnit)
|
|
||||||
val unitTo = unitsRepo.getById(userPrefs.latestRightSideUnit)
|
|
||||||
|
|
||||||
this@ConverterViewModel.unitFrom.update { unitFrom }
|
|
||||||
this@ConverterViewModel.unitTo.update { unitTo }
|
|
||||||
if (unitFrom.group == UnitGroup.CURRENCY) updateCurrencyRates(unitFrom)
|
|
||||||
} catch (e: NoSuchElementException) {
|
|
||||||
val unitFrom = unitsRepo.getById(UnitID.kilometer)
|
|
||||||
val unitTo = unitsRepo.getById(UnitID.mile)
|
|
||||||
|
|
||||||
this@ConverterViewModel.unitFrom.update { unitFrom }
|
|
||||||
this@ConverterViewModel.unitTo.update { unitTo }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
viewModelScope.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,12 +22,10 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
@ -39,10 +37,11 @@ import com.sadellie.unitto.core.base.R
|
|||||||
import com.sadellie.unitto.core.ui.common.EmptyScreen
|
import com.sadellie.unitto.core.ui.common.EmptyScreen
|
||||||
import com.sadellie.unitto.core.ui.common.SearchBar
|
import com.sadellie.unitto.core.ui.common.SearchBar
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.converter.UnitSearchResultItem
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.database.UnitsEntity
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
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.UnitsList
|
import com.sadellie.unitto.feature.converter.components.UnitsList
|
||||||
@ -50,7 +49,7 @@ import java.math.BigDecimal
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun UnitFromSelectorRoute(
|
internal fun UnitFromSelectorRoute(
|
||||||
unitSelectorViewModel: UnitSelectorViewModel,
|
unitSelectorViewModel: UnitFromSelectorViewModel,
|
||||||
converterViewModel: ConverterViewModel,
|
converterViewModel: ConverterViewModel,
|
||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
navigateToUnitGroups: () -> Unit,
|
navigateToUnitGroups: () -> Unit,
|
||||||
@ -62,7 +61,7 @@ internal fun UnitFromSelectorRoute(
|
|||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
onQueryChange = unitSelectorViewModel::updateSelectorQuery,
|
onQueryChange = unitSelectorViewModel::updateSelectorQuery,
|
||||||
toggleFavoritesOnly = unitSelectorViewModel::updateShowFavoritesOnly,
|
toggleFavoritesOnly = unitSelectorViewModel::updateShowFavoritesOnly,
|
||||||
updateUnitFrom = converterViewModel::updateUnitFrom,
|
updateUnitFrom = converterViewModel::updateUnitFromId,
|
||||||
updateUnitGroup = unitSelectorViewModel::updateSelectedUnitGroup,
|
updateUnitGroup = unitSelectorViewModel::updateSelectedUnitGroup,
|
||||||
favoriteUnit = unitSelectorViewModel::favoriteUnit,
|
favoriteUnit = unitSelectorViewModel::favoriteUnit,
|
||||||
navigateUp = navigateUp,
|
navigateUp = navigateUp,
|
||||||
@ -77,25 +76,14 @@ private fun UnitFromSelectorScreen(
|
|||||||
uiState: UnitSelectorUIState.UnitFrom,
|
uiState: UnitSelectorUIState.UnitFrom,
|
||||||
onQueryChange: (TextFieldValue) -> Unit,
|
onQueryChange: (TextFieldValue) -> Unit,
|
||||||
toggleFavoritesOnly: (Boolean) -> Unit,
|
toggleFavoritesOnly: (Boolean) -> Unit,
|
||||||
updateUnitFrom: (AbstractUnit) -> Unit,
|
updateUnitFrom: (String) -> Unit,
|
||||||
updateUnitGroup: (UnitGroup?) -> Unit,
|
updateUnitGroup: (UnitGroup?) -> Unit,
|
||||||
favoriteUnit: (AbstractUnit) -> Unit,
|
favoriteUnit: (UnitSearchResultItem) -> Unit,
|
||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
navigateToUnitGroups: () -> Unit,
|
navigateToUnitGroups: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior()
|
||||||
|
|
||||||
val chipsRowLazyListState = rememberLazyListState()
|
|
||||||
|
|
||||||
LaunchedEffect(uiState.unitFrom, uiState.shownUnitGroups) {
|
|
||||||
kotlin.runCatching {
|
|
||||||
val groupToSelect = uiState.shownUnitGroups.indexOf(uiState.unitFrom.group)
|
|
||||||
if (groupToSelect > -1) {
|
|
||||||
chipsRowLazyListState.scrollToItem(groupToSelect)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
@ -127,15 +115,16 @@ private fun UnitFromSelectorScreen(
|
|||||||
},
|
},
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
val resources = LocalContext.current.resources
|
val resources = LocalContext.current.resources
|
||||||
|
|
||||||
UnitsList(
|
UnitsList(
|
||||||
modifier = Modifier.padding(paddingValues),
|
modifier = Modifier.padding(paddingValues),
|
||||||
searchResult = uiState.units,
|
searchResult = uiState.units,
|
||||||
navigateToUnitGroups = navigateToUnitGroups,
|
navigateToUnitGroups = navigateToUnitGroups,
|
||||||
currentUnitId = uiState.unitFrom.id,
|
currentUnitId = uiState.unitFromId,
|
||||||
supportLabel = { resources.getString(it.shortName) },
|
supportLabel = { resources.getString(it.basicUnit.shortName) },
|
||||||
onClick = {
|
onClick = {
|
||||||
onQueryChange(TextFieldValue())
|
onQueryChange(TextFieldValue())
|
||||||
updateUnitFrom(it)
|
updateUnitFrom(it.basicUnit.id)
|
||||||
navigateUp()
|
navigateUp()
|
||||||
},
|
},
|
||||||
favoriteUnit = { favoriteUnit(it) },
|
favoriteUnit = { favoriteUnit(it) },
|
||||||
@ -146,7 +135,7 @@ private fun UnitFromSelectorScreen(
|
|||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun UnitFromSelectorScreenPreview() {
|
private fun UnitFromSelectorScreenPreview() {
|
||||||
val units: Map<UnitGroup, List<AbstractUnit>> = mapOf(
|
val units: Map<UnitGroup, List<UnitSearchResultItem>> = mapOf(
|
||||||
UnitGroup.LENGTH to listOf(
|
UnitGroup.LENGTH to listOf(
|
||||||
NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short),
|
NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short),
|
||||||
NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short),
|
NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short),
|
||||||
@ -155,14 +144,15 @@ private fun UnitFromSelectorScreenPreview() {
|
|||||||
NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short),
|
NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short),
|
||||||
NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short),
|
NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short),
|
||||||
NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short),
|
NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short),
|
||||||
),
|
)
|
||||||
|
.map { UnitSearchResultItem(it, UnitsEntity(unitId = it.id), null) },
|
||||||
)
|
)
|
||||||
|
|
||||||
UnitFromSelectorScreen(
|
UnitFromSelectorScreen(
|
||||||
uiState = UnitSelectorUIState.UnitFrom(
|
uiState = UnitSelectorUIState.UnitFrom(
|
||||||
unitFrom = units.values.first().first(),
|
unitFromId = UnitID.kilometer,
|
||||||
query = TextFieldValue("test"),
|
query = TextFieldValue("test"),
|
||||||
units = UnitSearchResult.Success(units),
|
units = units,
|
||||||
selectedUnitGroup = UnitGroup.SPEED,
|
selectedUnitGroup = UnitGroup.SPEED,
|
||||||
shownUnitGroups = UnitGroup.entries,
|
shownUnitGroups = UnitGroup.entries,
|
||||||
showFavoritesOnly = false,
|
showFavoritesOnly = false,
|
||||||
|
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
* Unitto is a calculator for Android
|
||||||
|
* Copyright (c) 2024 Elshan Agaev
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sadellie.unitto.feature.converter
|
||||||
|
|
||||||
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
|
import androidx.lifecycle.SavedStateHandle
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
|
import com.sadellie.unitto.data.converter.UnitSearchResultItem
|
||||||
|
import com.sadellie.unitto.data.converter.UnitsRepositoryImpl
|
||||||
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
|
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
||||||
|
import com.sadellie.unitto.feature.converter.navigation.UNIT_FROM_ID_ARG
|
||||||
|
import com.sadellie.unitto.feature.converter.navigation.UNIT_GROUP_ARG
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
internal class UnitFromSelectorViewModel @Inject constructor(
|
||||||
|
private val userPrefsRepository: UserPreferencesRepository,
|
||||||
|
private val unitsRepo: UnitsRepositoryImpl,
|
||||||
|
savedStateHandle: SavedStateHandle,
|
||||||
|
) : ViewModel() {
|
||||||
|
private var searchJob: Job? = null
|
||||||
|
|
||||||
|
private val query = MutableStateFlow(TextFieldValue())
|
||||||
|
private val searchResults = MutableStateFlow<Map<UnitGroup, List<UnitSearchResultItem>>?>(null)
|
||||||
|
private val selectedUnitGroup = MutableStateFlow(savedStateHandle.get<UnitGroup>(UNIT_GROUP_ARG))
|
||||||
|
private val unitFromId = savedStateHandle.get<String>(UNIT_FROM_ID_ARG)
|
||||||
|
|
||||||
|
val unitFromUIState: StateFlow<UnitSelectorUIState> = combine(
|
||||||
|
query,
|
||||||
|
searchResults,
|
||||||
|
selectedUnitGroup,
|
||||||
|
userPrefsRepository.converterPrefs,
|
||||||
|
) { query, searchResults, selectedUnitGroup, prefs ->
|
||||||
|
if (searchResults == null) return@combine UnitSelectorUIState.Loading
|
||||||
|
|
||||||
|
return@combine UnitSelectorUIState.UnitFrom(
|
||||||
|
query = query,
|
||||||
|
unitFromId = unitFromId ?: "",
|
||||||
|
shownUnitGroups = prefs.shownUnitGroups,
|
||||||
|
showFavoritesOnly = prefs.unitConverterFavoritesOnly,
|
||||||
|
units = searchResults,
|
||||||
|
selectedUnitGroup = selectedUnitGroup,
|
||||||
|
sorting = prefs.unitConverterSorting,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.stateIn(viewModelScope, UnitSelectorUIState.Loading)
|
||||||
|
|
||||||
|
fun updateSelectorQuery(value: TextFieldValue) {
|
||||||
|
query.update { value }
|
||||||
|
onSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateShowFavoritesOnly(value: Boolean) = viewModelScope.launch {
|
||||||
|
userPrefsRepository.updateUnitConverterFavoritesOnly(value)
|
||||||
|
onSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateSelectedUnitGroup(value: UnitGroup?) {
|
||||||
|
selectedUnitGroup.update { value }
|
||||||
|
onSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun favoriteUnit(unit: UnitSearchResultItem) = viewModelScope.launch {
|
||||||
|
unitsRepo.favorite(unit.basicUnit.id)
|
||||||
|
onSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onSearch() {
|
||||||
|
searchJob?.cancel()
|
||||||
|
searchJob = viewModelScope.launch {
|
||||||
|
val prefs = userPrefsRepository.converterPrefs.first()
|
||||||
|
val selectedGroupValue = selectedUnitGroup.value
|
||||||
|
val result = unitsRepo.filterUnits(
|
||||||
|
query = query.value.text,
|
||||||
|
favoritesOnly = prefs.unitConverterFavoritesOnly,
|
||||||
|
sorting = prefs.unitConverterSorting,
|
||||||
|
unitGroups = if (selectedGroupValue == null) {
|
||||||
|
prefs.shownUnitGroups
|
||||||
|
} else {
|
||||||
|
listOf(selectedGroupValue)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
searchResults.update { result }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
onSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
viewModelScope.cancel()
|
||||||
|
}
|
||||||
|
}
|
@ -20,29 +20,30 @@ 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.FormatterSymbols
|
import com.sadellie.unitto.core.base.FormatterSymbols
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.converter.UnitSearchResultItem
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
|
import com.sadellie.unitto.data.model.converter.unit.BasicUnit
|
||||||
|
|
||||||
internal sealed class UnitSelectorUIState {
|
internal sealed class UnitSelectorUIState {
|
||||||
data object Loading : UnitSelectorUIState()
|
data object Loading : UnitSelectorUIState()
|
||||||
|
|
||||||
data class UnitFrom(
|
data class UnitFrom(
|
||||||
val query: TextFieldValue,
|
val query: TextFieldValue,
|
||||||
val unitFrom: AbstractUnit,
|
val unitFromId: String,
|
||||||
val shownUnitGroups: List<UnitGroup>,
|
val shownUnitGroups: List<UnitGroup>,
|
||||||
val showFavoritesOnly: Boolean,
|
val showFavoritesOnly: Boolean,
|
||||||
val units: UnitSearchResult,
|
val units: Map<UnitGroup, List<UnitSearchResultItem>>,
|
||||||
val selectedUnitGroup: UnitGroup?,
|
val selectedUnitGroup: UnitGroup?,
|
||||||
val sorting: UnitsListSorting,
|
val sorting: UnitsListSorting,
|
||||||
) : UnitSelectorUIState()
|
) : UnitSelectorUIState()
|
||||||
|
|
||||||
data class UnitTo(
|
data class UnitTo(
|
||||||
val query: TextFieldValue,
|
val query: TextFieldValue,
|
||||||
val unitFrom: AbstractUnit,
|
val unitFrom: BasicUnit,
|
||||||
val unitTo: AbstractUnit,
|
val unitTo: BasicUnit,
|
||||||
val showFavoritesOnly: Boolean,
|
val showFavoritesOnly: Boolean,
|
||||||
val units: UnitSearchResult,
|
val units: Map<UnitGroup, List<UnitSearchResultItem>>,
|
||||||
val input: String?,
|
val input: String?,
|
||||||
val sorting: UnitsListSorting,
|
val sorting: UnitsListSorting,
|
||||||
val scale: Int,
|
val scale: Int,
|
||||||
@ -50,13 +51,3 @@ internal sealed class UnitSelectorUIState {
|
|||||||
val formatterSymbols: FormatterSymbols,
|
val formatterSymbols: FormatterSymbols,
|
||||||
) : UnitSelectorUIState()
|
) : UnitSelectorUIState()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class UnitSearchResult {
|
|
||||||
data object Empty : UnitSearchResult()
|
|
||||||
|
|
||||||
data object Loading : UnitSearchResult()
|
|
||||||
|
|
||||||
data class Success(
|
|
||||||
val units: Map<UnitGroup, List<AbstractUnit>>,
|
|
||||||
) : UnitSearchResult()
|
|
||||||
}
|
|
||||||
|
@ -36,20 +36,21 @@ import com.sadellie.unitto.core.ui.common.EmptyScreen
|
|||||||
import com.sadellie.unitto.core.ui.common.SearchBar
|
import com.sadellie.unitto.core.ui.common.SearchBar
|
||||||
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.converter.DefaultBatchConvertResult
|
||||||
|
import com.sadellie.unitto.data.converter.NumberBaseBatchConvertResult
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.converter.UnitSearchResultItem
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.database.UnitsEntity
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.DefaultUnit
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import com.sadellie.unitto.data.model.unit.NumberBaseUnit
|
|
||||||
import com.sadellie.unitto.feature.converter.components.FavoritesButton
|
import com.sadellie.unitto.feature.converter.components.FavoritesButton
|
||||||
import com.sadellie.unitto.feature.converter.components.UnitsList
|
import com.sadellie.unitto.feature.converter.components.UnitsList
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun UnitToSelectorRoute(
|
internal fun UnitToSelectorRoute(
|
||||||
unitSelectorViewModel: UnitSelectorViewModel,
|
unitSelectorViewModel: UnitToSelectorViewModel,
|
||||||
converterViewModel: ConverterViewModel,
|
converterViewModel: ConverterViewModel,
|
||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
navigateToUnitGroups: () -> Unit,
|
navigateToUnitGroups: () -> Unit,
|
||||||
@ -61,7 +62,7 @@ internal fun UnitToSelectorRoute(
|
|||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
onQueryChange = unitSelectorViewModel::updateSelectorQuery,
|
onQueryChange = unitSelectorViewModel::updateSelectorQuery,
|
||||||
toggleFavoritesOnly = unitSelectorViewModel::updateShowFavoritesOnly,
|
toggleFavoritesOnly = unitSelectorViewModel::updateShowFavoritesOnly,
|
||||||
updateUnitTo = converterViewModel::updateUnitTo,
|
updateUnitTo = converterViewModel::updateUnitToId,
|
||||||
favoriteUnit = unitSelectorViewModel::favoriteUnit,
|
favoriteUnit = unitSelectorViewModel::favoriteUnit,
|
||||||
navigateUp = navigateUp,
|
navigateUp = navigateUp,
|
||||||
navigateToUnitGroups = navigateToUnitGroups,
|
navigateToUnitGroups = navigateToUnitGroups,
|
||||||
@ -75,8 +76,8 @@ private fun UnitToSelectorScreen(
|
|||||||
uiState: UnitSelectorUIState.UnitTo,
|
uiState: UnitSelectorUIState.UnitTo,
|
||||||
onQueryChange: (TextFieldValue) -> Unit,
|
onQueryChange: (TextFieldValue) -> Unit,
|
||||||
toggleFavoritesOnly: (Boolean) -> Unit,
|
toggleFavoritesOnly: (Boolean) -> Unit,
|
||||||
updateUnitTo: (AbstractUnit) -> Unit,
|
updateUnitTo: (String) -> Unit,
|
||||||
favoriteUnit: (AbstractUnit) -> Unit,
|
favoriteUnit: (UnitSearchResultItem) -> Unit,
|
||||||
navigateUp: () -> Unit,
|
navigateUp: () -> Unit,
|
||||||
navigateToUnitGroups: () -> Unit,
|
navigateToUnitGroups: () -> Unit,
|
||||||
) {
|
) {
|
||||||
@ -105,19 +106,25 @@ private fun UnitToSelectorScreen(
|
|||||||
navigateToUnitGroups = navigateToUnitGroups,
|
navigateToUnitGroups = navigateToUnitGroups,
|
||||||
currentUnitId = uiState.unitTo.id,
|
currentUnitId = uiState.unitTo.id,
|
||||||
supportLabel = {
|
supportLabel = {
|
||||||
formatUnitToSupportLabel(
|
val label = resources.getString(it.basicUnit.shortName)
|
||||||
unitFrom = uiState.unitFrom,
|
|
||||||
unitTo = it,
|
when (val conversion = it.conversion) {
|
||||||
input = uiState.input,
|
is DefaultBatchConvertResult -> {
|
||||||
shortName = resources.getString(it.shortName),
|
val formattedConversion = conversion.value
|
||||||
scale = uiState.scale,
|
.format(uiState.scale, uiState.outputFormat)
|
||||||
outputFormat = uiState.outputFormat,
|
.formatExpression(uiState.formatterSymbols)
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
|
||||||
)
|
"$formattedConversion $label"
|
||||||
|
}
|
||||||
|
is NumberBaseBatchConvertResult -> {
|
||||||
|
"${conversion.value} $label"
|
||||||
|
}
|
||||||
|
else -> label
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
onQueryChange(TextFieldValue())
|
onQueryChange(TextFieldValue())
|
||||||
updateUnitTo(it)
|
updateUnitTo(it.basicUnit.id)
|
||||||
navigateUp()
|
navigateUp()
|
||||||
},
|
},
|
||||||
favoriteUnit = { favoriteUnit(it) },
|
favoriteUnit = { favoriteUnit(it) },
|
||||||
@ -125,49 +132,10 @@ private fun UnitToSelectorScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun formatUnitToSupportLabel(
|
|
||||||
unitFrom: AbstractUnit?,
|
|
||||||
unitTo: AbstractUnit?,
|
|
||||||
input: String?,
|
|
||||||
shortName: String,
|
|
||||||
scale: Int,
|
|
||||||
outputFormat: Int,
|
|
||||||
formatterSymbols: FormatterSymbols,
|
|
||||||
): String {
|
|
||||||
if (input.isNullOrEmpty()) return shortName
|
|
||||||
|
|
||||||
try {
|
|
||||||
if ((unitFrom is DefaultUnit) and (unitTo is DefaultUnit)) {
|
|
||||||
unitFrom as DefaultUnit
|
|
||||||
unitTo as DefaultUnit
|
|
||||||
|
|
||||||
val conversion = unitFrom
|
|
||||||
.convert(unitTo, BigDecimal(input))
|
|
||||||
.format(scale, outputFormat)
|
|
||||||
.formatExpression(formatterSymbols)
|
|
||||||
|
|
||||||
return "$conversion $shortName"
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((unitFrom is NumberBaseUnit) and (unitTo is NumberBaseUnit)) {
|
|
||||||
unitFrom as NumberBaseUnit
|
|
||||||
unitTo as NumberBaseUnit
|
|
||||||
|
|
||||||
val conversion = unitFrom.convert(unitTo, input).uppercase()
|
|
||||||
|
|
||||||
return "$conversion $shortName"
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {
|
|
||||||
return shortName
|
|
||||||
}
|
|
||||||
|
|
||||||
return shortName
|
|
||||||
}
|
|
||||||
|
|
||||||
@Preview
|
@Preview
|
||||||
@Composable
|
@Composable
|
||||||
private fun UnitToSelectorPreview() {
|
private fun UnitToSelectorPreview() {
|
||||||
val units: Map<UnitGroup, List<AbstractUnit>> = mapOf(
|
val units: Map<UnitGroup, List<UnitSearchResultItem>> = mapOf(
|
||||||
UnitGroup.LENGTH to listOf(
|
UnitGroup.LENGTH to listOf(
|
||||||
NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short),
|
NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short),
|
||||||
NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short),
|
NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short),
|
||||||
@ -176,15 +144,16 @@ private fun UnitToSelectorPreview() {
|
|||||||
NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short),
|
NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short),
|
||||||
NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short),
|
NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short),
|
||||||
NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short),
|
NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short),
|
||||||
),
|
)
|
||||||
|
.map { UnitSearchResultItem(it, UnitsEntity(unitId = it.id), null) },
|
||||||
)
|
)
|
||||||
|
|
||||||
UnitToSelectorScreen(
|
UnitToSelectorScreen(
|
||||||
uiState = UnitSelectorUIState.UnitTo(
|
uiState = UnitSelectorUIState.UnitTo(
|
||||||
unitFrom = units.values.first().first(),
|
unitFrom = units.values.first().first().basicUnit,
|
||||||
unitTo = units.values.first().first(),
|
unitTo = units.values.first().first().basicUnit,
|
||||||
query = TextFieldValue("test"),
|
query = TextFieldValue("test"),
|
||||||
units = UnitSearchResult.Success(units),
|
units = units,
|
||||||
showFavoritesOnly = false,
|
showFavoritesOnly = false,
|
||||||
sorting = UnitsListSorting.USAGE,
|
sorting = UnitsListSorting.USAGE,
|
||||||
input = "100",
|
input = "100",
|
||||||
|
@ -23,83 +23,48 @@ import androidx.lifecycle.SavedStateHandle
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.converter.UnitSearchResultItem
|
||||||
import com.sadellie.unitto.data.model.repository.UnitsRepository
|
import com.sadellie.unitto.data.converter.UnitsRepositoryImpl
|
||||||
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
|
||||||
import com.sadellie.unitto.feature.converter.navigation.INPUT_ARG
|
import com.sadellie.unitto.feature.converter.navigation.INPUT_ARG
|
||||||
import com.sadellie.unitto.feature.converter.navigation.UNIT_FROM_ID_ARG
|
import com.sadellie.unitto.feature.converter.navigation.UNIT_FROM_ID_ARG
|
||||||
import com.sadellie.unitto.feature.converter.navigation.UNIT_GROUP_ARG
|
import com.sadellie.unitto.feature.converter.navigation.UNIT_GROUP_ARG
|
||||||
import com.sadellie.unitto.feature.converter.navigation.UNIT_TO_ID_ARG
|
import com.sadellie.unitto.feature.converter.navigation.UNIT_TO_ID_ARG
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.mapLatest
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
internal class UnitSelectorViewModel @Inject constructor(
|
internal class UnitToSelectorViewModel @Inject constructor(
|
||||||
private val userPrefsRepository: UserPreferencesRepository,
|
private val userPrefsRepository: UserPreferencesRepository,
|
||||||
private val unitsRepo: UnitsRepository,
|
private val unitsRepo: UnitsRepositoryImpl,
|
||||||
savedStateHandle: SavedStateHandle,
|
savedStateHandle: SavedStateHandle,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
private var searchJob: Job? = null
|
||||||
|
|
||||||
private val query = MutableStateFlow(TextFieldValue())
|
private val query = MutableStateFlow(TextFieldValue())
|
||||||
private val searchResults = MutableStateFlow<UnitSearchResult>(UnitSearchResult.Loading)
|
private val searchResults = MutableStateFlow<Map<UnitGroup, List<UnitSearchResultItem>>?>(null)
|
||||||
private val selectedUnitGroup = MutableStateFlow(savedStateHandle.get<UnitGroup>(UNIT_GROUP_ARG))
|
private val selectedUnitGroup = MutableStateFlow(savedStateHandle.get<UnitGroup>(UNIT_GROUP_ARG))
|
||||||
private val unitFromId = savedStateHandle.get<String>(UNIT_FROM_ID_ARG)
|
private val unitFromId = savedStateHandle.get<String>(UNIT_FROM_ID_ARG)
|
||||||
private val unitToId = savedStateHandle.get<String>(UNIT_TO_ID_ARG)
|
private val unitToId = savedStateHandle.get<String>(UNIT_TO_ID_ARG)
|
||||||
private val input = savedStateHandle.get<String>(INPUT_ARG)
|
private val input = savedStateHandle.get<String>(INPUT_ARG)
|
||||||
|
|
||||||
val unitFromUIState: StateFlow<UnitSelectorUIState> = combine(
|
|
||||||
query,
|
|
||||||
searchResults,
|
|
||||||
selectedUnitGroup,
|
|
||||||
userPrefsRepository.converterPrefs,
|
|
||||||
) { query, searchResults, selectedUnitGroup, prefs ->
|
|
||||||
if (unitFromId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading
|
|
||||||
|
|
||||||
return@combine UnitSelectorUIState.UnitFrom(
|
|
||||||
query = query,
|
|
||||||
unitFrom = unitsRepo.getById(unitFromId),
|
|
||||||
shownUnitGroups = prefs.shownUnitGroups,
|
|
||||||
showFavoritesOnly = prefs.unitConverterFavoritesOnly,
|
|
||||||
units = searchResults,
|
|
||||||
selectedUnitGroup = selectedUnitGroup,
|
|
||||||
sorting = prefs.unitConverterSorting,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
.mapLatest { ui ->
|
|
||||||
if (ui is UnitSelectorUIState.UnitFrom) {
|
|
||||||
searchResults.update {
|
|
||||||
val result = unitsRepo.filterUnits(
|
|
||||||
query = ui.query.text,
|
|
||||||
unitGroup = ui.selectedUnitGroup,
|
|
||||||
favoritesOnly = ui.showFavoritesOnly,
|
|
||||||
hideBrokenUnits = false,
|
|
||||||
sorting = ui.sorting,
|
|
||||||
shownUnitGroups = ui.shownUnitGroups,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (result.isEmpty()) UnitSearchResult.Empty else UnitSearchResult.Success(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ui
|
|
||||||
}
|
|
||||||
.stateIn(viewModelScope, UnitSelectorUIState.Loading)
|
|
||||||
|
|
||||||
val unitToUIState: StateFlow<UnitSelectorUIState> = combine(
|
val unitToUIState: StateFlow<UnitSelectorUIState> = combine(
|
||||||
query,
|
query,
|
||||||
searchResults,
|
searchResults,
|
||||||
userPrefsRepository.converterPrefs,
|
userPrefsRepository.converterPrefs,
|
||||||
unitsRepo.units,
|
) { query, searchResults, prefs ->
|
||||||
) { query, searchResults, prefs, _ ->
|
|
||||||
if (unitFromId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading
|
if (unitFromId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading
|
||||||
if (unitToId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading
|
if (unitToId.isNullOrEmpty()) return@combine UnitSelectorUIState.Loading
|
||||||
|
if (searchResults == null) return@combine UnitSelectorUIState.Loading
|
||||||
|
|
||||||
UnitSelectorUIState.UnitTo(
|
UnitSelectorUIState.UnitTo(
|
||||||
query = query,
|
query = query,
|
||||||
@ -113,36 +78,47 @@ internal class UnitSelectorViewModel @Inject constructor(
|
|||||||
outputFormat = prefs.outputFormat,
|
outputFormat = prefs.outputFormat,
|
||||||
formatterSymbols = prefs.formatterSymbols,
|
formatterSymbols = prefs.formatterSymbols,
|
||||||
)
|
)
|
||||||
}
|
|
||||||
.mapLatest { ui ->
|
|
||||||
if (ui is UnitSelectorUIState.UnitTo) {
|
|
||||||
searchResults.update {
|
|
||||||
if (ui.unitFrom.group == UnitGroup.CURRENCY) unitsRepo.updateRates(ui.unitFrom)
|
|
||||||
|
|
||||||
val result = unitsRepo.filterUnits(
|
|
||||||
query = ui.query.text,
|
|
||||||
unitGroup = ui.unitFrom.group,
|
|
||||||
favoritesOnly = ui.showFavoritesOnly,
|
|
||||||
hideBrokenUnits = true,
|
|
||||||
sorting = ui.sorting,
|
|
||||||
)
|
|
||||||
|
|
||||||
if (result.isEmpty()) UnitSearchResult.Empty else UnitSearchResult.Success(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ui
|
|
||||||
}
|
}
|
||||||
.stateIn(viewModelScope, UnitSelectorUIState.Loading)
|
.stateIn(viewModelScope, UnitSelectorUIState.Loading)
|
||||||
|
|
||||||
fun updateSelectorQuery(value: TextFieldValue) = query.update { value }
|
fun updateSelectorQuery(value: TextFieldValue) {
|
||||||
|
query.update { value }
|
||||||
|
onSearch()
|
||||||
|
}
|
||||||
|
|
||||||
fun updateShowFavoritesOnly(value: Boolean) = viewModelScope.launch {
|
fun updateShowFavoritesOnly(value: Boolean) = viewModelScope.launch {
|
||||||
userPrefsRepository.updateUnitConverterFavoritesOnly(value)
|
userPrefsRepository.updateUnitConverterFavoritesOnly(value)
|
||||||
|
onSearch()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateSelectedUnitGroup(value: UnitGroup?) = selectedUnitGroup.update { value }
|
fun favoriteUnit(unit: UnitSearchResultItem) = viewModelScope.launch {
|
||||||
|
unitsRepo.favorite(unit.basicUnit.id)
|
||||||
|
onSearch()
|
||||||
|
}
|
||||||
|
|
||||||
fun favoriteUnit(unit: AbstractUnit) = viewModelScope.launch(Dispatchers.IO) {
|
private fun onSearch() {
|
||||||
unitsRepo.favorite(unit)
|
searchJob?.cancel()
|
||||||
|
searchJob = viewModelScope.launch {
|
||||||
|
val prefs = userPrefsRepository.converterPrefs.first()
|
||||||
|
val result = unitsRepo.filterUnitsAndBatchConvert(
|
||||||
|
query = query.value.text,
|
||||||
|
unitGroup = selectedUnitGroup.value ?: return@launch,
|
||||||
|
favoritesOnly = prefs.unitConverterFavoritesOnly,
|
||||||
|
sorting = prefs.unitConverterSorting,
|
||||||
|
unitFromId = unitFromId ?: return@launch,
|
||||||
|
input = input,
|
||||||
|
)
|
||||||
|
|
||||||
|
searchResults.update { result }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
onSearch()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCleared() {
|
||||||
|
super.onCleared()
|
||||||
|
viewModelScope.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -48,7 +48,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.core.ui.common.AssistChip
|
import com.sadellie.unitto.core.ui.common.AssistChip
|
||||||
import com.sadellie.unitto.core.ui.common.FilterChip
|
import com.sadellie.unitto.core.ui.common.FilterChip
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Row of chips with [UnitGroup]s. Temporary solution
|
* Row of chips with [UnitGroup]s. Temporary solution
|
||||||
|
@ -24,7 +24,7 @@ import androidx.compose.ui.Modifier
|
|||||||
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 com.sadellie.unitto.core.ui.common.Header
|
import com.sadellie.unitto.core.ui.common.Header
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun UnitGroupHeader(modifier: Modifier, unitGroup: UnitGroup) {
|
internal fun UnitGroupHeader(modifier: Modifier, unitGroup: UnitGroup) {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
package com.sadellie.unitto.feature.converter.components
|
package com.sadellie.unitto.feature.converter.components
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
@ -30,57 +31,55 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.core.ui.common.SearchPlaceholder
|
import com.sadellie.unitto.core.ui.common.SearchPlaceholder
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.converter.UnitSearchResultItem
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.database.UnitsEntity
|
||||||
import com.sadellie.unitto.data.model.unit.NormalUnit
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.feature.converter.UnitSearchResult
|
import com.sadellie.unitto.data.model.converter.unit.NormalUnit
|
||||||
import java.math.BigDecimal
|
import java.math.BigDecimal
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun UnitsList(
|
internal fun UnitsList(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
searchResult: UnitSearchResult,
|
searchResult: Map<UnitGroup, List<UnitSearchResultItem>>,
|
||||||
navigateToUnitGroups: () -> Unit,
|
navigateToUnitGroups: () -> Unit,
|
||||||
currentUnitId: String,
|
currentUnitId: String,
|
||||||
supportLabel: (AbstractUnit) -> String,
|
supportLabel: (UnitSearchResultItem) -> String,
|
||||||
onClick: (AbstractUnit) -> Unit,
|
onClick: (UnitSearchResultItem) -> Unit,
|
||||||
favoriteUnit: (AbstractUnit) -> Unit,
|
favoriteUnit: (UnitSearchResultItem) -> Unit,
|
||||||
) {
|
) {
|
||||||
Crossfade(
|
Crossfade(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
targetState = searchResult,
|
targetState = searchResult,
|
||||||
label = "Units list",
|
label = "Units list",
|
||||||
|
animationSpec = tween(200),
|
||||||
) { result ->
|
) { result ->
|
||||||
when (result) {
|
when {
|
||||||
is UnitSearchResult.Success -> LazyColumn(
|
result.isEmpty() -> SearchPlaceholder(
|
||||||
|
onButtonClick = navigateToUnitGroups,
|
||||||
|
supportText = stringResource(R.string.converter_no_results_support),
|
||||||
|
buttonLabel = stringResource(R.string.open_settings_label),
|
||||||
|
)
|
||||||
|
else -> LazyColumn(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
) {
|
||||||
result.units.forEach { (group, units) ->
|
result.forEach { (group, units) ->
|
||||||
item(group.name) {
|
item(group.name) {
|
||||||
UnitGroupHeader(Modifier.animateItemPlacement(), group)
|
UnitGroupHeader(Modifier.animateItemPlacement(), group)
|
||||||
}
|
}
|
||||||
|
|
||||||
items(units, { it.id }) {
|
items(units, { it.basicUnit.id }) {
|
||||||
BasicUnitListItem(
|
BasicUnitListItem(
|
||||||
modifier = Modifier.animateItemPlacement(),
|
modifier = Modifier.animateItemPlacement(),
|
||||||
name = stringResource(it.displayName),
|
name = stringResource(it.basicUnit.displayName),
|
||||||
supportLabel = supportLabel(it),
|
supportLabel = supportLabel(it),
|
||||||
isFavorite = it.isFavorite,
|
isFavorite = it.stats.isFavorite,
|
||||||
isSelected = it.id == currentUnitId,
|
isSelected = it.basicUnit.id == currentUnitId,
|
||||||
onClick = { onClick(it) },
|
onClick = { onClick(it) },
|
||||||
favoriteUnit = { favoriteUnit(it) },
|
favoriteUnit = { favoriteUnit(it) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
UnitSearchResult.Empty -> SearchPlaceholder(
|
|
||||||
onButtonClick = navigateToUnitGroups,
|
|
||||||
supportText = stringResource(R.string.converter_no_results_support),
|
|
||||||
buttonLabel = stringResource(R.string.open_settings_label),
|
|
||||||
)
|
|
||||||
|
|
||||||
UnitSearchResult.Loading -> Unit
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,7 +88,7 @@ internal fun UnitsList(
|
|||||||
@Composable
|
@Composable
|
||||||
private fun PreviewUnitsList() {
|
private fun PreviewUnitsList() {
|
||||||
val resources = LocalContext.current.resources
|
val resources = LocalContext.current.resources
|
||||||
val groupedUnits: Map<UnitGroup, List<AbstractUnit>> = mapOf(
|
val units: Map<UnitGroup, List<UnitSearchResultItem>> = mapOf(
|
||||||
UnitGroup.LENGTH to listOf(
|
UnitGroup.LENGTH to listOf(
|
||||||
NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short),
|
NormalUnit(UnitID.meter, BigDecimal("1000000000000000000"), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short),
|
||||||
NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short),
|
NormalUnit(UnitID.kilometer, BigDecimal("1000000000000000000000"), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short),
|
||||||
@ -98,15 +97,16 @@ private fun PreviewUnitsList() {
|
|||||||
NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short),
|
NormalUnit(UnitID.foot, BigDecimal("304800000000000000"), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short),
|
||||||
NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short),
|
NormalUnit(UnitID.yard, BigDecimal("914400000000000000"), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short),
|
||||||
NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short),
|
NormalUnit(UnitID.mile, BigDecimal("1609344000000000000000"), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short),
|
||||||
),
|
)
|
||||||
|
.map { UnitSearchResultItem(it, UnitsEntity(unitId = it.id), null) },
|
||||||
)
|
)
|
||||||
|
|
||||||
UnitsList(
|
UnitsList(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
searchResult = UnitSearchResult.Success(units = groupedUnits),
|
searchResult = units,
|
||||||
navigateToUnitGroups = {},
|
navigateToUnitGroups = {},
|
||||||
currentUnitId = UnitID.mile,
|
currentUnitId = UnitID.mile,
|
||||||
supportLabel = { resources.getString(it.shortName) },
|
supportLabel = { resources.getString(it.basicUnit.shortName) },
|
||||||
onClick = {},
|
onClick = {},
|
||||||
favoriteUnit = {},
|
favoriteUnit = {},
|
||||||
)
|
)
|
||||||
|
@ -28,11 +28,9 @@ import androidx.navigation.navDeepLink
|
|||||||
import com.sadellie.unitto.core.ui.model.DrawerItem
|
import com.sadellie.unitto.core.ui.model.DrawerItem
|
||||||
import com.sadellie.unitto.core.ui.unittoComposable
|
import com.sadellie.unitto.core.ui.unittoComposable
|
||||||
import com.sadellie.unitto.core.ui.unittoNavigation
|
import com.sadellie.unitto.core.ui.unittoNavigation
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.feature.converter.ConverterRoute
|
import com.sadellie.unitto.feature.converter.ConverterRoute
|
||||||
import com.sadellie.unitto.feature.converter.ConverterViewModel
|
import com.sadellie.unitto.feature.converter.ConverterViewModel
|
||||||
import com.sadellie.unitto.feature.converter.CurrencyRateUpdateState
|
|
||||||
import com.sadellie.unitto.feature.converter.UnitConverterUIState
|
|
||||||
import com.sadellie.unitto.feature.converter.UnitFromSelectorRoute
|
import com.sadellie.unitto.feature.converter.UnitFromSelectorRoute
|
||||||
import com.sadellie.unitto.feature.converter.UnitToSelectorRoute
|
import com.sadellie.unitto.feature.converter.UnitToSelectorRoute
|
||||||
|
|
||||||
@ -47,7 +45,7 @@ internal const val UNIT_TO_ID_ARG = "unitToIdArg"
|
|||||||
internal const val INPUT_ARG = "inputArg"
|
internal const val INPUT_ARG = "inputArg"
|
||||||
|
|
||||||
private const val UNIT_FROM_ROUTE = "$UNIT_FROM/{$UNIT_FROM_ID_ARG}/{$UNIT_GROUP_ARG}"
|
private const val UNIT_FROM_ROUTE = "$UNIT_FROM/{$UNIT_FROM_ID_ARG}/{$UNIT_GROUP_ARG}"
|
||||||
private const val UNIT_TO_ROUTE = "$UNIT_TO/{$UNIT_FROM_ID_ARG}/{$UNIT_TO_ID_ARG}/{$INPUT_ARG}"
|
private const val UNIT_TO_ROUTE = "$UNIT_TO/{$UNIT_FROM_ID_ARG}/{$UNIT_TO_ID_ARG}/{$UNIT_GROUP_ARG}/{$INPUT_ARG}"
|
||||||
private fun NavHostController.navigateLeft(
|
private fun NavHostController.navigateLeft(
|
||||||
unitFromId: String,
|
unitFromId: String,
|
||||||
unitGroup: UnitGroup,
|
unitGroup: UnitGroup,
|
||||||
@ -56,8 +54,9 @@ private fun NavHostController.navigateLeft(
|
|||||||
private fun NavHostController.navigateRight(
|
private fun NavHostController.navigateRight(
|
||||||
unitFromId: String,
|
unitFromId: String,
|
||||||
unitToId: String,
|
unitToId: String,
|
||||||
input: String?,
|
unitGroup: UnitGroup,
|
||||||
) = navigate("$UNIT_TO/$unitFromId/$unitToId/$input")
|
input: String,
|
||||||
|
) = navigate("$UNIT_TO/$unitFromId/$unitToId/$unitGroup/${input.ifEmpty { null }}")
|
||||||
|
|
||||||
fun NavGraphBuilder.converterGraph(
|
fun NavGraphBuilder.converterGraph(
|
||||||
openDrawer: () -> Unit,
|
openDrawer: () -> Unit,
|
||||||
@ -80,54 +79,8 @@ fun NavGraphBuilder.converterGraph(
|
|||||||
|
|
||||||
ConverterRoute(
|
ConverterRoute(
|
||||||
viewModel = parentViewModel,
|
viewModel = parentViewModel,
|
||||||
// Navigation logic is here, but should actually be in ConverterScreen
|
navigateToLeftScreen = navController::navigateLeft,
|
||||||
navigateToLeftScreen = { uiState: UnitConverterUIState ->
|
navigateToRightScreen = navController::navigateRight,
|
||||||
when (uiState) {
|
|
||||||
is UnitConverterUIState.Default ->
|
|
||||||
navController
|
|
||||||
.navigateLeft(uiState.unitFrom.id, uiState.unitFrom.group)
|
|
||||||
|
|
||||||
is UnitConverterUIState.NumberBase ->
|
|
||||||
navController
|
|
||||||
.navigateLeft(uiState.unitFrom.id, uiState.unitFrom.group)
|
|
||||||
|
|
||||||
else -> Unit
|
|
||||||
}
|
|
||||||
},
|
|
||||||
navigateToRightScreen = { uiState: UnitConverterUIState ->
|
|
||||||
when (uiState) {
|
|
||||||
is UnitConverterUIState.Default -> {
|
|
||||||
// Don't allow converting if still loading currencies
|
|
||||||
val convertingCurrencies = uiState.unitFrom.group == UnitGroup.CURRENCY
|
|
||||||
val currenciesReady =
|
|
||||||
uiState.currencyRateUpdateState is CurrencyRateUpdateState.Ready
|
|
||||||
|
|
||||||
val input: String? = if (convertingCurrencies and !currenciesReady) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
(uiState.calculation?.toPlainString() ?: uiState.input1.text)
|
|
||||||
.ifEmpty { null }
|
|
||||||
}
|
|
||||||
|
|
||||||
navController.navigateRight(
|
|
||||||
uiState.unitFrom.id,
|
|
||||||
uiState.unitTo.id,
|
|
||||||
input,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
is UnitConverterUIState.NumberBase -> {
|
|
||||||
val input = uiState.input.text.ifEmpty { null }
|
|
||||||
navController.navigateRight(
|
|
||||||
uiState.unitFrom.id,
|
|
||||||
uiState.unitTo.id,
|
|
||||||
input,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
UnitConverterUIState.Loading -> Unit
|
|
||||||
}
|
|
||||||
},
|
|
||||||
openDrawer = openDrawer,
|
openDrawer = openDrawer,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -166,6 +119,9 @@ fun NavGraphBuilder.converterGraph(
|
|||||||
navArgument(UNIT_TO_ID_ARG) {
|
navArgument(UNIT_TO_ID_ARG) {
|
||||||
type = NavType.StringType
|
type = NavType.StringType
|
||||||
},
|
},
|
||||||
|
navArgument(UNIT_GROUP_ARG) {
|
||||||
|
type = NavType.EnumType(UnitGroup::class.java)
|
||||||
|
},
|
||||||
navArgument(INPUT_ARG) {
|
navArgument(INPUT_ARG) {
|
||||||
type = NavType.StringType
|
type = NavType.StringType
|
||||||
nullable = true
|
nullable = true
|
||||||
|
@ -1,134 +0,0 @@
|
|||||||
/*
|
|
||||||
* Unitto is a calculator for Android
|
|
||||||
* Copyright (c) 2023-2024 Elshan Agaev
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.sadellie.unitto.feature.converter
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import com.sadellie.unitto.core.base.FormatterSymbols
|
|
||||||
import com.sadellie.unitto.core.base.Token
|
|
||||||
import org.junit.Assert
|
|
||||||
import org.junit.Test
|
|
||||||
import org.junit.runner.RunWith
|
|
||||||
import org.robolectric.RobolectricTestRunner
|
|
||||||
import org.robolectric.RuntimeEnvironment
|
|
||||||
import java.math.BigDecimal
|
|
||||||
|
|
||||||
@RunWith(RobolectricTestRunner::class)
|
|
||||||
class ConverterUIStateKtTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun format() {
|
|
||||||
val formatterSymbols = FormatterSymbols(Token.SPACE, Token.PERIOD)
|
|
||||||
var basicValue = BigDecimal("1")
|
|
||||||
val mContext: Context = RuntimeEnvironment.getApplication().applicationContext
|
|
||||||
|
|
||||||
fun String.formatTime() = formatTime(basicValue.multiply(BigDecimal(this)))
|
|
||||||
.format(mContext, formatterSymbols)
|
|
||||||
|
|
||||||
// Edgy things (minus, decimals and zeros)
|
|
||||||
Assert.assertEquals("−28as", "-28".formatTime())
|
|
||||||
Assert.assertEquals("−0.05as", "-0.05".formatTime())
|
|
||||||
Assert.assertEquals("0", "0".formatTime())
|
|
||||||
|
|
||||||
basicValue = BigDecimal("86400000000000000000000")
|
|
||||||
Assert.assertEquals("−28d", "-28".formatTime())
|
|
||||||
Assert.assertEquals("−1h 12m", "-0.05".formatTime())
|
|
||||||
Assert.assertEquals("0", "0".formatTime())
|
|
||||||
Assert.assertEquals("0", "-0".formatTime())
|
|
||||||
|
|
||||||
// DAYS
|
|
||||||
basicValue = BigDecimal("86400000000000000000000")
|
|
||||||
Assert.assertEquals("12h", "0.5".formatTime())
|
|
||||||
Assert.assertEquals("1h 12m", "0.05".formatTime())
|
|
||||||
Assert.assertEquals("7m 12s", "0.005".formatTime())
|
|
||||||
Assert.assertEquals("28d", "28".formatTime())
|
|
||||||
Assert.assertEquals("90d", "90".formatTime())
|
|
||||||
Assert.assertEquals("90d 12h", "90.5".formatTime())
|
|
||||||
Assert.assertEquals("90d 7m 12s", "90.005".formatTime())
|
|
||||||
|
|
||||||
// HOURS
|
|
||||||
basicValue = BigDecimal("3600000000000000000000")
|
|
||||||
Assert.assertEquals("30m", "0.5".formatTime())
|
|
||||||
Assert.assertEquals("3m", "0.05".formatTime())
|
|
||||||
Assert.assertEquals("18s", "0.005".formatTime())
|
|
||||||
Assert.assertEquals("1d 4h", "28".formatTime())
|
|
||||||
Assert.assertEquals("3d 18h", "90".formatTime())
|
|
||||||
Assert.assertEquals("3d 18h 30m", "90.5".formatTime())
|
|
||||||
Assert.assertEquals("3d 18h 18s", "90.005".formatTime())
|
|
||||||
|
|
||||||
// MINUTES
|
|
||||||
basicValue = BigDecimal("60000000000000000000")
|
|
||||||
Assert.assertEquals("30s", "0.5".formatTime())
|
|
||||||
Assert.assertEquals("3s", "0.05".formatTime())
|
|
||||||
Assert.assertEquals("300ms", "0.005".formatTime())
|
|
||||||
Assert.assertEquals("28m", "28".formatTime())
|
|
||||||
Assert.assertEquals("1h 30m", "90".formatTime())
|
|
||||||
Assert.assertEquals("1h 30m 30s", "90.5".formatTime())
|
|
||||||
Assert.assertEquals("1h 30m 300ms", "90.005".formatTime())
|
|
||||||
|
|
||||||
// SECONDS
|
|
||||||
basicValue = BigDecimal("1000000000000000000")
|
|
||||||
Assert.assertEquals("500ms", "0.5".formatTime())
|
|
||||||
Assert.assertEquals("50ms", "0.05".formatTime())
|
|
||||||
Assert.assertEquals("5ms", "0.005".formatTime())
|
|
||||||
Assert.assertEquals("28s", "28".formatTime())
|
|
||||||
Assert.assertEquals("1m 30s", "90".formatTime())
|
|
||||||
Assert.assertEquals("1m 30s 500ms", "90.5".formatTime())
|
|
||||||
Assert.assertEquals("1m 30s 5ms", "90.005".formatTime())
|
|
||||||
|
|
||||||
// MILLISECONDS
|
|
||||||
basicValue = BigDecimal("1000000000000000")
|
|
||||||
Assert.assertEquals("500µs", "0.5".formatTime())
|
|
||||||
Assert.assertEquals("50µs", "0.05".formatTime())
|
|
||||||
Assert.assertEquals("5µs", "0.005".formatTime())
|
|
||||||
Assert.assertEquals("28ms", "28".formatTime())
|
|
||||||
Assert.assertEquals("90ms", "90".formatTime())
|
|
||||||
Assert.assertEquals("90ms 500µs", "90.5".formatTime())
|
|
||||||
Assert.assertEquals("90ms 5µs", "90.005".formatTime())
|
|
||||||
|
|
||||||
// MICROSECONDS
|
|
||||||
basicValue = BigDecimal("1000000000000")
|
|
||||||
Assert.assertEquals("500ns", "0.5".formatTime())
|
|
||||||
Assert.assertEquals("50ns", "0.05".formatTime())
|
|
||||||
Assert.assertEquals("5ns", "0.005".formatTime())
|
|
||||||
Assert.assertEquals("28µs", "28".formatTime())
|
|
||||||
Assert.assertEquals("90µs", "90".formatTime())
|
|
||||||
Assert.assertEquals("90µs 500ns", "90.5".formatTime())
|
|
||||||
Assert.assertEquals("90µs 5ns", "90.005".formatTime())
|
|
||||||
|
|
||||||
// NANOSECONDS
|
|
||||||
basicValue = BigDecimal("1000000000")
|
|
||||||
Assert.assertEquals("500 000 000as", "0.5".formatTime())
|
|
||||||
Assert.assertEquals("50 000 000as", "0.05".formatTime())
|
|
||||||
Assert.assertEquals("5 000 000as", "0.005".formatTime())
|
|
||||||
Assert.assertEquals("28ns", "28".formatTime())
|
|
||||||
Assert.assertEquals("90ns", "90".formatTime())
|
|
||||||
Assert.assertEquals("90ns 500 000 000as", "90.5".formatTime())
|
|
||||||
Assert.assertEquals("90ns 5 000 000as", "90.005".formatTime())
|
|
||||||
|
|
||||||
// ATTOSECONDS
|
|
||||||
basicValue = BigDecimal("1")
|
|
||||||
Assert.assertEquals("0.5as", "0.5".formatTime())
|
|
||||||
Assert.assertEquals("0.05as", "0.05".formatTime())
|
|
||||||
Assert.assertEquals("0.005as", "0.005".formatTime())
|
|
||||||
Assert.assertEquals("28as", "28".formatTime())
|
|
||||||
Assert.assertEquals("90as", "90".formatTime())
|
|
||||||
Assert.assertEquals("90.5as", "90.5".formatTime())
|
|
||||||
Assert.assertEquals("90.005as", "90.005".formatTime())
|
|
||||||
}
|
|
||||||
}
|
|
@ -42,8 +42,8 @@ import com.sadellie.unitto.core.ui.common.EmptyScreen
|
|||||||
import com.sadellie.unitto.core.ui.common.ListItem
|
import com.sadellie.unitto.core.ui.common.ListItem
|
||||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||||
import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar
|
import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.userprefs.ConverterPreferences
|
import com.sadellie.unitto.data.model.userprefs.ConverterPreferences
|
||||||
import com.sadellie.unitto.data.userprefs.ConverterPreferencesImpl
|
import com.sadellie.unitto.data.userprefs.ConverterPreferencesImpl
|
||||||
import com.sadellie.unitto.feature.settings.components.AlertDialogWithList
|
import com.sadellie.unitto.feature.settings.components.AlertDialogWithList
|
||||||
|
@ -21,7 +21,7 @@ package com.sadellie.unitto.feature.settings.converter
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.model.UnitsListSorting
|
import com.sadellie.unitto.data.model.converter.UnitsListSorting
|
||||||
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
@ -56,7 +56,7 @@ import com.sadellie.unitto.core.ui.common.EmptyScreen
|
|||||||
import com.sadellie.unitto.core.ui.common.Header
|
import com.sadellie.unitto.core.ui.common.Header
|
||||||
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
import com.sadellie.unitto.core.ui.common.NavigateUpButton
|
||||||
import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar
|
import com.sadellie.unitto.core.ui.common.ScaffoldWithLargeTopBar
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import org.burnoutcrew.reorderable.ReorderableItem
|
import org.burnoutcrew.reorderable.ReorderableItem
|
||||||
import org.burnoutcrew.reorderable.detectReorder
|
import org.burnoutcrew.reorderable.detectReorder
|
||||||
import org.burnoutcrew.reorderable.detectReorderAfterLongPress
|
import org.burnoutcrew.reorderable.detectReorderAfterLongPress
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
package com.sadellie.unitto.feature.settings.unitgroups
|
package com.sadellie.unitto.feature.settings.unitgroups
|
||||||
|
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
|
|
||||||
internal sealed class UnitGroupsUIState {
|
internal sealed class UnitGroupsUIState {
|
||||||
data object Loading : UnitGroupsUIState()
|
data object Loading : UnitGroupsUIState()
|
||||||
|
@ -21,7 +21,7 @@ package com.sadellie.unitto.feature.settings.unitgroups
|
|||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.sadellie.unitto.data.common.stateIn
|
import com.sadellie.unitto.data.common.stateIn
|
||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.converter.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
Loading…
x
Reference in New Issue
Block a user