diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/PagedIsland.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/PagedIsland.kt
new file mode 100644
index 00000000..4ffedd94
--- /dev/null
+++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/PagedIsland.kt
@@ -0,0 +1,108 @@
+/*
+ * Unitto is a unit converter for Android
+ * Copyright (c) 2023 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.core.ui.common
+
+import androidx.annotation.IntRange
+import androidx.compose.animation.AnimatedContent
+import androidx.compose.foundation.Canvas
+import androidx.compose.foundation.background
+import androidx.compose.foundation.interaction.MutableInteractionSource
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.ColumnScope
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Text
+import androidx.compose.material3.contentColorFor
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableIntStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+
+@Composable
+fun PagedIsland(
+ modifier: Modifier = Modifier,
+ @IntRange(from = 1) pagesCount: Int,
+ onPageChange: (currentPage: Int) -> Unit = {},
+ backgroundColor: Color = MaterialTheme.colorScheme.secondaryContainer,
+ pageContent: @Composable ColumnScope.(currentPage: Int) -> Unit,
+) {
+ var currentPage: Int by remember { mutableIntStateOf(0) }
+ val contentColor = MaterialTheme.colorScheme.contentColorFor(backgroundColor)
+ val disabledContentColor = contentColor.copy(alpha = 0.5f)
+
+ AnimatedContent(
+ modifier = modifier
+ .squashable(
+ onClick = {
+ if (currentPage == pagesCount - 1) currentPage = 0 else currentPage++
+ onPageChange(currentPage)
+ },
+ cornerRadiusRange = 8.dp..32.dp,
+ interactionSource = remember { MutableInteractionSource() }
+ )
+ .background(backgroundColor),
+ targetState = currentPage
+ ) { state ->
+ ProvideColor(color = contentColor) {
+ Column(
+ modifier = Modifier.padding(16.dp)
+ ) {
+ Row(
+ modifier = Modifier
+ .padding(8.dp),
+ horizontalArrangement = Arrangement.spacedBy(8.dp)
+ ) {
+ repeat(pagesCount) {
+ ADot(color = if (it == state) contentColor else disabledContentColor)
+ }
+ }
+ pageContent(state)
+ }
+ }
+ }
+}
+
+@Composable
+private fun ADot(
+ color: Color,
+) {
+ Canvas(modifier = Modifier.size(4.dp)) {
+ drawCircle(color)
+ }
+}
+
+@Preview
+@Composable
+private fun PreviewPagedIsland() {
+ PagedIsland(pagesCount = 5) { currentPage ->
+ Text("Current page: $currentPage")
+
+ if (currentPage == 3) {
+ Text("Middle in: $currentPage")
+ }
+ }
+}
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt
index ee28e56c..c048e4ea 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingScreen.kt
@@ -18,11 +18,8 @@
package com.sadellie.unitto.feature.settings.formatting
-import androidx.compose.foundation.background
import androidx.compose.foundation.horizontalScroll
-import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
@@ -55,15 +52,18 @@ import com.sadellie.unitto.core.base.OutputFormat
import com.sadellie.unitto.core.base.R
import com.sadellie.unitto.core.base.Separator
import com.sadellie.unitto.core.ui.common.NavigateUpButton
+import com.sadellie.unitto.core.ui.common.PagedIsland
import com.sadellie.unitto.core.ui.common.SegmentedButton
import com.sadellie.unitto.core.ui.common.SegmentedButtonsRow
import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen
import com.sadellie.unitto.core.ui.common.UnittoListItem
import com.sadellie.unitto.core.ui.common.UnittoScreenWithLargeTopBar
import com.sadellie.unitto.core.ui.common.UnittoSlider
-import com.sadellie.unitto.core.ui.common.squashable
+import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
import com.sadellie.unitto.core.ui.common.textfield.formatExpression
import com.sadellie.unitto.core.ui.theme.NumberTypographyUnitto
+import com.sadellie.unitto.data.common.format
+import kotlin.math.ceil
import kotlin.math.roundToInt
@Composable
@@ -80,7 +80,6 @@ fun FormattingRoute(
onPrecisionChange = viewModel::updatePrecision,
onSeparatorChange = viewModel::updateSeparator,
onOutputFormatChange = viewModel::updateOutputFormat,
- togglePreview = viewModel::togglePreview
)
}
}
@@ -93,7 +92,6 @@ fun FormattingScreen(
onPrecisionChange: (Int) -> Unit,
onSeparatorChange: (Int) -> Unit,
onOutputFormatChange: (Int) -> Unit,
- togglePreview: () -> Unit,
precisions: ClosedFloatingPointRange = 0f..16f, // 16th is a MAX_PRECISION (1000)
) {
val resources = LocalContext.current.resources
@@ -120,25 +118,24 @@ fun FormattingScreen(
.padding(paddingValues)
) {
item("preview") {
- Column(
- Modifier
- .padding(16.dp)
- .squashable(
- onClick = togglePreview,
- cornerRadiusRange = 8.dp..32.dp,
- interactionSource = remember { MutableInteractionSource() }
- )
- .background(MaterialTheme.colorScheme.secondaryContainer)
+ PagedIsland(
+ modifier = Modifier
.fillMaxWidth()
- .padding(16.dp)
- ) {
+ .padding(16.dp),
+ pagesCount = 2,
+ ) { currentPage ->
+ val preview = when (currentPage) {
+ 0 -> "123456.${"789123456".repeat(ceil(uiState.precision.toDouble() / 9.0).toInt())}"
+ 1 -> "0.${"1".padStart(uiState.precision, '0')}"
+ else -> ""
+ }
+ .toBigDecimalOrNull()
+ ?.format(uiState.precision, uiState.outputFormat)
+ ?.formatExpression(uiState.formatterSymbols)
+ ?: ""
+
Text(
- text = stringResource(R.string.settings_formatting_preview),
- style = MaterialTheme.typography.labelMedium,
- color = MaterialTheme.colorScheme.onSecondaryContainer
- )
- Text(
- text = uiState.preview,
+ text = preview,
style = NumberTypographyUnitto.displayMedium,
maxLines = 1,
modifier = Modifier
@@ -153,7 +150,10 @@ fun FormattingScreen(
item("precision_label") {
UnittoListItem(
leadingContent = {
- Icon(Icons.Default.Architecture, stringResource(R.string.settings_precision))
+ Icon(
+ Icons.Default.Architecture,
+ stringResource(R.string.settings_precision)
+ )
},
headlineContent = {
Row(
@@ -265,15 +265,14 @@ private fun PreviewFormattingScreen() {
FormattingScreen(
uiState = FormattingUIState(
- preview = "123456.789",
precision = 16,
separator = Separator.SPACE,
- outputFormat = OutputFormat.PLAIN
+ outputFormat = OutputFormat.PLAIN,
+ formatterSymbols = FormatterSymbols.Spaces
),
onPrecisionChange = { currentPrecision = it },
onSeparatorChange = { currentSeparator = it },
onOutputFormatChange = { currentOutputFormat = it },
navigateUpAction = {},
- togglePreview = {}
)
}
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingUIState.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingUIState.kt
index fb23227d..3a5b6ce0 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingUIState.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingUIState.kt
@@ -21,9 +21,8 @@ package com.sadellie.unitto.feature.settings.formatting
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
data class FormattingUIState(
- val preview: String = "",
- val precision: Int = 0,
- val separator: Int? = null,
- val outputFormat: Int? = null,
- val formatterSymbols: FormatterSymbols = FormatterSymbols.Spaces
+ val precision: Int,
+ val separator: Int,
+ val outputFormat: Int,
+ val formatterSymbols: FormatterSymbols,
)
diff --git a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt
index 7a66d743..94acb92a 100644
--- a/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt
+++ b/feature/settings/src/main/java/com/sadellie/unitto/feature/settings/formatting/FormattingViewModel.kt
@@ -22,64 +22,29 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sadellie.unitto.core.base.MAX_PRECISION
import com.sadellie.unitto.core.ui.common.textfield.AllFormatterSymbols
-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.common.stateIn
import com.sadellie.unitto.data.model.repository.UserPreferencesRepository
import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.coroutines.flow.MutableStateFlow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
-import java.math.BigDecimal
import javax.inject.Inject
-import kotlin.math.ceil
@HiltViewModel
class FormattingViewModel @Inject constructor(
private val userPreferencesRepository: UserPreferencesRepository
) : ViewModel() {
private val _prefs = userPreferencesRepository.formattingPrefs
- private val _fractional = MutableStateFlow(false)
- val uiState = combine(_prefs, _fractional) { mainPrefs, fractional ->
- val formatterSymbols = AllFormatterSymbols.getById(mainPrefs.separator)
-
- return@combine FormattingUIState(
- preview = updatePreview(
- fractional = fractional,
- precision = mainPrefs.digitsPrecision,
- outputFormat = mainPrefs.outputFormat,
- formatterSymbols = formatterSymbols
- ),
+ val uiState = _prefs.map { mainPrefs ->
+ FormattingUIState(
precision = mainPrefs.digitsPrecision,
separator = mainPrefs.separator,
outputFormat = mainPrefs.outputFormat,
- formatterSymbols = formatterSymbols
+ formatterSymbols = AllFormatterSymbols.getById(mainPrefs.separator)
)
}
.stateIn(viewModelScope, null)
- fun togglePreview() = _fractional.update { !it }
-
- private fun updatePreview(
- fractional: Boolean,
- precision: Int,
- outputFormat: Int,
- formatterSymbols: FormatterSymbols
- ): String {
- val bigD = when {
- fractional -> "0.${"1".padStart(precision, '0')}"
- precision > 0 -> "123456.${"789123456".repeat(ceil(precision.toDouble() / 9.0).toInt())}"
- else -> "123456"
- }
-
- return BigDecimal(bigD)
- .format(precision, outputFormat)
- .formatExpression(formatterSymbols)
- }
-
/**
* @see UserPreferencesRepository.updateDigitsPrecision
*/