diff --git a/app/src/main/java/com/sadellie/unitto/data/units/UnitGroup.kt b/app/src/main/java/com/sadellie/unitto/data/units/UnitGroup.kt index 24739d66..d734e2d0 100644 --- a/app/src/main/java/com/sadellie/unitto/data/units/UnitGroup.kt +++ b/app/src/main/java/com/sadellie/unitto/data/units/UnitGroup.kt @@ -1,5 +1,6 @@ package com.sadellie.unitto.data.units +import androidx.annotation.StringRes import com.sadellie.unitto.R val ALL_UNIT_GROUPS: List by lazy { @@ -10,7 +11,10 @@ val ALL_UNIT_GROUPS: List by lazy { * As not all measurements can be converted between into other, we separate them into groups. * Within one groups all measurements can be converted */ -enum class UnitGroup(val res: Int, val canNegate: Boolean = false) { +enum class UnitGroup( + @StringRes val res: Int, + val canNegate: Boolean = false +) { LENGTH(res = R.string.length), CURRENCY(res = R.string.currency), MASS(res = R.string.mass), diff --git a/app/src/main/java/com/sadellie/unitto/screens/second/SecondScreen.kt b/app/src/main/java/com/sadellie/unitto/screens/second/SecondScreen.kt index 7599ba66..dd617d4b 100644 --- a/app/src/main/java/com/sadellie/unitto/screens/second/SecondScreen.kt +++ b/app/src/main/java/com/sadellie/unitto/screens/second/SecondScreen.kt @@ -84,17 +84,17 @@ fun SecondScreen( ) UnitsList( groupedUnits = unitsList, - changeAction = { viewModel.changeUnitFrom(it); focusManager.clearFocus(true); navigateUp() }, + selectAction = { viewModel.changeUnitFrom(it); focusManager.clearFocus(true); navigateUp() }, favoriteAction = { viewModel.favoriteUnit(it) }, currentUnit = viewModel.unitFrom, ) } else { UnitsList( groupedUnits = unitsList, - changeAction = { viewModel.changeUnitTo(it); focusManager.clearFocus(true); navigateUp() }, + selectAction = { viewModel.changeUnitTo(it); focusManager.clearFocus(true); navigateUp() }, favoriteAction = { viewModel.favoriteUnit(it) }, currentUnit = viewModel.unitTo, - inputValue = viewModel.mainUIState.inputValue.toBigDecimal(), + input = viewModel.mainUIState.inputValue.toBigDecimal(), unitFrom = viewModel.unitFrom ) } diff --git a/app/src/main/java/com/sadellie/unitto/screens/second/components/UnitListItem.kt b/app/src/main/java/com/sadellie/unitto/screens/second/components/UnitListItem.kt index e993bf41..98fcde41 100644 --- a/app/src/main/java/com/sadellie/unitto/screens/second/components/UnitListItem.kt +++ b/app/src/main/java/com/sadellie/unitto/screens/second/components/UnitListItem.kt @@ -24,7 +24,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -40,34 +39,29 @@ import com.sadellie.unitto.R import com.sadellie.unitto.data.units.AbstractUnit /** - * Represents one list item. Once clicked will navigate up + * Represents one list item. Once clicked will navigate up. * - * @param modifier Modifier that will be applied to a box that surrounds row. - * @param changeAction Function to change current unit. Called when choosing unit - * @param favoriteAction Function to mark unit as favorite. It's a toggle - * @param item The unit itself - * @param isSelected Whether this unit is selected or not (current pair of unit) - * @param convertValue Used for right side units. Shows conversion from unit on the left + * @param unit The unit itself. + * @param isSelected Whether this unit is selected or not (current pair of unit). + * @param selectAction Function to change current unit. Called when choosing unit. + * @param favoriteAction Function to mark unit as favorite. It's a toggle. + * @param shortNameLabel String on the second line. */ @Composable -fun UnitListItem( - modifier: Modifier, - changeAction: (AbstractUnit) -> Unit, - favoriteAction: (AbstractUnit) -> Unit, - item: AbstractUnit, +private fun BasicUnitListItem( + unit: AbstractUnit, isSelected: Boolean, - convertValue: (AbstractUnit) -> String + selectAction: (AbstractUnit) -> Unit, + favoriteAction: (AbstractUnit) -> Unit, + shortNameLabel: String ) { - var isFavorite: Boolean by rememberSaveable { mutableStateOf(item.isFavorite) } - var convertedValue: String by remember { mutableStateOf("") } + var isFavorite: Boolean by rememberSaveable { mutableStateOf(unit.isFavorite) } Box( - modifier = modifier + modifier = Modifier .clickable( interactionSource = remember { MutableInteractionSource() }, indication = rememberRipple(), // You can also change the color and radius of the ripple - onClick = { - changeAction(item) - } + onClick = { selectAction(unit) } ) .padding(horizontal = 12.dp) ) { @@ -87,19 +81,19 @@ fun UnitListItem( .weight(1f) ) { Text( - text = stringResource(id = item.displayName), + text = stringResource(id = unit.displayName), maxLines = 1, overflow = TextOverflow.Ellipsis ) Text( - text = convertedValue + stringResource(id = item.shortName), + text = shortNameLabel, style = MaterialTheme.typography.bodySmall, color = MaterialTheme.colorScheme.onSurfaceVariant, maxLines = 1, overflow = TextOverflow.Ellipsis ) } - IconButton(onClick = { favoriteAction(item); isFavorite = !isFavorite }) { + IconButton(onClick = { favoriteAction(unit); isFavorite = !isFavorite }) { AnimatedContent( targetState = isFavorite, transitionSpec = { @@ -107,15 +101,57 @@ fun UnitListItem( } ) { Icon( - if (item.isFavorite) Icons.Filled.Favorite else Icons.Filled.FavoriteBorder, + if (unit.isFavorite) Icons.Filled.Favorite else Icons.Filled.FavoriteBorder, contentDescription = stringResource(id = R.string.favorite_button_description) ) } } } } - LaunchedEffect(Unit) { - // Converting value - convertedValue = convertValue(item) - } } + +/** + * Represents one list item. Once clicked will navigate up. Has without conversion. + * + * @param unit The unit itself. + * @param isSelected Whether this unit is selected or not (current pair of unit). + * @param selectAction Function to change current unit. Called when choosing unit. + * @param favoriteAction Function to mark unit as favorite. It's a toggle. + */ +@Composable +fun UnitListItem( + unit: AbstractUnit, + isSelected: Boolean, + selectAction: (AbstractUnit) -> Unit, + favoriteAction: (AbstractUnit) -> Unit, +) = BasicUnitListItem( + unit = unit, + isSelected = isSelected, + selectAction = selectAction, + favoriteAction = favoriteAction, + stringResource(id = unit.shortName) +) + +/** + * Represents one list item. Once clicked will navigate up. Has with conversion. + * + * @param unit The unit itself. + * @param isSelected Whether this unit is selected or not (current pair of unit). + * @param selectAction Function to change current unit. Called when choosing unit. + * @param favoriteAction Function to mark unit as favorite. It's a toggle. + * @param convertValue Function to call that will convert this unit. + */ +@Composable +fun UnitListItem( + unit: AbstractUnit, + isSelected: Boolean, + selectAction: (AbstractUnit) -> Unit, + favoriteAction: (AbstractUnit) -> Unit, + convertValue: (AbstractUnit) -> String +) = BasicUnitListItem( + unit = unit, + isSelected = isSelected, + selectAction = selectAction, + favoriteAction = favoriteAction, + shortNameLabel = "${convertValue(unit)} ${stringResource(id = unit.shortName)}" +) \ No newline at end of file diff --git a/app/src/main/java/com/sadellie/unitto/screens/second/components/UnitsList.kt b/app/src/main/java/com/sadellie/unitto/screens/second/components/UnitsList.kt index 82979c7a..3358d6e4 100644 --- a/app/src/main/java/com/sadellie/unitto/screens/second/components/UnitsList.kt +++ b/app/src/main/java/com/sadellie/unitto/screens/second/components/UnitsList.kt @@ -19,22 +19,18 @@ import java.math.BigDecimal /** - * Component with grouped units + * Component with grouped units. * - * @param groupedUnits Grouped [AbstractUnit]s to be listed - * @param changeAction Action to perform when clicking on a list item - * @param favoriteAction Action to perform when clicking "favorite" button on list item - * @param inputValue Current input value. Used for right side screen - * @param unitFrom Current unit on the left. Used for right side screen - * @param currentUnit Currently selected unit. Will be visually distinguishable + * @param groupedUnits Grouped [AbstractUnit]s to be listed. + * @param selectAction Action to perform when clicking on a list item. + * @param favoriteAction Action to perform when clicking "favorite" button on list item. + * @param currentUnit Currently selected unit. Will be visually distinguishable. */ @Composable fun UnitsList( groupedUnits: Map>, - changeAction: (AbstractUnit) -> Unit, + selectAction: (AbstractUnit) -> Unit, favoriteAction: (AbstractUnit) -> Unit, - inputValue: BigDecimal = BigDecimal.ONE, - unitFrom: AbstractUnit? = null, currentUnit: AbstractUnit, ) { LazyColumn( @@ -42,41 +38,82 @@ fun UnitsList( content = { if (groupedUnits.isEmpty()) { item { SearchPlaceholder() } - } else { - groupedUnits.forEach { (unitGroup, listOfUnits) -> - stickyHeader { - Text( - modifier = Modifier - .background(MaterialTheme.colorScheme.background) - .fillMaxWidth() - .padding(vertical = 12.dp, horizontal = 8.dp), - text = stringResource(id = unitGroup.res), - style = MaterialTheme.typography.titleMedium, - color = MaterialTheme.colorScheme.primary - ) - } - items(items = listOfUnits, key = { it.unitId }) { unit -> - UnitListItem( - modifier = Modifier, - changeAction = changeAction, - favoriteAction = favoriteAction, - item = unit, - isSelected = currentUnit == unit, - convertValue = { - if (unitFrom != null) { - Formatter.format( - unitFrom - .convert(it, inputValue, 3) - .toPlainString() - ).plus(" ") - } else { - "" - } - } - ) - } + return@LazyColumn + } + groupedUnits.forEach { (unitGroup, listOfUnits) -> + stickyHeader { Header(text = stringResource(id = unitGroup.res)) } + items(items = listOfUnits, key = { it.unitId }) { unit -> + UnitListItem( + unit = unit, + isSelected = currentUnit == unit, + selectAction = selectAction, + favoriteAction = favoriteAction + ) } } } ) } + + +/** + * Component with grouped units/ + * + * @param groupedUnits Grouped [AbstractUnit]s to be listed. + * @param selectAction Action to perform when clicking on a list item. + * @param favoriteAction Action to perform when clicking "favorite" button on list item. + * @param currentUnit Currently selected unit. Will be visually distinguishable. + * @param unitFrom Unit to convert from. Used for conversion in short name field. + * @param input Current input value. Used for conversion in short name field. + */ +@Composable +fun UnitsList( + groupedUnits: Map>, + selectAction: (AbstractUnit) -> Unit, + favoriteAction: (AbstractUnit) -> Unit, + currentUnit: AbstractUnit, + unitFrom: AbstractUnit, + input: BigDecimal +) { + LazyColumn( + modifier = Modifier.fillMaxSize(), + content = { + if (groupedUnits.isEmpty()) { + item { SearchPlaceholder() } + return@LazyColumn + } + groupedUnits.forEach { (unitGroup, listOfUnits) -> + stickyHeader { Header(text = stringResource(id = unitGroup.res)) } + items(items = listOfUnits, key = { it.unitId }) { unit -> + UnitListItem( + unit = unit, + isSelected = currentUnit == unit, + selectAction = selectAction, + favoriteAction = favoriteAction, + convertValue = { + Formatter.format(unitFrom.convert(unit, input, 3).toPlainString()) + } + ) + } + } + } + ) +} + +/** + * Unit group header. + * + * @param text Unit group name. + */ +@Composable +private fun Header(text: String) { + Text( + modifier = Modifier + .background(MaterialTheme.colorScheme.background) + .fillMaxWidth() + .padding(vertical = 12.dp, horizontal = 8.dp), + text = text, + style = MaterialTheme.typography.titleMedium, + color = MaterialTheme.colorScheme.primary + ) +} \ No newline at end of file