diff --git a/core/base/src/main/java/com/sadellie/unitto/core/base/Token.kt b/core/base/src/main/java/com/sadellie/unitto/core/base/Token.kt index 1d5b1d8f..8ea12f19 100644 --- a/core/base/src/main/java/com/sadellie/unitto/core/base/Token.kt +++ b/core/base/src/main/java/com/sadellie/unitto/core/base/Token.kt @@ -115,8 +115,7 @@ object Token { multiply, multiplyDisplay, plus, minus, minusDisplay, divide, divideDisplay, baseA, baseB, baseC, baseD, baseE, baseF, - _1, _2, _3, _4, _5, _6, _7, _8, _9, _0, - dot + _1, _2, _3, _4, _5, _6, _7, _8, _9, _0 ).sortedByDescending { it.length } } } diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/Formatter.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/Formatter.kt index ac51abdb..4311461b 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/Formatter.kt +++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/Formatter.kt @@ -18,10 +18,9 @@ package com.sadellie.unitto.core.ui -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.stringResource -import com.sadellie.unitto.core.base.Token +import android.content.Context import com.sadellie.unitto.core.base.Separator +import com.sadellie.unitto.core.base.Token import java.math.BigDecimal import java.math.RoundingMode @@ -90,8 +89,6 @@ open class UnittoFormatter { if (input.contains(Token.E)) return input.replace(Token.dot, fractional) var output = input - - // We may receive expressions. Find all numbers in this expression val allNumbers: List = input.getOnlyNumbers() allNumbers.forEach { @@ -116,7 +113,11 @@ open class UnittoFormatter { // Remove grouping // 12345,6789 // Replace fractional with "." because formatter accepts only numbers where fractional is a dot - return format(removeFormat(input)) + return format( + input + .replace(grouping, "") + .replace(fractional, Token.dot) + ) } /** @@ -129,17 +130,67 @@ open class UnittoFormatter { Separator.COMMA -> COMMA else -> SPACE } + .also { if (it == grouping) return input } val sFractional = if (separator == Separator.PERIOD) Token.comma else Token.dot return input - .replace(sGrouping, grouping) + .replace(sGrouping, "\t") .replace(sFractional, fractional) + .replace("\t", grouping) } - fun removeFormat(input: String): String { - return input - .replace(grouping, "") - .replace(fractional, Token.dot) + fun toSeparator(input: String, separator: Int): String { + val output = filterUnknownSymbols(input).replace(fractional, Token.dot) + val sGrouping = when (separator) { + Separator.PERIOD -> PERIOD + Separator.COMMA -> COMMA + else -> SPACE + } + val sFractional = if (separator == Separator.PERIOD) Token.comma else Token.dot + + return format(output) + .replace(grouping, "\t") + .replace(fractional, sFractional) + .replace("\t", sGrouping) + } + + fun removeGrouping(input: String): String = input.replace(grouping, "") + + /** + * Takes [input] and [basicUnit] of the unit to format it to be more human readable. + * + * @return String like "1d 12h 12s". + */ + fun formatTime(context: Context, input: String, basicUnit: BigDecimal?): String { + if (basicUnit == null) return Token._0 + + try { + // Don't need magic if the input is zero + if (BigDecimal(input).compareTo(BigDecimal.ZERO) == 0) return Token._0 + } catch (e: NumberFormatException) { + // For case such as "10-" and "(" + return Token._0 + } + // Attoseconds don't need "magic" + if (basicUnit.compareTo(BigDecimal.ONE) == 0) return formatNumber(input) + + var result = if (input.startsWith(Token.minus)) Token.minus else "" + var remainingSeconds = BigDecimal(input) + .abs() + .multiply(basicUnit) + .setScale(0, RoundingMode.HALF_EVEN) + + if (remainingSeconds.compareTo(BigDecimal.ZERO) == 0) return Token._0 + + timeDivisions.forEach { (timeStr, divider) -> + val division = remainingSeconds.divideAndRemainder(divider) + val time = division.component1() + remainingSeconds = division.component2() + if (time.compareTo(BigDecimal.ZERO) == 1) { + result += "${formatNumber(time.toPlainString())}${context.getString(timeStr)} " + } + } + return result.trimEnd() } /** @@ -170,47 +221,31 @@ open class UnittoFormatter { return (output + remainingPart.replace(".", fractional)) } - /** - * Takes [input] and [basicUnit] of the unit to format it to be more human readable. - * - * @return String like "1d 12h 12s". - */ - @Composable - fun formatTime(input: String, basicUnit: BigDecimal?): String { - if (basicUnit == null) return Token._0 - - try { - // Don't need magic if the input is zero - if (BigDecimal(input).compareTo(BigDecimal.ZERO) == 0) return Token._0 - } catch (e: NumberFormatException) { - // For case such as "10-" and "(" - return Token._0 - } - // Attoseconds don't need "magic" - if (basicUnit.compareTo(BigDecimal.ONE) == 0) return formatNumber(input) - - var result = if (input.startsWith(Token.minus)) Token.minus else "" - var remainingSeconds = BigDecimal(input) - .abs() - .multiply(basicUnit) - .setScale(0, RoundingMode.HALF_EVEN) - - if (remainingSeconds.compareTo(BigDecimal.ZERO) == 0) return Token._0 - - timeDivisions.forEach { (timeStr, divider) -> - val division = remainingSeconds.divideAndRemainder(divider) - val time = division.component1() - remainingSeconds = division.component2() - if (time.compareTo(BigDecimal.ZERO) == 1) { - result += "${formatNumber(time.toPlainString())}${stringResource(timeStr)} " - } - } - return result.trimEnd() - } - /** * @receiver Must be a string with a dot (".") used as a fractional. */ private fun String.getOnlyNumbers(): List = numbersRegex.findAll(this).map(MatchResult::value).toList() + + fun filterUnknownSymbols(input: String): String { + var clearStr = input.replace(" ", "") + var garbage = clearStr + + // String with unknown symbols + Token.knownSymbols.plus(fractional).forEach { + garbage = garbage.replace(it, " ") + } + + // Remove unknown symbols from input + garbage.split(" ").forEach { + clearStr = clearStr.replace(it, "") + } + + clearStr = clearStr + .replace(Token.divide, Token.divideDisplay) + .replace(Token.multiply, Token.multiplyDisplay) + .replace(Token.minus, Token.minusDisplay) + + return clearStr + } } diff --git a/core/ui/src/test/java/com/sadellie/unitto/core/ui/FormatterTest.kt b/core/ui/src/test/java/com/sadellie/unitto/core/ui/FormatterTest.kt index 746c57df..cf8cc458 100644 --- a/core/ui/src/test/java/com/sadellie/unitto/core/ui/FormatterTest.kt +++ b/core/ui/src/test/java/com/sadellie/unitto/core/ui/FormatterTest.kt @@ -18,6 +18,7 @@ package com.sadellie.unitto.core.ui +import android.content.Context import androidx.compose.ui.test.junit4.createComposeRule import com.sadellie.unitto.core.base.Separator import org.junit.Assert.assertEquals @@ -25,6 +26,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.robolectric.RobolectricTestRunner +import org.robolectric.RuntimeEnvironment import java.math.BigDecimal private val formatter = Formatter @@ -93,98 +95,121 @@ class FormatterTest { @Test fun formatTimeTest() { formatter.setSeparator(Separator.SPACES) - composeTestRule.setContent { - var basicValue = BigDecimal.valueOf(1) - assertEquals("-28", formatter.formatTime("-28", basicValue)) - assertEquals("-0.05", formatter.formatTime("-0.05", basicValue)) - assertEquals("0", formatter.formatTime("0", basicValue)) - assertEquals("0", formatter.formatTime("-0", basicValue)) + var basicValue = BigDecimal.valueOf(1) + val mContext: Context = RuntimeEnvironment.getApplication().applicationContext + assertEquals("-28", formatter.formatTime(mContext, "-28", basicValue)) + assertEquals("-0.05", formatter.formatTime(mContext, "-0.05", basicValue)) + assertEquals("0", formatter.formatTime(mContext, "0", basicValue)) + assertEquals("0", formatter.formatTime(mContext, "-0", basicValue)) - basicValue = BigDecimal.valueOf(86_400_000_000_000_000_000_000.0) - assertEquals("-28d", formatter.formatTime("-28", basicValue)) - assertEquals("-1h 12m", formatter.formatTime("-0.05", basicValue)) - assertEquals("0", formatter.formatTime("0", basicValue)) - assertEquals("0", formatter.formatTime("-0", basicValue)) + basicValue = BigDecimal.valueOf(86_400_000_000_000_000_000_000.0) + assertEquals("-28d", formatter.formatTime(mContext, "-28", basicValue)) + assertEquals("-1h 12m", formatter.formatTime(mContext, "-0.05", basicValue)) + assertEquals("0", formatter.formatTime(mContext, "0", basicValue)) + assertEquals("0", formatter.formatTime(mContext, "-0", basicValue)) - // DAYS - basicValue = BigDecimal.valueOf(86_400_000_000_000_000_000_000.0) - assertEquals("12h", formatter.formatTime("0.5", basicValue)) - assertEquals("1h 12m", formatter.formatTime("0.05", basicValue)) - assertEquals("7m 12s", formatter.formatTime("0.005", basicValue)) - assertEquals("28d", formatter.formatTime("28", basicValue)) - assertEquals("90d", formatter.formatTime("90", basicValue)) - assertEquals("90d 12h", formatter.formatTime("90.5", basicValue)) - assertEquals("90d 7m 12s", formatter.formatTime("90.005", basicValue)) + // DAYS + basicValue = BigDecimal.valueOf(86_400_000_000_000_000_000_000.0) + assertEquals("12h", formatter.formatTime(mContext, "0.5", basicValue)) + assertEquals("1h 12m", formatter.formatTime(mContext, "0.05", basicValue)) + assertEquals("7m 12s", formatter.formatTime(mContext, "0.005", basicValue)) + assertEquals("28d", formatter.formatTime(mContext, "28", basicValue)) + assertEquals("90d", formatter.formatTime(mContext, "90", basicValue)) + assertEquals("90d 12h", formatter.formatTime(mContext, "90.5", basicValue)) + assertEquals("90d 7m 12s", formatter.formatTime(mContext, "90.005", basicValue)) - // HOURS - basicValue = BigDecimal.valueOf(3_600_000_000_000_000_000_000.0) - assertEquals("30m", formatter.formatTime("0.5", basicValue)) - assertEquals("3m", formatter.formatTime("0.05", basicValue)) - assertEquals("18s", formatter.formatTime("0.005", basicValue)) - assertEquals("1d 4h", formatter.formatTime("28", basicValue)) - assertEquals("3d 18h", formatter.formatTime("90", basicValue)) - assertEquals("3d 18h 30m", formatter.formatTime("90.5", basicValue)) - assertEquals("3d 18h 18s", formatter.formatTime("90.005", basicValue)) + // HOURS + basicValue = BigDecimal.valueOf(3_600_000_000_000_000_000_000.0) + assertEquals("30m", formatter.formatTime(mContext, "0.5", basicValue)) + assertEquals("3m", formatter.formatTime(mContext, "0.05", basicValue)) + assertEquals("18s", formatter.formatTime(mContext, "0.005", basicValue)) + assertEquals("1d 4h", formatter.formatTime(mContext, "28", basicValue)) + assertEquals("3d 18h", formatter.formatTime(mContext, "90", basicValue)) + assertEquals("3d 18h 30m", formatter.formatTime(mContext, "90.5", basicValue)) + assertEquals("3d 18h 18s", formatter.formatTime(mContext, "90.005", basicValue)) - // MINUTES - basicValue = BigDecimal.valueOf(60_000_000_000_000_000_000.0) - assertEquals("30s", formatter.formatTime("0.5", basicValue)) - assertEquals("3s", formatter.formatTime("0.05", basicValue)) - assertEquals("300ms", formatter.formatTime("0.005", basicValue)) - assertEquals("28m", formatter.formatTime("28", basicValue)) - assertEquals("1h 30m", formatter.formatTime("90", basicValue)) - assertEquals("1h 30m 30s", formatter.formatTime("90.5", basicValue)) - assertEquals("1h 30m 300ms", formatter.formatTime("90.005", basicValue)) + // MINUTES + basicValue = BigDecimal.valueOf(60_000_000_000_000_000_000.0) + assertEquals("30s", formatter.formatTime(mContext, "0.5", basicValue)) + assertEquals("3s", formatter.formatTime(mContext, "0.05", basicValue)) + assertEquals("300ms", formatter.formatTime(mContext, "0.005", basicValue)) + assertEquals("28m", formatter.formatTime(mContext, "28", basicValue)) + assertEquals("1h 30m", formatter.formatTime(mContext, "90", basicValue)) + assertEquals("1h 30m 30s", formatter.formatTime(mContext, "90.5", basicValue)) + assertEquals("1h 30m 300ms", formatter.formatTime(mContext, "90.005", basicValue)) - // SECONDS - basicValue = BigDecimal.valueOf(1_000_000_000_000_000_000) - assertEquals("500ms", formatter.formatTime("0.5", basicValue)) - assertEquals("50ms", formatter.formatTime("0.05", basicValue)) - assertEquals("5ms", formatter.formatTime("0.005", basicValue)) - assertEquals("28s", formatter.formatTime("28", basicValue)) - assertEquals("1m 30s", formatter.formatTime("90", basicValue)) - assertEquals("1m 30s 500ms", formatter.formatTime("90.5", basicValue)) - assertEquals("1m 30s 5ms", formatter.formatTime("90.005", basicValue)) + // SECONDS + basicValue = BigDecimal.valueOf(1_000_000_000_000_000_000) + assertEquals("500ms", formatter.formatTime(mContext, "0.5", basicValue)) + assertEquals("50ms", formatter.formatTime(mContext, "0.05", basicValue)) + assertEquals("5ms", formatter.formatTime(mContext, "0.005", basicValue)) + assertEquals("28s", formatter.formatTime(mContext, "28", basicValue)) + assertEquals("1m 30s", formatter.formatTime(mContext, "90", basicValue)) + assertEquals("1m 30s 500ms", formatter.formatTime(mContext, "90.5", basicValue)) + assertEquals("1m 30s 5ms", formatter.formatTime(mContext, "90.005", basicValue)) - // MILLISECONDS - basicValue = BigDecimal.valueOf(1_000_000_000_000_000) - assertEquals("500µs", formatter.formatTime("0.5", basicValue)) - assertEquals("50µs", formatter.formatTime("0.05", basicValue)) - assertEquals("5µs", formatter.formatTime("0.005", basicValue)) - assertEquals("28ms", formatter.formatTime("28", basicValue)) - assertEquals("90ms", formatter.formatTime("90", basicValue)) - assertEquals("90ms 500µs", formatter.formatTime("90.5", basicValue)) - assertEquals("90ms 5µs", formatter.formatTime("90.005", basicValue)) + // MILLISECONDS + basicValue = BigDecimal.valueOf(1_000_000_000_000_000) + assertEquals("500µs", formatter.formatTime(mContext, "0.5", basicValue)) + assertEquals("50µs", formatter.formatTime(mContext, "0.05", basicValue)) + assertEquals("5µs", formatter.formatTime(mContext, "0.005", basicValue)) + assertEquals("28ms", formatter.formatTime(mContext, "28", basicValue)) + assertEquals("90ms", formatter.formatTime(mContext, "90", basicValue)) + assertEquals("90ms 500µs", formatter.formatTime(mContext, "90.5", basicValue)) + assertEquals("90ms 5µs", formatter.formatTime(mContext, "90.005", basicValue)) - // MICROSECONDS - basicValue = BigDecimal.valueOf(1_000_000_000_000) - assertEquals("500ns", formatter.formatTime("0.5", basicValue)) - assertEquals("50ns", formatter.formatTime("0.05", basicValue)) - assertEquals("5ns", formatter.formatTime("0.005", basicValue)) - assertEquals("28µs", formatter.formatTime("28", basicValue)) - assertEquals("90µs", formatter.formatTime("90", basicValue)) - assertEquals("90µs 500ns", formatter.formatTime("90.5", basicValue)) - assertEquals("90µs 5ns", formatter.formatTime("90.005", basicValue)) + // MICROSECONDS + basicValue = BigDecimal.valueOf(1_000_000_000_000) + assertEquals("500ns", formatter.formatTime(mContext, "0.5", basicValue)) + assertEquals("50ns", formatter.formatTime(mContext, "0.05", basicValue)) + assertEquals("5ns", formatter.formatTime(mContext, "0.005", basicValue)) + assertEquals("28µs", formatter.formatTime(mContext, "28", basicValue)) + assertEquals("90µs", formatter.formatTime(mContext, "90", basicValue)) + assertEquals("90µs 500ns", formatter.formatTime(mContext, "90.5", basicValue)) + assertEquals("90µs 5ns", formatter.formatTime(mContext, "90.005", basicValue)) - // NANOSECONDS - basicValue = BigDecimal.valueOf(1_000_000_000) - assertEquals("500 000 000as", formatter.formatTime("0.5", basicValue)) - assertEquals("50 000 000as", formatter.formatTime("0.05", basicValue)) - assertEquals("5 000 000as", formatter.formatTime("0.005", basicValue)) - assertEquals("28ns", formatter.formatTime("28", basicValue)) - assertEquals("90ns", formatter.formatTime("90", basicValue)) - assertEquals("90ns 500 000 000as", formatter.formatTime("90.5", basicValue)) - assertEquals("90ns 5 000 000as", formatter.formatTime("90.005", basicValue)) + // NANOSECONDS + basicValue = BigDecimal.valueOf(1_000_000_000) + assertEquals("500 000 000as", formatter.formatTime(mContext, "0.5", basicValue)) + assertEquals("50 000 000as", formatter.formatTime(mContext, "0.05", basicValue)) + assertEquals("5 000 000as", formatter.formatTime(mContext, "0.005", basicValue)) + assertEquals("28ns", formatter.formatTime(mContext, "28", basicValue)) + assertEquals("90ns", formatter.formatTime(mContext, "90", basicValue)) + assertEquals("90ns 500 000 000as", formatter.formatTime(mContext, "90.5", basicValue)) + assertEquals("90ns 5 000 000as", formatter.formatTime(mContext, "90.005", basicValue)) - // ATTOSECONDS - basicValue = BigDecimal.valueOf(1) - assertEquals("0.5", formatter.formatTime("0.5", basicValue)) - assertEquals("0.05", formatter.formatTime("0.05", basicValue)) - assertEquals("0.005", formatter.formatTime("0.005", basicValue)) - assertEquals("28", formatter.formatTime("28", basicValue)) - assertEquals("90", formatter.formatTime("90", basicValue)) - assertEquals("90.5", formatter.formatTime("90.5", basicValue)) - assertEquals("90.005", formatter.formatTime("90.005", basicValue)) - } + // ATTOSECONDS + basicValue = BigDecimal.valueOf(1) + assertEquals("0.5", formatter.formatTime(mContext, "0.5", basicValue)) + assertEquals("0.05", formatter.formatTime(mContext, "0.05", basicValue)) + assertEquals("0.005", formatter.formatTime(mContext, "0.005", basicValue)) + assertEquals("28", formatter.formatTime(mContext, "28", basicValue)) + assertEquals("90", formatter.formatTime(mContext, "90", basicValue)) + assertEquals("90.5", formatter.formatTime(mContext, "90.5", basicValue)) + assertEquals("90.005", formatter.formatTime(mContext, "90.005", basicValue)) + } + + @Test + fun fromSeparatorToSpacesTest() { + formatter.setSeparator(Separator.SPACES) + assertEquals("123 456.789", formatter.fromSeparator("123,456.789", Separator.COMMA)) + assertEquals("123 456.789", formatter.fromSeparator("123 456.789", Separator.SPACES)) + assertEquals("123 456.789", formatter.fromSeparator("123.456,789", Separator.PERIOD)) + } + + @Test + fun fromSeparatorToPeriodTest() { + formatter.setSeparator(Separator.PERIOD) + assertEquals("123.456,789", formatter.fromSeparator("123,456.789", Separator.COMMA)) + assertEquals("123.456,789", formatter.fromSeparator("123 456.789", Separator.SPACES)) + assertEquals("123.456,789", formatter.fromSeparator("123.456,789", Separator.PERIOD)) + } + + @Test + fun fromSeparatorToCommaTest() { + formatter.setSeparator(Separator.COMMA) + assertEquals("123,456.789", formatter.fromSeparator("123,456.789", Separator.COMMA)) + assertEquals("123,456.789", formatter.fromSeparator("123 456.789", Separator.SPACES)) + assertEquals("123,456.789", formatter.fromSeparator("123.456,789", Separator.PERIOD)) } } \ No newline at end of file diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt index 7a4a4e81..01b8b82f 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt +++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/CalculatorScreen.kt @@ -100,7 +100,9 @@ internal fun CalculatorRoute( // This method is called immediately after copying formatted text, we replace it with the // the unformatted version. clipboardManager.setText( - AnnotatedString(Formatter.removeFormat(clipboardText.text)) + AnnotatedString( + clipboardText.text.replace(Formatter.grouping, "") + ) ) } diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/TextFieldController.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/TextFieldController.kt index f88d5a1f..63d38a88 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/TextFieldController.kt +++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/TextFieldController.kt @@ -128,27 +128,7 @@ class TextFieldController @Inject constructor() { private fun String.fixFormat(): String = localFormatter.reFormat(this) - private fun String.filterUnknownSymbols(): String { - var clearStr = this.replace(" ", "") - var garbage = clearStr - - // String with unknown symbols - Token.knownSymbols.forEach { - garbage = garbage.replace(it, " ") - } - - // Remove unknown symbols from input - garbage.split(" ").forEach { - clearStr = clearStr.replace(it, "") - } - - clearStr = clearStr - .replace(Token.divide, Token.divideDisplay) - .replace(Token.multiply, Token.multiplyDisplay) - .replace(Token.minus, Token.minusDisplay) - - return clearStr - } + private fun String.filterUnknownSymbols() = localFormatter.filterUnknownSymbols(this) inner class CursorFixer { private val illegalTokens by lazy { diff --git a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/InputTextField.kt b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/InputTextField.kt index 72fbe3b5..e225f790 100644 --- a/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/InputTextField.kt +++ b/feature/calculator/src/main/java/com/sadellie/unitto/feature/calculator/components/InputTextField.kt @@ -31,6 +31,7 @@ import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.platform.LocalTextInputService import androidx.compose.ui.platform.LocalTextToolbar import androidx.compose.ui.platform.LocalView +import androidx.compose.ui.text.AnnotatedString import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import com.sadellie.unitto.core.base.Separator @@ -46,6 +47,7 @@ internal fun InputTextField( cutCallback: () -> Unit ) { val clipboardManager = LocalClipboardManager.current + val formattedInput: TextFieldValue by remember(value) { derivedStateOf { value.copy( @@ -57,7 +59,11 @@ internal fun InputTextField( } fun copyToClipboard() = clipboardManager.setText( - formattedInput.annotatedString.subSequence(formattedInput.selection) + AnnotatedString( + Formatter.removeGrouping( + formattedInput.annotatedString.subSequence(formattedInput.selection).text + ) + ) ) CompositionLocalProvider( @@ -65,7 +71,13 @@ internal fun InputTextField( LocalTextToolbar provides UnittoTextToolbar( view = LocalView.current, copyCallback = ::copyToClipboard, - pasteCallback = { pasteCallback(clipboardManager.getText()?.text ?: "") }, + pasteCallback = { + pasteCallback( + Formatter.toSeparator( + clipboardManager.getText()?.text ?: "", Separator.COMMA + ) + ) + }, cutCallback = { copyToClipboard(); cutCallback() } ) ) { diff --git a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/TopScreen.kt b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/TopScreen.kt index 9af92fe6..26a5d7d9 100644 --- a/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/TopScreen.kt +++ b/feature/converter/src/main/java/com/sadellie/unitto/feature/converter/components/TopScreen.kt @@ -38,6 +38,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.sadellie.unitto.core.ui.Formatter @@ -88,6 +89,7 @@ internal fun TopScreenPart( targetValue = if (swapped) 0f else 180f, animationSpec = tween(easing = FastOutSlowInEasing) ) + val mContext = LocalContext.current Column( modifier = modifier, @@ -115,6 +117,7 @@ internal fun TopScreenPart( converterMode == ConverterMode.BASE -> outputValue.uppercase() formatTime and (unitTo?.group == UnitGroup.TIME) -> { Formatter.formatTime( + context = mContext, input = calculatedValue ?: inputValue, basicUnit = unitFrom?.basicUnit )