From 3c10fb9b0c9c94dc3d8830cb2c29124aacf88444 Mon Sep 17 00:00:00 2001 From: Sad Ellie Date: Wed, 7 Feb 2024 23:42:51 +0300 Subject: [PATCH] Refactor LeftSideScreen and RightSideScreen Reusable UnitsList --- .../feature/converter/LeftSideScreen.kt | 59 +++------- .../feature/converter/RightSideScreen.kt | 79 +++++-------- .../feature/converter/components/UnitsList.kt | 110 ++++++++++++++++++ 3 files changed, 151 insertions(+), 97 deletions(-) create mode 100644 feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitsList.kt diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideScreen.kt index 03b6e039..35060b7d 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideScreen.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/LeftSideScreen.kt @@ -18,13 +18,9 @@ package com.sadellie.unitto.feature.converter -import androidx.compose.animation.Crossfade import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold @@ -33,12 +29,11 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.res.stringResource +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.SearchPlaceholder import com.sadellie.unitto.core.ui.common.EmptyScreen import com.sadellie.unitto.core.ui.common.SearchBar import com.sadellie.unitto.data.converter.UnitID @@ -46,10 +41,9 @@ import com.sadellie.unitto.data.model.UnitGroup import com.sadellie.unitto.data.model.UnitsListSorting import com.sadellie.unitto.data.model.unit.AbstractUnit import com.sadellie.unitto.data.model.unit.NormalUnit -import com.sadellie.unitto.feature.converter.components.BasicUnitListItem import com.sadellie.unitto.feature.converter.components.ChipsRow import com.sadellie.unitto.feature.converter.components.FavoritesButton -import com.sadellie.unitto.feature.converter.components.UnitGroupHeader +import com.sadellie.unitto.feature.converter.components.UnitsList import java.math.BigDecimal @Composable @@ -129,43 +123,20 @@ private fun LeftSideScreen( } } ) { paddingValues -> - Crossfade( - targetState = uiState.units.isNotEmpty(), + val resources = LocalContext.current.resources + UnitsList( modifier = Modifier.padding(paddingValues), - label = "Units list" - ) { hasUnits -> - when (hasUnits) { - true -> LazyColumn(Modifier.fillMaxSize()) { - uiState.units.forEach { (unitGroup, units) -> - item(unitGroup.name) { - UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup) - } - - items(units, { it.id }) { - BasicUnitListItem( - modifier = Modifier.animateItemPlacement(), - name = stringResource(it.displayName), - supportLabel = stringResource(it.shortName), - isFavorite = it.isFavorite, - isSelected = it.id == uiState.unitFrom.id, - onClick = { - onQueryChange(TextFieldValue()) - updateUnitFrom(it) - navigateUp() - }, - favoriteUnit = { favoriteUnit(it) } - ) - } - } - } - - false -> SearchPlaceholder( - onButtonClick = navigateToUnitGroups, - supportText = stringResource(R.string.converter_no_results_support), - buttonLabel = stringResource(R.string.open_settings_label) - ) - } - } + groupedUnits = uiState.units, + navigateToUnitGroups = navigateToUnitGroups, + currentUnitId = uiState.unitFrom.id, + supportLabel = { resources.getString(it.shortName) }, + onClick = { + onQueryChange(TextFieldValue()) + updateUnitFrom(it) + navigateUp() + }, + favoriteUnit = { favoriteUnit(it) } + ) } } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideScreen.kt index 32e16b2f..cb413666 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideScreen.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/RightSideScreen.kt @@ -18,38 +18,32 @@ package com.sadellie.unitto.feature.converter -import androidx.compose.animation.Crossfade -import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items import androidx.compose.material3.Scaffold import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.res.stringResource +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.tooling.preview.Preview import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sadellie.unitto.core.base.OutputFormat import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.SearchPlaceholder import com.sadellie.unitto.core.ui.common.EmptyScreen import com.sadellie.unitto.core.ui.common.SearchBar import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols import com.sadellie.unitto.core.ui.common.textfield.formatExpression import com.sadellie.unitto.data.common.format +import com.sadellie.unitto.data.converter.UnitID import com.sadellie.unitto.data.model.UnitGroup import com.sadellie.unitto.data.model.UnitsListSorting import com.sadellie.unitto.data.model.unit.AbstractUnit import com.sadellie.unitto.data.model.unit.DefaultUnit import com.sadellie.unitto.data.model.unit.NormalUnit import com.sadellie.unitto.data.model.unit.NumberBaseUnit -import com.sadellie.unitto.data.converter.UnitID -import com.sadellie.unitto.feature.converter.components.BasicUnitListItem import com.sadellie.unitto.feature.converter.components.FavoritesButton -import com.sadellie.unitto.feature.converter.components.UnitGroupHeader +import com.sadellie.unitto.feature.converter.components.UnitsList import java.math.BigDecimal @Composable @@ -103,52 +97,31 @@ private fun RightSideScreen( ) } ) { paddingValues -> - Crossfade( - targetState = uiState.units.isNotEmpty(), + val resources = LocalContext.current.resources + UnitsList( modifier = Modifier.padding(paddingValues), - label = "Units list" - ) { hasUnits -> - when (hasUnits) { - true -> LazyColumn(Modifier.fillMaxSize()) { - uiState.units.forEach { (unitGroup, units) -> - item(unitGroup.name) { - UnitGroupHeader(Modifier.animateItemPlacement(), unitGroup) - } - - items(units, { it.id }) { - BasicUnitListItem( - modifier = Modifier.animateItemPlacement(), - name = stringResource(it.displayName), - supportLabel = formatUnitToSupportLabel( - unitFrom = uiState.unitFrom, - unitTo = it, - input = uiState.input, - shortName = stringResource(it.shortName), - scale = uiState.scale, - outputFormat = uiState.outputFormat, - formatterSymbols = uiState.formatterSymbols, - readyCurrencies = uiState.currencyRateUpdateState is CurrencyRateUpdateState.Ready, - ), - isFavorite = it.isFavorite, - isSelected = it.id == uiState.unitTo.id, - onClick = { - onQueryChange(TextFieldValue()) - updateUnitTo(it) - navigateUp() - }, - favoriteUnit = { favoriteUnit(it) } - ) - } - } - } - - false -> SearchPlaceholder( - onButtonClick = navigateToUnitGroups, - supportText = stringResource(R.string.converter_no_results_support), - buttonLabel = stringResource(R.string.open_settings_label) + groupedUnits = uiState.units, + navigateToUnitGroups = navigateToUnitGroups, + currentUnitId = uiState.unitTo.id, + supportLabel = { + formatUnitToSupportLabel( + unitFrom = uiState.unitFrom, + unitTo = it, + input = uiState.input, + shortName = resources.getString(it.shortName), + scale = uiState.scale, + outputFormat = uiState.outputFormat, + formatterSymbols = uiState.formatterSymbols, + readyCurrencies = uiState.currencyRateUpdateState is CurrencyRateUpdateState.Ready, ) - } - } + }, + onClick = { + onQueryChange(TextFieldValue()) + updateUnitTo(it) + navigateUp() + }, + favoriteUnit = { favoriteUnit(it) } + ) } } diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitsList.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitsList.kt new file mode 100644 index 00000000..cb5212d4 --- /dev/null +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/UnitsList.kt @@ -0,0 +1,110 @@ +/* + * 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 . + */ + +package com.sadellie.unitto.feature.converter.components + +import androidx.compose.animation.Crossfade +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.sadellie.unitto.core.base.R +import com.sadellie.unitto.core.ui.common.SearchPlaceholder +import com.sadellie.unitto.data.converter.UnitID +import com.sadellie.unitto.data.model.UnitGroup +import com.sadellie.unitto.data.model.unit.AbstractUnit +import com.sadellie.unitto.data.model.unit.NormalUnit +import java.math.BigDecimal + +@Composable +internal fun UnitsList( + modifier: Modifier, + groupedUnits: Map>, + navigateToUnitGroups: () -> Unit, + currentUnitId: String, + supportLabel: (AbstractUnit) -> String, + onClick: (AbstractUnit) -> Unit, + favoriteUnit: (AbstractUnit) -> Unit, +) { + Crossfade( + modifier = modifier, + targetState = groupedUnits.isNotEmpty(), + label = "Units list" + ) { hasUnits -> + when (hasUnits) { + true -> LazyColumn( + modifier = Modifier.fillMaxSize() + ) { + groupedUnits.forEach { (group, units) -> + item(group.name) { + UnitGroupHeader(Modifier.animateItemPlacement(), group) + } + + items(units, { it.id }) { + BasicUnitListItem( + modifier = Modifier.animateItemPlacement(), + name = stringResource(it.displayName), + supportLabel = supportLabel(it), + isFavorite = it.isFavorite, + isSelected = it.id == currentUnitId, + onClick = { onClick(it) }, + favoriteUnit = { favoriteUnit(it) }, + ) + } + } + } + + false -> SearchPlaceholder( + onButtonClick = navigateToUnitGroups, + supportText = stringResource(R.string.converter_no_results_support), + buttonLabel = stringResource(R.string.open_settings_label) + ) + } + } +} + +@Preview +@Composable +private fun PreviewUnitsList() { + val resources = LocalContext.current.resources + val groupedUnits: Map> = mapOf( + UnitGroup.LENGTH to listOf( + NormalUnit(UnitID.meter, BigDecimal.valueOf(1.0E+18), UnitGroup.LENGTH, R.string.unit_meter, R.string.unit_meter_short), + NormalUnit(UnitID.kilometer, BigDecimal.valueOf(1.0E+21), UnitGroup.LENGTH, R.string.unit_kilometer, R.string.unit_kilometer_short), + NormalUnit(UnitID.nautical_mile, BigDecimal.valueOf(1.852E+21), UnitGroup.LENGTH, R.string.unit_nautical_mile, R.string.unit_nautical_mile_short), + NormalUnit(UnitID.inch, BigDecimal.valueOf(25_400_000_000_000_000), UnitGroup.LENGTH, R.string.unit_inch, R.string.unit_inch_short), + NormalUnit(UnitID.foot, BigDecimal.valueOf(304_800_000_000_002_200), UnitGroup.LENGTH, R.string.unit_foot, R.string.unit_foot_short), + NormalUnit(UnitID.yard, BigDecimal.valueOf(914_400_000_000_006_400), UnitGroup.LENGTH, R.string.unit_yard, R.string.unit_yard_short), + NormalUnit(UnitID.mile, BigDecimal.valueOf(1_609_344_000_000_010_500_000.0), UnitGroup.LENGTH, R.string.unit_mile, R.string.unit_mile_short), + ) + ) + + UnitsList( + modifier = Modifier.fillMaxSize(), + groupedUnits = groupedUnits, + navigateToUnitGroups = {}, + currentUnitId = UnitID.mile, + supportLabel = { resources.getString(it.shortName) }, + onClick = {}, + favoriteUnit = {} + ) +}