mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-19 08:45:27 +02:00
I pressed some buttons on my keyboard
Experimental feature: Unit groups in vertical list
This commit is contained in:
parent
1d5bbaf5b2
commit
771b56eec8
@ -111,6 +111,7 @@ data class MainPreferences(
|
|||||||
val unitConverterFormatTime: Boolean = false,
|
val unitConverterFormatTime: Boolean = false,
|
||||||
val unitConverterSorting: UnitsListSorting = UnitsListSorting.USAGE,
|
val unitConverterSorting: UnitsListSorting = UnitsListSorting.USAGE,
|
||||||
val middleZero: Boolean = false,
|
val middleZero: Boolean = false,
|
||||||
|
val enableToolsExperiment: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -208,6 +209,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
val unitConverterFormatTime: Boolean = preferences[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] ?: false
|
val unitConverterFormatTime: Boolean = preferences[PrefsKeys.UNIT_CONVERTER_FORMAT_TIME] ?: false
|
||||||
val unitConverterSorting: UnitsListSorting = preferences[PrefsKeys.UNIT_CONVERTER_SORTING]?.let { UnitsListSorting.valueOf(it) } ?: UnitsListSorting.USAGE
|
val unitConverterSorting: UnitsListSorting = preferences[PrefsKeys.UNIT_CONVERTER_SORTING]?.let { UnitsListSorting.valueOf(it) } ?: UnitsListSorting.USAGE
|
||||||
val middleZero: Boolean = preferences[PrefsKeys.MIDDLE_ZERO] ?: false
|
val middleZero: Boolean = preferences[PrefsKeys.MIDDLE_ZERO] ?: false
|
||||||
|
val enableToolsExperiment: Boolean = preferences[PrefsKeys.ENABLE_TOOLS_EXPERIMENT] ?: false
|
||||||
|
|
||||||
MainPreferences(
|
MainPreferences(
|
||||||
digitsPrecision = digitsPrecision,
|
digitsPrecision = digitsPrecision,
|
||||||
@ -222,6 +224,7 @@ class UserPreferencesRepository @Inject constructor(private val dataStore: DataS
|
|||||||
unitConverterFormatTime = unitConverterFormatTime,
|
unitConverterFormatTime = unitConverterFormatTime,
|
||||||
unitConverterSorting = unitConverterSorting,
|
unitConverterSorting = unitConverterSorting,
|
||||||
middleZero = middleZero,
|
middleZero = middleZero,
|
||||||
|
enableToolsExperiment = enableToolsExperiment
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,8 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
unitFrom = unitFrom,
|
unitFrom = unitFrom,
|
||||||
sorting = prefs.unitConverterSorting,
|
sorting = prefs.unitConverterSorting,
|
||||||
shownUnitGroups = prefs.shownUnitGroups,
|
shownUnitGroups = prefs.shownUnitGroups,
|
||||||
favorites = prefs.unitConverterFavoritesOnly
|
favorites = prefs.unitConverterFavoritesOnly,
|
||||||
|
verticalList = prefs.enableToolsExperiment,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.onEach {
|
.onEach {
|
||||||
@ -162,7 +163,7 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
unitGroup = it.unitGroup,
|
unitGroup = it.unitGroup,
|
||||||
favoritesOnly = it.favorites,
|
favoritesOnly = it.favorites,
|
||||||
sorting = it.sorting,
|
sorting = it.sorting,
|
||||||
shownUnitGroups = it.shownUnitGroups
|
shownUnitGroups = it.shownUnitGroups,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.stateIn(viewModelScope, SharingStarted.Lazily, LeftSideUIState())
|
.stateIn(viewModelScope, SharingStarted.Lazily, LeftSideUIState())
|
||||||
|
@ -51,6 +51,7 @@ import com.sadellie.unitto.core.ui.common.UnittoSearchBar
|
|||||||
import com.sadellie.unitto.data.model.UnitGroup
|
import com.sadellie.unitto.data.model.UnitGroup
|
||||||
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
import com.sadellie.unitto.data.model.unit.AbstractUnit
|
||||||
import com.sadellie.unitto.feature.converter.components.BasicUnitListItem
|
import com.sadellie.unitto.feature.converter.components.BasicUnitListItem
|
||||||
|
import com.sadellie.unitto.feature.converter.components.ChipsFlexRow
|
||||||
import com.sadellie.unitto.feature.converter.components.ChipsRow
|
import com.sadellie.unitto.feature.converter.components.ChipsRow
|
||||||
import com.sadellie.unitto.feature.converter.components.FavoritesButton
|
import com.sadellie.unitto.feature.converter.components.FavoritesButton
|
||||||
import com.sadellie.unitto.feature.converter.components.SearchPlaceholder
|
import com.sadellie.unitto.feature.converter.components.SearchPlaceholder
|
||||||
@ -129,13 +130,24 @@ private fun LeftSideScreen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
ChipsRow(
|
|
||||||
chosenUnitGroup = uiState.unitGroup,
|
if (uiState.verticalList) {
|
||||||
items = uiState.shownUnitGroups,
|
ChipsFlexRow(
|
||||||
selectAction = updateUnitGroup,
|
chosenUnitGroup = uiState.unitGroup,
|
||||||
lazyListState = chipsRowLazyListState,
|
items = uiState.shownUnitGroups,
|
||||||
navigateToSettingsAction = navigateToUnitGroups
|
selectAction = updateUnitGroup,
|
||||||
)
|
lazyListState = chipsRowLazyListState,
|
||||||
|
navigateToSettingsAction = navigateToUnitGroups
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
ChipsRow(
|
||||||
|
chosenUnitGroup = uiState.unitGroup,
|
||||||
|
items = uiState.shownUnitGroups,
|
||||||
|
selectAction = updateUnitGroup,
|
||||||
|
lazyListState = chipsRowLazyListState,
|
||||||
|
navigateToSettingsAction = navigateToUnitGroups
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
|
@ -31,4 +31,5 @@ internal data class LeftSideUIState(
|
|||||||
val shownUnitGroups: List<UnitGroup> = emptyList(),
|
val shownUnitGroups: List<UnitGroup> = emptyList(),
|
||||||
val unitGroup: UnitGroup? = unitFrom?.group,
|
val unitGroup: UnitGroup? = unitFrom?.group,
|
||||||
val sorting: UnitsListSorting = UnitsListSorting.USAGE,
|
val sorting: UnitsListSorting = UnitsListSorting.USAGE,
|
||||||
|
val verticalList: Boolean = false,
|
||||||
)
|
)
|
||||||
|
@ -19,32 +19,53 @@
|
|||||||
package com.sadellie.unitto.feature.converter.components
|
package com.sadellie.unitto.feature.converter.components
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.core.animateDp
|
||||||
|
import androidx.compose.animation.core.animateFloat
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.animation.core.updateTransition
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.border
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
||||||
|
import androidx.compose.foundation.layout.FlowRow
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.RowScope
|
import androidx.compose.foundation.layout.RowScope
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.LazyRow
|
import androidx.compose.foundation.lazy.LazyRow
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.filled.Check
|
import androidx.compose.material.icons.filled.Check
|
||||||
|
import androidx.compose.material.icons.filled.ExpandMore
|
||||||
import androidx.compose.material.icons.filled.Settings
|
import androidx.compose.material.icons.filled.Settings
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
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
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.clipToBounds
|
||||||
|
import androidx.compose.ui.draw.rotate
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.sadellie.unitto.core.base.R
|
import com.sadellie.unitto.core.base.R
|
||||||
import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS
|
import com.sadellie.unitto.data.model.ALL_UNIT_GROUPS
|
||||||
@ -118,6 +139,89 @@ internal fun ChipsRow(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
|
@Composable
|
||||||
|
fun ChipsFlexRow(
|
||||||
|
items: List<UnitGroup> = ALL_UNIT_GROUPS,
|
||||||
|
chosenUnitGroup: UnitGroup?,
|
||||||
|
selectAction: (UnitGroup?) -> Unit,
|
||||||
|
navigateToSettingsAction: () -> Unit,
|
||||||
|
lazyListState: LazyListState
|
||||||
|
) {
|
||||||
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
val transition = updateTransition(expanded, label = "Expanded transition")
|
||||||
|
|
||||||
|
val rowHeight by transition.animateDp({ tween() }, "Row height") {
|
||||||
|
if (it) 392.dp else 32.dp
|
||||||
|
}
|
||||||
|
|
||||||
|
val expandRotation by transition.animateFloat({ tween() }, "Expand rotation") {
|
||||||
|
if (it) 180f else 0f
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(16.dp, 8.dp)
|
||||||
|
.heightIn(max = rowHeight)
|
||||||
|
.clipToBounds()
|
||||||
|
) {
|
||||||
|
FlowRow(
|
||||||
|
modifier = Modifier
|
||||||
|
.verticalScroll(rememberScrollState(), expanded)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.weight(1f),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
items.forEach { item ->
|
||||||
|
val isSelected: Boolean = item == chosenUnitGroup
|
||||||
|
UnittoFilterChip(
|
||||||
|
isSelected = isSelected,
|
||||||
|
selectAction = { selectAction(if (item == chosenUnitGroup) null else item) }
|
||||||
|
) {
|
||||||
|
AnimatedVisibility(visible = isSelected) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.height(18.dp),
|
||||||
|
imageVector = Icons.Default.Check,
|
||||||
|
contentDescription = stringResource(R.string.checked_filter_description)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
|
text = stringResource(item.res),
|
||||||
|
style = MaterialTheme.typography.labelLarge,
|
||||||
|
color = if (isSelected) MaterialTheme.colorScheme.onSecondaryContainer else MaterialTheme.colorScheme.onSurfaceVariant
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
UnittoFilterChip(
|
||||||
|
isSelected = false,
|
||||||
|
selectAction = navigateToSettingsAction,
|
||||||
|
paddingValues = PaddingValues(horizontal = 8.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.height(18.dp),
|
||||||
|
imageVector = Icons.Default.Settings,
|
||||||
|
contentDescription = stringResource(R.string.open_settings_description)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
onClick = { expanded = !expanded },
|
||||||
|
modifier = Modifier.size(32.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.ExpandMore,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(32.dp)
|
||||||
|
.rotate(expandRotation)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Basic chip implementation
|
* Basic chip implementation
|
||||||
*
|
*
|
||||||
@ -154,3 +258,39 @@ private fun UnittoFilterChip(
|
|||||||
content()
|
content()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
fun PreviewUnittoChips() {
|
||||||
|
var selected by remember { mutableStateOf<UnitGroup?>(UnitGroup.LENGTH) }
|
||||||
|
|
||||||
|
fun selectAction(unitGroup: UnitGroup?) {
|
||||||
|
selected = unitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
ChipsRow(
|
||||||
|
items = ALL_UNIT_GROUPS,
|
||||||
|
chosenUnitGroup = selected,
|
||||||
|
selectAction = { selectAction(it) },
|
||||||
|
navigateToSettingsAction = {},
|
||||||
|
lazyListState = rememberLazyListState()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(showSystemUi = true, showBackground = true, backgroundColor = 0xFFE0E0E0)
|
||||||
|
@Composable
|
||||||
|
fun PreviewChipsFlowRow() {
|
||||||
|
var selected by remember { mutableStateOf<UnitGroup?>(UnitGroup.LENGTH) }
|
||||||
|
|
||||||
|
fun selectAction(unitGroup: UnitGroup?) {
|
||||||
|
selected = unitGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
ChipsFlexRow(
|
||||||
|
items = ALL_UNIT_GROUPS,
|
||||||
|
chosenUnitGroup = selected,
|
||||||
|
selectAction = { selectAction(it) },
|
||||||
|
navigateToSettingsAction = {},
|
||||||
|
lazyListState = rememberLazyListState()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
@ -186,7 +186,7 @@ internal fun AboutScreen(
|
|||||||
supportingContent = { Text("${BuildConfig.APP_NAME} (${BuildConfig.APP_CODE})") },
|
supportingContent = { Text("${BuildConfig.APP_NAME} (${BuildConfig.APP_CODE})") },
|
||||||
modifier = Modifier.combinedClickable {
|
modifier = Modifier.combinedClickable {
|
||||||
if (userPrefs.value.enableToolsExperiment) {
|
if (userPrefs.value.enableToolsExperiment) {
|
||||||
Toast.makeText(mContext, "Tools already enabled!", Toast.LENGTH_LONG).show()
|
Toast.makeText(mContext, "Experiments features are already enabled!", Toast.LENGTH_LONG).show()
|
||||||
return@combinedClickable
|
return@combinedClickable
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ internal fun AboutScreen(
|
|||||||
if (aboutItemClick < 7) return@combinedClickable
|
if (aboutItemClick < 7) return@combinedClickable
|
||||||
|
|
||||||
viewModel.enableToolsExperiment()
|
viewModel.enableToolsExperiment()
|
||||||
Toast.makeText(mContext, "Tools enabled!", Toast.LENGTH_LONG).show()
|
Toast.makeText(mContext, "Experimental features enabled!", Toast.LENGTH_LONG).show()
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user