Move unit converter supported units to a different screen

This commit is contained in:
MM20 2024-08-12 19:34:38 +02:00
parent 827eb08908
commit 3887324d37
No known key found for this signature in database
GPG Key ID: 0B61A8F2DEAFA389
19 changed files with 236 additions and 116 deletions

View File

@ -66,6 +66,7 @@ import de.mm20.launcher2.ui.settings.plugins.PluginsSettingsScreen
import de.mm20.launcher2.ui.settings.search.SearchSettingsScreen import de.mm20.launcher2.ui.settings.search.SearchSettingsScreen
import de.mm20.launcher2.ui.settings.searchactions.SearchActionsSettingsScreen import de.mm20.launcher2.ui.settings.searchactions.SearchActionsSettingsScreen
import de.mm20.launcher2.ui.settings.tags.TagsSettingsScreen import de.mm20.launcher2.ui.settings.tags.TagsSettingsScreen
import de.mm20.launcher2.ui.settings.unitconverter.UnitConverterHelpSettingsScreen
import de.mm20.launcher2.ui.settings.unitconverter.UnitConverterSettingsScreen import de.mm20.launcher2.ui.settings.unitconverter.UnitConverterSettingsScreen
import de.mm20.launcher2.ui.settings.weather.WeatherIntegrationSettingsScreen import de.mm20.launcher2.ui.settings.weather.WeatherIntegrationSettingsScreen
import de.mm20.launcher2.ui.settings.wikipedia.WikipediaSettingsScreen import de.mm20.launcher2.ui.settings.wikipedia.WikipediaSettingsScreen
@ -169,6 +170,9 @@ class SettingsActivity : BaseActivity() {
composable("settings/search/unitconverter") { composable("settings/search/unitconverter") {
UnitConverterSettingsScreen() UnitConverterSettingsScreen()
} }
composable("settings/search/unitconverter/help") {
UnitConverterHelpSettingsScreen()
}
composable("settings/search/wikipedia") { composable("settings/search/wikipedia") {
WikipediaSettingsScreen() WikipediaSettingsScreen()
} }

View File

@ -0,0 +1,100 @@
package de.mm20.launcher2.ui.settings.unitconverter
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.Preference
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
import de.mm20.launcher2.ui.launcher.search.unitconverter.getDimensionIcon
import de.mm20.launcher2.unitconverter.Dimension
import de.mm20.launcher2.unitconverter.MeasureUnit
import kotlinx.coroutines.flow.flow
@Composable
fun UnitConverterHelpSettingsScreen() {
val viewModel: UnitConverterSettingsScreenVM = viewModel()
val availableConverters by viewModel.availableConverters.collectAsState(emptyList())
val availableUnits by viewModel.availableUnits.collectAsState(emptyList())
PreferenceScreen(title = stringResource(R.string.preference_search_unitconverter),
helpUrl = "https://kvaesitso.mm20.de/docs/user-guide/search/unit-converter") {
for (i in availableConverters.indices) {
stickyHeader {
DimensionHeader(availableConverters[i].dimension)
}
items(availableUnits.getOrNull(i)?.size ?: 0) {
val unit = availableUnits[i].getOrNull(it) ?: return@items
Preference(
title = unit.formatName(LocalContext.current, 1.0),
controls = {
Box(
modifier = Modifier.size(36.dp)
.background(MaterialTheme.colorScheme.secondaryContainer, MaterialTheme.shapes.extraSmall),
contentAlignment = Alignment.Center,
) {
Text(unit.symbol, style = MaterialTheme.typography.labelSmall)
}
}
)
}
}
}
}
@Composable
private fun DimensionHeader(dimension: Dimension) {
Row(
modifier = Modifier.background(MaterialTheme.colorScheme.surfaceContainer).fillMaxWidth().padding(top = 16.dp, bottom = 16.dp)
) {
Icon(
getDimensionIcon(dimension),
null,
modifier = Modifier.padding(horizontal = 24.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
Text(
stringResource(dimension.resource),
style = MaterialTheme.typography.titleSmall,
modifier = Modifier.weight(1f),
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
@Composable
private fun UnitList(units: List<MeasureUnit>) {
val context = LocalContext.current
for (unit in units) {
Preference(
title = unit.formatName(context, 1.0),
controls = {
Box(
modifier = Modifier.size(36.dp)
.background(MaterialTheme.colorScheme.secondaryContainer, MaterialTheme.shapes.extraSmall),
contentAlignment = Alignment.Center,
) {
Text(unit.symbol, style = MaterialTheme.typography.labelSmall)
}
}
)
}
}

View File

@ -1,49 +1,28 @@
package de.mm20.launcher2.ui.settings.unitconverter package de.mm20.launcher2.ui.settings.unitconverter
import android.icu.util.Currency import androidx.compose.material.icons.Icons
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.icons.automirrored.filled.Help
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import de.mm20.launcher2.preferences.search.UnitConverterSettings
import de.mm20.launcher2.ui.R import de.mm20.launcher2.ui.R
import de.mm20.launcher2.ui.component.preferences.Preference import de.mm20.launcher2.ui.component.preferences.Preference
import de.mm20.launcher2.ui.component.preferences.PreferenceCategory import de.mm20.launcher2.ui.component.preferences.PreferenceCategory
import de.mm20.launcher2.ui.component.preferences.PreferenceScreen import de.mm20.launcher2.ui.component.preferences.PreferenceScreen
import de.mm20.launcher2.ui.component.preferences.SwitchPreference import de.mm20.launcher2.ui.component.preferences.SwitchPreference
import de.mm20.launcher2.ui.launcher.search.unitconverter.getDimensionIcon import de.mm20.launcher2.ui.locals.LocalNavController
import de.mm20.launcher2.unitconverter.converters.CurrencyConverter
import de.mm20.launcher2.unitconverter.converters.SimpleFactorConverter
import de.mm20.launcher2.unitconverter.converters.TemperatureConverter
import org.koin.androidx.compose.inject
@Composable @Composable
fun UnitConverterSettingsScreen() { fun UnitConverterSettingsScreen() {
val settings: UnitConverterSettings by inject()
val viewModel: UnitConverterSettingsScreenVM = viewModel() val viewModel: UnitConverterSettingsScreenVM = viewModel()
val loading by viewModel.loading val navController = LocalNavController.current
val currenciesEnabled by settings.currencies.collectAsState(initial = false) PreferenceScreen(
title = stringResource(R.string.preference_search_unitconverter),
LaunchedEffect(currenciesEnabled) { helpUrl = "https://kvaesitso.mm20.de/docs/user-guide/search/unit-converter"
viewModel.loadCurrencies() ) {
}
PreferenceScreen(title = stringResource(R.string.preference_search_unitconverter),
helpUrl = "https://kvaesitso.mm20.de/docs/user-guide/search/unit-converter") {
if (loading) {
item {
LinearProgressIndicator(
modifier = Modifier.fillMaxWidth()
)
}
}
item { item {
PreferenceCategory { PreferenceCategory {
val unitConverter by viewModel.unitConverter.collectAsState() val unitConverter by viewModel.unitConverter.collectAsState()
@ -66,46 +45,16 @@ fun UnitConverterSettingsScreen() {
} }
) )
} }
PreferenceCategory( PreferenceCategory {
title = stringResource(R.string.preference_search_supportedunits) Preference(
) { title = stringResource(R.string.preference_search_supportedunits),
for (converter in viewModel.convertersList.value) { icon = Icons.AutoMirrored.Default.Help,
val units = buildString { onClick = {
when (converter) { navController?.navigate("settings/search/unitconverter/help")
is SimpleFactorConverter -> {
converter.standardUnits.forEachIndexed { index, unit ->
if (index > 0) append(", ")
append(pluralStringResource(unit.nameResource, 1))
append(" (${unit.symbol})")
}
}
is TemperatureConverter -> {
converter.units.forEachIndexed { index, unit ->
if (index > 0) append(", ")
append(pluralStringResource(unit.nameResource, 1))
append(" (${unit.symbol})")
}
}
is CurrencyConverter -> {
viewModel.currenciesList.value.forEachIndexed { index, currency ->
if (index > 0) append(", ")
append(Currency.getInstance(currency)?.displayName ?: currency)
append(" ($currency)")
}
}
}
} }
)
Preference(
title = stringResource(converter.dimension.resource),
icon = getDimensionIcon(converter.dimension),
summary = units
)
}
} }
} }
} }
} }

View File

@ -6,12 +6,13 @@ import androidx.lifecycle.viewModelScope
import de.mm20.launcher2.preferences.search.UnitConverterSettings import de.mm20.launcher2.preferences.search.UnitConverterSettings
import de.mm20.launcher2.unitconverter.UnitConverterRepository import de.mm20.launcher2.unitconverter.UnitConverterRepository
import de.mm20.launcher2.unitconverter.converters.Converter import de.mm20.launcher2.unitconverter.converters.Converter
import de.mm20.launcher2.unitconverter.converters.CurrencyConverter
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent import org.koin.core.component.KoinComponent
@ -22,10 +23,6 @@ class UnitConverterSettingsScreenVM: ViewModel(), KoinComponent {
private val settings: UnitConverterSettings by inject() private val settings: UnitConverterSettings by inject()
private val repository: UnitConverterRepository by inject() private val repository: UnitConverterRepository by inject()
val loading = mutableStateOf(false)
val convertersList = mutableStateOf(emptyList<Converter>())
val currenciesList = mutableStateOf(emptyList<String>())
val unitConverter = settings.enabled val unitConverter = settings.enabled
.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null) .stateIn(viewModelScope, SharingStarted.WhileSubscribed(), null)
fun setUnitConverter(unitConverter: Boolean) { fun setUnitConverter(unitConverter: Boolean) {
@ -37,18 +34,12 @@ class UnitConverterSettingsScreenVM: ViewModel(), KoinComponent {
fun setCurrencyConverter(currencyConverter: Boolean) { fun setCurrencyConverter(currencyConverter: Boolean) {
settings.setCurrencies(currencyConverter) settings.setCurrencies(currencyConverter)
} }
fun loadCurrencies() {
loading.value = true
viewModelScope.launch(Dispatchers.Default) {
convertersList.value = repository.availableConverters(
settings.currencies.distinctUntilChanged().first()
)
val currencyConverter = convertersList.value.find { it is CurrencyConverter } val availableConverters = settings.currencies.map {
if (currencyConverter != null) { repository.getAvailableConverters(includeCurrencies = it)
currenciesList.value = (currencyConverter as CurrencyConverter).getAbbreviations() }.shareIn(viewModelScope, SharingStarted.WhileSubscribed(100), 1)
}
} val availableUnits = availableConverters.map {
loading.value = false it.map { converter -> converter.getSupportedUnits() }
} }.shareIn(viewModelScope, SharingStarted.WhileSubscribed(100), 1)
} }

View File

@ -608,7 +608,7 @@
<string name="preference_search_unitconverter_summary">Usage: 1.5 kg or 4 cm &gt;&gt; in</string> <string name="preference_search_unitconverter_summary">Usage: 1.5 kg or 4 cm &gt;&gt; in</string>
<string name="preference_search_currencyconverter">Currency converter</string> <string name="preference_search_currencyconverter">Currency converter</string>
<string name="preference_search_currencyconverter_summary">Periodically download exchange rates to convert currencies</string> <string name="preference_search_currencyconverter_summary">Periodically download exchange rates to convert currencies</string>
<string name="preference_search_supportedunits">Supported units\n(use abbreviation on search box)</string> <string name="preference_search_supportedunits">Supported units</string>
<string name="preference_search_wikipedia">Wikipedia</string> <string name="preference_search_wikipedia">Wikipedia</string>
<string name="preference_search_wikipedia_summary">Search the free encyclopedia</string> <string name="preference_search_wikipedia_summary">Search the free encyclopedia</string>
<string name="preference_search_websites">Websites</string> <string name="preference_search_websites">Websites</string>

View File

@ -8,9 +8,7 @@ import kotlin.math.roundToInt
internal object ConverterUtils { internal object ConverterUtils {
fun formatName(context: Context, unit: MeasureUnit, value: Double): String { fun formatName(context: Context, unit: MeasureUnit, value: Double): String {
val resId = unit.nameResource return unit.formatName(context, value)
val text = context.resources.getQuantityString(resId, value.roundToInt())
return text
} }
fun formatValue(context: Context, unit: MeasureUnit, value: Double): String { fun formatValue(context: Context, unit: MeasureUnit, value: Double): String {

View File

@ -0,0 +1,8 @@
package de.mm20.launcher2.unitconverter
import android.content.Context
interface MeasureUnit {
val symbol: String
fun formatName(context: Context, value: Double): String
}

View File

@ -1,6 +0,0 @@
package de.mm20.launcher2.unitconverter
interface MeasureUnit {
val symbol: String
val nameResource: Int
}

View File

@ -19,6 +19,7 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -26,7 +27,7 @@ import org.koin.core.component.KoinComponent
interface UnitConverterRepository { interface UnitConverterRepository {
fun search(query: String): Flow<UnitConverter?> fun search(query: String): Flow<UnitConverter?>
fun availableConverters(includeCurrencies: Boolean) : List<Converter> suspend fun getAvailableConverters(includeCurrencies: Boolean) : List<Converter>
} }
internal class UnitConverterRepositoryImpl( internal class UnitConverterRepositoryImpl(
@ -55,7 +56,7 @@ internal class UnitConverterRepositoryImpl(
} }
} }
override fun availableConverters(includeCurrencies: Boolean) : List<Converter> { override suspend fun getAvailableConverters(includeCurrencies: Boolean) : List<Converter> {
val converters = mutableListOf( val converters = mutableListOf(
MassConverter(context), MassConverter(context),
LengthConverter(context), LengthConverter(context),
@ -90,7 +91,7 @@ internal class UnitConverterRepositoryImpl(
val value = valueStr.toDoubleOrNull() ?: valueStr.replace(',', '.').toDoubleOrNull() val value = valueStr.toDoubleOrNull() ?: valueStr.replace(',', '.').toDoubleOrNull()
?: return null ?: return null
val converters = availableConverters(includeCurrencies) val converters = getAvailableConverters(includeCurrencies)
for (converter in converters) { for (converter in converters) {
if (!converter.isValidUnit(unitStr)) continue if (!converter.isValidUnit(unitStr)) continue

View File

@ -4,7 +4,7 @@ import android.content.Context
import de.mm20.launcher2.unitconverter.Dimension import de.mm20.launcher2.unitconverter.Dimension
import de.mm20.launcher2.unitconverter.R import de.mm20.launcher2.unitconverter.R
class AreaConverter(context: Context) : SimpleFactorConverter() { internal class AreaConverter(context: Context) : SimpleFactorConverter() {
override val dimension = Dimension.Area override val dimension = Dimension.Area
override val standardUnits = listOf( override val standardUnits = listOf(

View File

@ -3,6 +3,7 @@ package de.mm20.launcher2.unitconverter.converters
import android.content.Context import android.content.Context
import de.mm20.launcher2.search.data.UnitConverter import de.mm20.launcher2.search.data.UnitConverter
import de.mm20.launcher2.unitconverter.Dimension import de.mm20.launcher2.unitconverter.Dimension
import de.mm20.launcher2.unitconverter.MeasureUnit
interface Converter { interface Converter {
val dimension: Dimension val dimension: Dimension
@ -15,5 +16,7 @@ interface Converter {
value: Double, value: Double,
toUnit: String? toUnit: String?
): UnitConverter ): UnitConverter
suspend fun getSupportedUnits(): List<MeasureUnit>
} }

View File

@ -7,6 +7,7 @@ import de.mm20.launcher2.currencies.CurrencyRepository
import de.mm20.launcher2.search.data.CurrencyUnitConverter import de.mm20.launcher2.search.data.CurrencyUnitConverter
import de.mm20.launcher2.search.data.UnitConverter import de.mm20.launcher2.search.data.UnitConverter
import de.mm20.launcher2.unitconverter.Dimension import de.mm20.launcher2.unitconverter.Dimension
import de.mm20.launcher2.unitconverter.MeasureUnit
import de.mm20.launcher2.unitconverter.UnitValue import de.mm20.launcher2.unitconverter.UnitValue
import java.text.DecimalFormat import java.text.DecimalFormat
import java.util.Locale import java.util.Locale
@ -19,7 +20,7 @@ class CurrencyConverter(
override val dimension: Dimension = Dimension.Currency override val dimension: Dimension = Dimension.Currency
suspend fun getAbbreviations() : List<String> { suspend fun getAbbreviations(): List<String> {
return repository.getKnownUnits() return repository.getKnownUnits()
} }
@ -35,7 +36,14 @@ class CurrencyConverter(
val text = StringBuilder() val text = StringBuilder()
val currency = Currency.getInstance(symbol) ?: return formatNameFallback(symbol) val currency = Currency.getInstance(symbol) ?: return formatNameFallback(symbol)
val pluralCount = PluralRules.forLocale(Locale.getDefault()).select(value) val pluralCount = PluralRules.forLocale(Locale.getDefault()).select(value)
text.append(currency.getName(Locale.getDefault(), Currency.PLURAL_LONG_NAME, pluralCount, booleanArrayOf(false))) text.append(
currency.getName(
Locale.getDefault(),
Currency.PLURAL_LONG_NAME,
pluralCount,
booleanArrayOf(false)
)
)
return text.toString() return text.toString()
} }
@ -62,12 +70,22 @@ class CurrencyConverter(
} }
override suspend fun convert(context: Context, fromUnit: String, value: Double, toUnit: String?): UnitConverter { override suspend fun convert(
context: Context,
fromUnit: String,
value: Double,
toUnit: String?
): UnitConverter {
val fromIsoCode = repository.resolveAlias(fromUnit) val fromIsoCode = repository.resolveAlias(fromUnit)
val toIsoCode = toUnit?.let { repository.resolveAlias(it) } val toIsoCode = toUnit?.let { repository.resolveAlias(it) }
val values = repository.convertCurrency(fromIsoCode, value, toIsoCode).map { val values = repository.convertCurrency(fromIsoCode, value, toIsoCode).map {
UnitValue(it.second, it.first, formatName(it.first, it.second), formatValue(it.first, it.second)) UnitValue(
it.second,
it.first,
formatName(it.first, it.second),
formatValue(it.first, it.second)
)
}.toMutableList() }.toMutableList()
val ownCurrencySymbol = JCurrency.getInstance(Locale.getDefault()).currencyCode ?: "USD" val ownCurrencySymbol = JCurrency.getInstance(Locale.getDefault()).currencyCode ?: "USD"
@ -89,8 +107,46 @@ class CurrencyConverter(
values.add(0, ownCurrency) values.add(0, ownCurrency)
} }
val inputValue = UnitValue(value, fromIsoCode, formatName(fromIsoCode, value), formatValue(fromIsoCode, value)) val inputValue = UnitValue(
value,
fromIsoCode,
formatName(fromIsoCode, value),
formatValue(fromIsoCode, value)
)
val lastUpdate = repository.getLastUpdate(fromIsoCode) val lastUpdate = repository.getLastUpdate(fromIsoCode)
return CurrencyUnitConverter(dimension, inputValue, values, lastUpdate) return CurrencyUnitConverter(dimension, inputValue, values, lastUpdate)
} }
override suspend fun getSupportedUnits(): List<MeasureUnit> {
val currencies = repository.getKnownUnits()
return currencies.map {
CurrencyUnit(
symbol = it,
)
}
}
}
internal data class CurrencyUnit(
override val symbol: String,
) : MeasureUnit {
override fun formatName(context: Context, value: Double): String {
val text = StringBuilder()
val currency = try {
Currency.getInstance(symbol)
} catch (e: IllegalArgumentException) {
null
} ?: return symbol
val pluralCount = PluralRules.forLocale(Locale.getDefault()).select(value)
text.append(
currency.getName(
Locale.getDefault(),
Currency.LONG_NAME,
pluralCount,
booleanArrayOf(false)
)
)
return text.toString()
}
} }

View File

@ -4,7 +4,7 @@ import android.content.Context
import de.mm20.launcher2.unitconverter.Dimension import de.mm20.launcher2.unitconverter.Dimension
import de.mm20.launcher2.unitconverter.R import de.mm20.launcher2.unitconverter.R
class DataConverter(context: Context) : SimpleFactorConverter() { internal class DataConverter(context: Context) : SimpleFactorConverter() {
override val dimension = Dimension.Data override val dimension = Dimension.Data
override val standardUnits = listOf( override val standardUnits = listOf(

View File

@ -4,7 +4,7 @@ import android.content.Context
import de.mm20.launcher2.unitconverter.Dimension import de.mm20.launcher2.unitconverter.Dimension
import de.mm20.launcher2.unitconverter.R import de.mm20.launcher2.unitconverter.R
class LengthConverter(context: Context) : SimpleFactorConverter() { internal class LengthConverter(context: Context) : SimpleFactorConverter() {
override val dimension = Dimension.Length override val dimension = Dimension.Length
override val standardUnits = listOf( override val standardUnits = listOf(

View File

@ -4,7 +4,7 @@ import android.content.Context
import de.mm20.launcher2.unitconverter.Dimension import de.mm20.launcher2.unitconverter.Dimension
import de.mm20.launcher2.unitconverter.R import de.mm20.launcher2.unitconverter.R
class MassConverter(context: Context): SimpleFactorConverter() { internal class MassConverter(context: Context): SimpleFactorConverter() {
override val dimension = Dimension.Mass override val dimension = Dimension.Mass
override val standardUnits = listOf( override val standardUnits = listOf(

View File

@ -5,11 +5,12 @@ import de.mm20.launcher2.search.data.UnitConverter
import de.mm20.launcher2.unitconverter.ConverterUtils import de.mm20.launcher2.unitconverter.ConverterUtils
import de.mm20.launcher2.unitconverter.MeasureUnit import de.mm20.launcher2.unitconverter.MeasureUnit
import de.mm20.launcher2.unitconverter.UnitValue import de.mm20.launcher2.unitconverter.UnitValue
import kotlin.math.roundToInt
/** /**
* A converter for units that can converted into each other by simple multiplication with a constant factor * A converter for units that can converted into each other by simple multiplication with a constant factor
*/ */
abstract class SimpleFactorConverter: Converter { internal abstract class SimpleFactorConverter: Converter {
open val standardUnits: List<MeasureUnitWithFactor> = emptyList() open val standardUnits: List<MeasureUnitWithFactor> = emptyList()
/** /**
@ -36,11 +37,19 @@ abstract class SimpleFactorConverter: Converter {
val inputValue = UnitValue(value, fromUnit, ConverterUtils.formatName(context, unit, value), ConverterUtils.formatValue(context, unit, value)) val inputValue = UnitValue(value, fromUnit, ConverterUtils.formatName(context, unit, value), ConverterUtils.formatValue(context, unit, value))
return UnitConverter(dimension, inputValue, results) return UnitConverter(dimension, inputValue, results)
} }
override suspend fun getSupportedUnits(): List<MeasureUnit> {
return standardUnits
}
} }
data class MeasureUnitWithFactor( data class MeasureUnitWithFactor(
val factor: Double, val factor: Double,
override val symbol: String, override val symbol: String,
override val nameResource: Int val nameResource: Int
): MeasureUnit ): MeasureUnit {
override fun formatName(context: Context, value: Double): String {
return context.resources.getQuantityString(nameResource, value.roundToInt())
}
}

View File

@ -4,7 +4,7 @@ import android.content.Context
import de.mm20.launcher2.search.data.UnitConverter import de.mm20.launcher2.search.data.UnitConverter
import de.mm20.launcher2.unitconverter.* import de.mm20.launcher2.unitconverter.*
class TemperatureConverter(context: Context) : Converter { internal class TemperatureConverter(context: Context) : Converter {
override val dimension = Dimension.Temperature override val dimension = Dimension.Temperature
val units = listOf( val units = listOf(
@ -100,14 +100,21 @@ class TemperatureConverter(context: Context) : Converter {
} }
throw IllegalArgumentException() throw IllegalArgumentException()
} }
override suspend fun getSupportedUnits(): List<MeasureUnit> {
return units
}
} }
data class TemperatureMeasureUnit( data class TemperatureMeasureUnit(
override val symbol: String, override val symbol: String,
override val nameResource: Int, val nameResource: Int,
val unit: TemperatureUnit val unit: TemperatureUnit
) : ) : MeasureUnit {
MeasureUnit override fun formatName(context: Context, value: Double): String {
return context.resources.getQuantityString(nameResource, value.toInt())
}
}
enum class TemperatureUnit { enum class TemperatureUnit {
DegreeCelsius, DegreeCelsius,

View File

@ -4,7 +4,7 @@ import android.content.Context
import de.mm20.launcher2.unitconverter.Dimension import de.mm20.launcher2.unitconverter.Dimension
import de.mm20.launcher2.unitconverter.R import de.mm20.launcher2.unitconverter.R
class TimeConverter(context: Context) : SimpleFactorConverter() { internal class TimeConverter(context: Context) : SimpleFactorConverter() {
override val dimension = Dimension.Time override val dimension = Dimension.Time
override val standardUnits = listOf( override val standardUnits = listOf(

View File

@ -4,7 +4,7 @@ import android.content.Context
import de.mm20.launcher2.unitconverter.Dimension import de.mm20.launcher2.unitconverter.Dimension
import de.mm20.launcher2.unitconverter.R import de.mm20.launcher2.unitconverter.R
class VelocityConverter(context: Context) : SimpleFactorConverter() { internal class VelocityConverter(context: Context) : SimpleFactorConverter() {
override val dimension = Dimension.Velocity override val dimension = Dimension.Velocity
override val standardUnits = listOf( override val standardUnits = listOf(