mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-23 18:50:31 +02:00
Refactor formatter
This commit is contained in:
parent
8d98cbfddf
commit
7150fc9133
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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<String> = 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<String> =
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
@ -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, "")
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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() }
|
||||
)
|
||||
) {
|
||||
|
@ -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
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user