mirror of
https://github.com/Myzel394/NumberHub.git
synced 2025-06-18 16:25:27 +02:00
Prepare for text2
Enabled physical keyboard support (#148), but not tested
This commit is contained in:
parent
bf9bf37812
commit
5c81a1c675
@ -18,37 +18,46 @@
|
|||||||
|
|
||||||
package com.sadellie.unitto.core.ui.common.textfield
|
package com.sadellie.unitto.core.ui.common.textfield
|
||||||
|
|
||||||
|
import android.content.ClipData
|
||||||
import androidx.compose.ui.platform.ClipboardManager
|
import androidx.compose.ui.platform.ClipboardManager
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
|
||||||
import com.sadellie.unitto.core.base.Token
|
import com.sadellie.unitto.core.base.Token
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copy value to clipboard with fractional symbols.
|
* Unformatted values are expected. Basically what BigDecimal and Expression parser use.
|
||||||
*
|
*
|
||||||
* Example:
|
* @property formatterSymbols Current [FormatterSymbols].
|
||||||
* "123456.789" will be copied as "123456,789"
|
* @property clipboardManager [android.content.ClipboardManager] provided by system.
|
||||||
*
|
|
||||||
* @param value Internal [TextFieldValue] without formatting with [Token.Digit.dot] as fractional.
|
|
||||||
*/
|
*/
|
||||||
internal fun ClipboardManager.copyWithFractional(
|
internal class ExpressionClipboardManager(
|
||||||
value: TextFieldValue,
|
private val formatterSymbols: FormatterSymbols,
|
||||||
formatterSymbols: FormatterSymbols
|
private val clipboardManager: android.content.ClipboardManager
|
||||||
) = this.setText(
|
): ClipboardManager {
|
||||||
AnnotatedString(
|
override fun setText(annotatedString: AnnotatedString) = clipboardManager.setPrimaryClip(
|
||||||
value.annotatedString
|
ClipData.newPlainText(
|
||||||
.subSequence(value.selection)
|
PLAIN_TEXT_LABEL,
|
||||||
.text
|
annotatedString
|
||||||
.replace(Token.Digit.dot, formatterSymbols.fractional)
|
.text
|
||||||
|
.replace(Token.Digit.dot, formatterSymbols.fractional)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
internal fun ClipboardManager.copy(value: TextFieldValue) = this.setText(
|
override fun getText(): AnnotatedString? = clipboardManager.primaryClip?.let { primaryClip ->
|
||||||
AnnotatedString(
|
if (primaryClip.itemCount > 0) {
|
||||||
value.annotatedString
|
val clipText = primaryClip.getItemAt(0)?.text ?:return@let null
|
||||||
.subSequence(value.selection)
|
|
||||||
.text
|
clipText
|
||||||
)
|
.toString()
|
||||||
)
|
.toAnnotatedString()
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasText() =
|
||||||
|
clipboardManager.primaryClipDescription?.hasMimeType("text/*") ?: false
|
||||||
|
}
|
||||||
|
|
||||||
internal const val PLAIN_TEXT_LABEL = "plain text"
|
internal const val PLAIN_TEXT_LABEL = "plain text"
|
||||||
|
|
||||||
|
private fun CharSequence.toAnnotatedString(): AnnotatedString = AnnotatedString(this.toString())
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
package com.sadellie.unitto.core.ui.common.textfield
|
package com.sadellie.unitto.core.ui.common.textfield
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import android.content.Context
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
@ -32,27 +32,19 @@ import androidx.compose.runtime.CompositionLocalProvider
|
|||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
|
||||||
import androidx.compose.ui.focus.focusRequester
|
|
||||||
import androidx.compose.ui.geometry.Offset
|
|
||||||
import androidx.compose.ui.geometry.Rect
|
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.platform.LocalClipboardManager
|
import androidx.compose.ui.platform.LocalClipboardManager
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.platform.LocalTextInputService
|
import androidx.compose.ui.platform.LocalTextInputService
|
||||||
import androidx.compose.ui.platform.LocalTextToolbar
|
|
||||||
import androidx.compose.ui.platform.LocalView
|
|
||||||
import androidx.compose.ui.platform.TextToolbar
|
|
||||||
import androidx.compose.ui.text.TextLayoutResult
|
import androidx.compose.ui.text.TextLayoutResult
|
||||||
import androidx.compose.ui.text.TextRange
|
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.text.input.VisualTransformation
|
import androidx.compose.ui.text.input.VisualTransformation
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.TextUnit
|
import androidx.compose.ui.unit.TextUnit
|
||||||
import com.sadellie.unitto.core.ui.common.autosize.AutoSizeTextStyleBox
|
import com.sadellie.unitto.core.ui.common.autosize.AutoSizeTextStyleBox
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.texttoolbar.UnittoTextToolbar
|
|
||||||
import com.sadellie.unitto.core.ui.theme.LocalNumberTypography
|
import com.sadellie.unitto.core.ui.theme.LocalNumberTypography
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -60,105 +52,86 @@ fun ExpressionTextField(
|
|||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
value: TextFieldValue,
|
value: TextFieldValue,
|
||||||
minRatio: Float = 1f,
|
minRatio: Float = 1f,
|
||||||
cutCallback: () -> Unit = {},
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
pasteCallback: (String) -> Unit = {},
|
|
||||||
onCursorChange: (TextRange) -> Unit,
|
|
||||||
textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
formatterSymbols: FormatterSymbols,
|
formatterSymbols: FormatterSymbols,
|
||||||
readOnly: Boolean = false,
|
readOnly: Boolean = false,
|
||||||
placeholder: String = "",
|
placeholder: String = "",
|
||||||
) {
|
) {
|
||||||
val localView = LocalView.current
|
val context = LocalContext.current
|
||||||
val clipboardManager = LocalClipboardManager.current
|
val clipboardManager = remember(formatterSymbols) {
|
||||||
val expressionTransformer = remember(formatterSymbols) { ExpressionTransformer(formatterSymbols) }
|
ExpressionClipboardManager(
|
||||||
|
formatterSymbols = formatterSymbols,
|
||||||
fun copyCallback() {
|
clipboardManager = context.getSystemService(Context.CLIPBOARD_SERVICE)
|
||||||
clipboardManager.copyWithFractional(value, formatterSymbols)
|
as android.content.ClipboardManager
|
||||||
onCursorChange(TextRange(value.selection.end))
|
)
|
||||||
|
}
|
||||||
|
val expressionTransformer = remember(formatterSymbols) {
|
||||||
|
ExpressionTransformer(formatterSymbols)
|
||||||
}
|
}
|
||||||
|
|
||||||
val textToolbar: UnittoTextToolbar = if (readOnly) {
|
CompositionLocalProvider(
|
||||||
UnittoTextToolbar(
|
LocalClipboardManager provides clipboardManager
|
||||||
view = localView,
|
) {
|
||||||
copyCallback = ::copyCallback,
|
AutoSizeTextField(
|
||||||
)
|
modifier = modifier,
|
||||||
} else {
|
value = value,
|
||||||
UnittoTextToolbar(
|
onValueChange = {
|
||||||
view = localView,
|
onValueChange(it.copy(text = it.text.clearAndFilterExpression(formatterSymbols)))
|
||||||
copyCallback = ::copyCallback,
|
|
||||||
pasteCallback = {
|
|
||||||
pasteCallback(clipboardManager.getText()?.text?.clearAndFilterExpression(formatterSymbols) ?: "")
|
|
||||||
},
|
},
|
||||||
cutCallback = {
|
placeholder = placeholder,
|
||||||
clipboardManager.copyWithFractional(value, formatterSymbols)
|
readOnly = readOnly,
|
||||||
cutCallback()
|
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
|
||||||
}
|
visualTransformation = expressionTransformer,
|
||||||
|
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
|
||||||
|
minRatio = minRatio
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun NumberBaseTextField(
|
||||||
|
modifier: Modifier,
|
||||||
|
value: TextFieldValue,
|
||||||
|
minRatio: Float = 1f,
|
||||||
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
|
textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
readOnly: Boolean = false,
|
||||||
|
placeholder: String = "",
|
||||||
|
) {
|
||||||
AutoSizeTextField(
|
AutoSizeTextField(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
value = value,
|
value = value,
|
||||||
onValueChange = { onCursorChange(it.selection) },
|
onValueChange = {
|
||||||
|
onValueChange(it.copy(text = it.text.clearAndFilterNumberBase()))
|
||||||
|
},
|
||||||
placeholder = placeholder,
|
placeholder = placeholder,
|
||||||
textToolbar = textToolbar,
|
|
||||||
readOnly = readOnly,
|
readOnly = readOnly,
|
||||||
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
|
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
|
||||||
visualTransformation = expressionTransformer,
|
|
||||||
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
|
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
|
||||||
minRatio = minRatio
|
minRatio = minRatio
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun UnformattedTextField(
|
fun SimpleTextField(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
value: TextFieldValue,
|
value: TextFieldValue,
|
||||||
minRatio: Float = 1f,
|
minRatio: Float = 1f,
|
||||||
cutCallback: () -> Unit = {},
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
pasteCallback: (String) -> Unit = {},
|
|
||||||
onCursorChange: (TextRange) -> Unit,
|
|
||||||
textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
textColor: Color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
readOnly: Boolean = false,
|
readOnly: Boolean = false,
|
||||||
placeholder: String = "",
|
placeholder: String = "",
|
||||||
) {
|
) {
|
||||||
val localView = LocalView.current
|
|
||||||
val clipboardManager = LocalClipboardManager.current
|
|
||||||
fun copyCallback() {
|
|
||||||
clipboardManager.copy(value)
|
|
||||||
onCursorChange(TextRange(value.selection.end))
|
|
||||||
}
|
|
||||||
|
|
||||||
val textToolbar: UnittoTextToolbar = remember(readOnly) {
|
|
||||||
if (readOnly) {
|
|
||||||
UnittoTextToolbar(
|
|
||||||
view = localView,
|
|
||||||
copyCallback = ::copyCallback,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
UnittoTextToolbar(
|
|
||||||
view = localView,
|
|
||||||
copyCallback = ::copyCallback,
|
|
||||||
pasteCallback = {
|
|
||||||
pasteCallback(clipboardManager.getText()?.text?.clearAndFilterNumberBase() ?: "")
|
|
||||||
},
|
|
||||||
cutCallback = {
|
|
||||||
clipboardManager.copy(value)
|
|
||||||
cutCallback()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoSizeTextField(
|
AutoSizeTextField(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
value = value,
|
value = value,
|
||||||
onValueChange = { onCursorChange(it.selection) },
|
onValueChange = onValueChange,
|
||||||
placeholder = placeholder,
|
placeholder = placeholder,
|
||||||
textToolbar = textToolbar,
|
|
||||||
readOnly = readOnly,
|
readOnly = readOnly,
|
||||||
textStyle = LocalNumberTypography.current.displayLarge.copy(color = textColor),
|
textStyle = LocalNumberTypography.current.displayLarge.copy(textColor),
|
||||||
minRatio = minRatio,
|
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurfaceVariant),
|
||||||
|
minRatio = minRatio
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,7 +139,6 @@ fun UnformattedTextField(
|
|||||||
* Based on: https://gist.github.com/inidamleader/b594d35362ebcf3cedf81055df519300
|
* Based on: https://gist.github.com/inidamleader/b594d35362ebcf3cedf81055df519300
|
||||||
*
|
*
|
||||||
* @param placeholder Placeholder text, shown when [value] is empty.
|
* @param placeholder Placeholder text, shown when [value] is empty.
|
||||||
* @param textToolbar [TextToolbar] with modified actions in menu.
|
|
||||||
* @param alignment The alignment of the text within its container.
|
* @param alignment The alignment of the text within its container.
|
||||||
* @see [BasicTextField]
|
* @see [BasicTextField]
|
||||||
* @see [AutoSizeTextStyleBox]
|
* @see [AutoSizeTextStyleBox]
|
||||||
@ -177,7 +149,6 @@ private fun AutoSizeTextField(
|
|||||||
value: TextFieldValue,
|
value: TextFieldValue,
|
||||||
onValueChange: (TextFieldValue) -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
placeholder: String? = null,
|
placeholder: String? = null,
|
||||||
textToolbar: TextToolbar = LocalTextToolbar.current,
|
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
readOnly: Boolean = false,
|
readOnly: Boolean = false,
|
||||||
textStyle: TextStyle = TextStyle.Default,
|
textStyle: TextStyle = TextStyle.Default,
|
||||||
@ -206,28 +177,14 @@ private fun AutoSizeTextField(
|
|||||||
) {
|
) {
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
LocalTextInputService provides null,
|
LocalTextInputService provides null,
|
||||||
LocalTextToolbar provides textToolbar
|
|
||||||
) {
|
) {
|
||||||
val currentTextToolbar = LocalTextToolbar.current
|
|
||||||
val style = LocalTextStyle.current
|
val style = LocalTextStyle.current
|
||||||
val focusRequester = remember { FocusRequester() }
|
|
||||||
|
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
value = value,
|
value = value,
|
||||||
onValueChange = onValueChange,
|
onValueChange = onValueChange,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth(),
|
||||||
.focusRequester(focusRequester)
|
|
||||||
.clickable(
|
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
|
||||||
indication = null,
|
|
||||||
onClick = {
|
|
||||||
currentTextToolbar.hide()
|
|
||||||
focusRequester.requestFocus()
|
|
||||||
onValueChange(value.copy(selection = TextRange.Zero))
|
|
||||||
currentTextToolbar.showMenu(Rect(Offset.Zero, 0f))
|
|
||||||
}
|
|
||||||
),
|
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
readOnly = readOnly,
|
readOnly = readOnly,
|
||||||
textStyle = style,
|
textStyle = style,
|
||||||
|
@ -46,11 +46,12 @@ class CalculatorScreenTest {
|
|||||||
addTokens = {},
|
addTokens = {},
|
||||||
clearInput = {},
|
clearInput = {},
|
||||||
deleteTokens = {},
|
deleteTokens = {},
|
||||||
onCursorChange = {},
|
onValueChange = {},
|
||||||
toggleCalculatorMode = {},
|
toggleCalculatorMode = {},
|
||||||
equal = {},
|
equal = {},
|
||||||
clearHistory = {},
|
clearHistory = {},
|
||||||
addBracket = {}
|
addBracket = {},
|
||||||
|
onDelete = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -69,7 +70,6 @@ class CalculatorScreenTest {
|
|||||||
outputFormat = OutputFormat.PLAIN,
|
outputFormat = OutputFormat.PLAIN,
|
||||||
formatterSymbols = FormatterSymbols.Spaces,
|
formatterSymbols = FormatterSymbols.Spaces,
|
||||||
history = emptyList(),
|
history = emptyList(),
|
||||||
allowVibration = false,
|
|
||||||
middleZero = false,
|
middleZero = false,
|
||||||
acButton = true,
|
acButton = true,
|
||||||
partialHistoryView = true
|
partialHistoryView = true
|
||||||
@ -79,11 +79,12 @@ class CalculatorScreenTest {
|
|||||||
addTokens = {},
|
addTokens = {},
|
||||||
clearInput = {},
|
clearInput = {},
|
||||||
deleteTokens = {},
|
deleteTokens = {},
|
||||||
onCursorChange = {},
|
onValueChange = {},
|
||||||
toggleCalculatorMode = {},
|
toggleCalculatorMode = {},
|
||||||
equal = {},
|
equal = {},
|
||||||
clearHistory = {},
|
clearHistory = {},
|
||||||
addBracket = {}
|
addBracket = {},
|
||||||
|
onDelete = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +104,6 @@ class CalculatorScreenTest {
|
|||||||
outputFormat = OutputFormat.PLAIN,
|
outputFormat = OutputFormat.PLAIN,
|
||||||
formatterSymbols = FormatterSymbols.Spaces,
|
formatterSymbols = FormatterSymbols.Spaces,
|
||||||
history = emptyList(),
|
history = emptyList(),
|
||||||
allowVibration = false,
|
|
||||||
middleZero = false,
|
middleZero = false,
|
||||||
acButton = true,
|
acButton = true,
|
||||||
partialHistoryView = true
|
partialHistoryView = true
|
||||||
@ -113,11 +113,12 @@ class CalculatorScreenTest {
|
|||||||
addTokens = {},
|
addTokens = {},
|
||||||
clearInput = {},
|
clearInput = {},
|
||||||
deleteTokens = {},
|
deleteTokens = {},
|
||||||
onCursorChange = {},
|
onValueChange = {},
|
||||||
toggleCalculatorMode = {},
|
toggleCalculatorMode = {},
|
||||||
equal = {},
|
equal = {},
|
||||||
clearHistory = {},
|
clearHistory = {},
|
||||||
addBracket = {}
|
addBracket = {},
|
||||||
|
onDelete = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,6 @@ import androidx.compose.ui.platform.LocalFocusManager
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.semantics.semantics
|
import androidx.compose.ui.semantics.semantics
|
||||||
import androidx.compose.ui.semantics.testTag
|
import androidx.compose.ui.semantics.testTag
|
||||||
import androidx.compose.ui.text.TextRange
|
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
@ -97,7 +96,7 @@ internal fun CalculatorRoute(
|
|||||||
addTokens = viewModel::addTokens,
|
addTokens = viewModel::addTokens,
|
||||||
clearInput = viewModel::clearInput,
|
clearInput = viewModel::clearInput,
|
||||||
deleteTokens = viewModel::deleteTokens,
|
deleteTokens = viewModel::deleteTokens,
|
||||||
onCursorChange = viewModel::onCursorChange,
|
onValueChange = viewModel::updateInput,
|
||||||
toggleCalculatorMode = viewModel::updateRadianMode,
|
toggleCalculatorMode = viewModel::updateRadianMode,
|
||||||
equal = viewModel::equal,
|
equal = viewModel::equal,
|
||||||
clearHistory = viewModel::clearHistory,
|
clearHistory = viewModel::clearHistory,
|
||||||
@ -115,7 +114,7 @@ internal fun CalculatorScreen(
|
|||||||
addBracket: () -> Unit,
|
addBracket: () -> Unit,
|
||||||
clearInput: () -> Unit,
|
clearInput: () -> Unit,
|
||||||
deleteTokens: () -> Unit,
|
deleteTokens: () -> Unit,
|
||||||
onCursorChange: (TextRange) -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
toggleCalculatorMode: (Boolean) -> Unit,
|
toggleCalculatorMode: (Boolean) -> Unit,
|
||||||
equal: () -> Unit,
|
equal: () -> Unit,
|
||||||
clearHistory: () -> Unit,
|
clearHistory: () -> Unit,
|
||||||
@ -130,7 +129,7 @@ internal fun CalculatorScreen(
|
|||||||
addSymbol = addTokens,
|
addSymbol = addTokens,
|
||||||
clearSymbols = clearInput,
|
clearSymbols = clearInput,
|
||||||
deleteSymbol = deleteTokens,
|
deleteSymbol = deleteTokens,
|
||||||
onCursorChange = onCursorChange,
|
onValueChange = onValueChange,
|
||||||
toggleAngleMode = { toggleCalculatorMode(!uiState.radianMode) },
|
toggleAngleMode = { toggleCalculatorMode(!uiState.radianMode) },
|
||||||
equal = equal,
|
equal = equal,
|
||||||
clearHistory = clearHistory,
|
clearHistory = clearHistory,
|
||||||
@ -149,7 +148,7 @@ private fun Ready(
|
|||||||
addBracket: () -> Unit,
|
addBracket: () -> Unit,
|
||||||
clearSymbols: () -> Unit,
|
clearSymbols: () -> Unit,
|
||||||
deleteSymbol: () -> Unit,
|
deleteSymbol: () -> Unit,
|
||||||
onCursorChange: (TextRange) -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
toggleAngleMode: () -> Unit,
|
toggleAngleMode: () -> Unit,
|
||||||
equal: () -> Unit,
|
equal: () -> Unit,
|
||||||
clearHistory: () -> Unit,
|
clearHistory: () -> Unit,
|
||||||
@ -266,9 +265,7 @@ private fun Ready(
|
|||||||
),
|
),
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
input = uiState.input,
|
input = uiState.input,
|
||||||
deleteSymbol = deleteSymbol,
|
onValueChange = onValueChange,
|
||||||
addSymbol = addSymbol,
|
|
||||||
onCursorChange = onCursorChange,
|
|
||||||
output = uiState.output
|
output = uiState.output
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -379,7 +376,7 @@ private fun PreviewCalculatorScreen() {
|
|||||||
addTokens = {},
|
addTokens = {},
|
||||||
clearInput = {},
|
clearInput = {},
|
||||||
deleteTokens = {},
|
deleteTokens = {},
|
||||||
onCursorChange = {},
|
onValueChange = {},
|
||||||
toggleCalculatorMode = {},
|
toggleCalculatorMode = {},
|
||||||
equal = {},
|
equal = {},
|
||||||
clearHistory = {},
|
clearHistory = {},
|
||||||
|
@ -166,11 +166,11 @@ internal class CalculatorViewModel @Inject constructor(
|
|||||||
TextFieldValue()
|
TextFieldValue()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onCursorChange(selection: TextRange) = _input.update {
|
fun updateInput(value: TextFieldValue) = _input.update {
|
||||||
// Without this line: will place token (even in the middle of the input) and place cursor at
|
// Without this line: will place token (even in the middle of the input) and place cursor at
|
||||||
// the end. This line also removes fractional output once user touches input text field
|
// the end. This line also removes fractional output once user touches input text field
|
||||||
_equalClicked.update { false }
|
_equalClicked.update { false }
|
||||||
it.copy(selection = selection)
|
value
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateRadianMode(newValue: Boolean) = viewModelScope.launch {
|
fun updateRadianMode(newValue: Boolean) = viewModelScope.launch {
|
||||||
|
@ -37,14 +37,13 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.semantics.semantics
|
import androidx.compose.ui.semantics.semantics
|
||||||
import androidx.compose.ui.semantics.testTag
|
import androidx.compose.ui.semantics.testTag
|
||||||
import androidx.compose.ui.text.TextRange
|
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.sadellie.unitto.core.ui.LocalWindowSize
|
import com.sadellie.unitto.core.ui.LocalWindowSize
|
||||||
import com.sadellie.unitto.core.ui.WindowHeightSizeClass
|
import com.sadellie.unitto.core.ui.WindowHeightSizeClass
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField
|
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.UnformattedTextField
|
import com.sadellie.unitto.core.ui.common.textfield.SimpleTextField
|
||||||
import com.sadellie.unitto.feature.calculator.CalculationResult
|
import com.sadellie.unitto.feature.calculator.CalculationResult
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
@ -52,9 +51,7 @@ fun TextBox(
|
|||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
formatterSymbols: FormatterSymbols,
|
formatterSymbols: FormatterSymbols,
|
||||||
input: TextFieldValue,
|
input: TextFieldValue,
|
||||||
deleteSymbol: () -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
addSymbol: (String) -> Unit,
|
|
||||||
onCursorChange: (TextRange) -> Unit,
|
|
||||||
output: CalculationResult,
|
output: CalculationResult,
|
||||||
) {
|
) {
|
||||||
Column(
|
Column(
|
||||||
@ -77,9 +74,7 @@ fun TextBox(
|
|||||||
.padding(horizontal = 8.dp),
|
.padding(horizontal = 8.dp),
|
||||||
value = input,
|
value = input,
|
||||||
minRatio = 0.5f,
|
minRatio = 0.5f,
|
||||||
cutCallback = deleteSymbol,
|
onValueChange = onValueChange,
|
||||||
pasteCallback = addSymbol,
|
|
||||||
onCursorChange = onCursorChange,
|
|
||||||
formatterSymbols = formatterSymbols
|
formatterSymbols = formatterSymbols
|
||||||
)
|
)
|
||||||
if (LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact) {
|
if (LocalWindowSize.current.heightSizeClass > WindowHeightSizeClass.Compact) {
|
||||||
@ -105,9 +100,9 @@ fun TextBox(
|
|||||||
.padding(horizontal = 8.dp),
|
.padding(horizontal = 8.dp),
|
||||||
value = outputTF,
|
value = outputTF,
|
||||||
minRatio = 0.8f,
|
minRatio = 0.8f,
|
||||||
onCursorChange = { outputTF = outputTF.copy(selection = it) },
|
onValueChange = { outputTF = it },
|
||||||
formatterSymbols = formatterSymbols,
|
|
||||||
textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.6f),
|
textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.6f),
|
||||||
|
formatterSymbols = formatterSymbols,
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -123,36 +118,36 @@ fun TextBox(
|
|||||||
.padding(horizontal = 8.dp),
|
.padding(horizontal = 8.dp),
|
||||||
value = outputTF,
|
value = outputTF,
|
||||||
minRatio = 0.8f,
|
minRatio = 0.8f,
|
||||||
onCursorChange = { outputTF = outputTF.copy(selection = it) },
|
onValueChange = { outputTF = it },
|
||||||
formatterSymbols = formatterSymbols,
|
|
||||||
textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.6f),
|
textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(0.6f),
|
||||||
|
formatterSymbols = formatterSymbols,
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is CalculationResult.DivideByZeroError -> {
|
is CalculationResult.DivideByZeroError -> {
|
||||||
UnformattedTextField(
|
SimpleTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(2f)
|
.weight(2f)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 8.dp),
|
.padding(horizontal = 8.dp),
|
||||||
value = TextFieldValue(stringResource(output.label)),
|
value = TextFieldValue(stringResource(output.label)),
|
||||||
minRatio = 0.8f,
|
minRatio = 0.8f,
|
||||||
onCursorChange = {},
|
onValueChange = {},
|
||||||
textColor = MaterialTheme.colorScheme.error,
|
textColor = MaterialTheme.colorScheme.error,
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is CalculationResult.Error -> {
|
is CalculationResult.Error -> {
|
||||||
UnformattedTextField(
|
SimpleTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(2f)
|
.weight(2f)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.padding(horizontal = 8.dp),
|
.padding(horizontal = 8.dp),
|
||||||
value = TextFieldValue(stringResource(output.label)),
|
value = TextFieldValue(stringResource(output.label)),
|
||||||
minRatio = 0.8f,
|
minRatio = 0.8f,
|
||||||
onCursorChange = {},
|
onValueChange = {},
|
||||||
textColor = MaterialTheme.colorScheme.error,
|
textColor = MaterialTheme.colorScheme.error,
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
)
|
)
|
||||||
|
@ -64,7 +64,6 @@ import androidx.compose.ui.focus.onFocusEvent
|
|||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.TextRange
|
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
@ -83,7 +82,8 @@ import com.sadellie.unitto.core.ui.common.ScaffoldWithTopBar
|
|||||||
import com.sadellie.unitto.core.ui.common.SettingsButton
|
import com.sadellie.unitto.core.ui.common.SettingsButton
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField
|
import com.sadellie.unitto.core.ui.common.textfield.ExpressionTextField
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
import com.sadellie.unitto.core.ui.common.textfield.FormatterSymbols
|
||||||
import com.sadellie.unitto.core.ui.common.textfield.UnformattedTextField
|
import com.sadellie.unitto.core.ui.common.textfield.NumberBaseTextField
|
||||||
|
import com.sadellie.unitto.core.ui.common.textfield.SimpleTextField
|
||||||
import com.sadellie.unitto.core.ui.datetime.formatDateWeekDayMonthYear
|
import com.sadellie.unitto.core.ui.datetime.formatDateWeekDayMonthYear
|
||||||
import com.sadellie.unitto.data.common.format
|
import com.sadellie.unitto.data.common.format
|
||||||
import com.sadellie.unitto.data.converter.UnitID
|
import com.sadellie.unitto.data.converter.UnitID
|
||||||
@ -114,7 +114,7 @@ internal fun ConverterRoute(
|
|||||||
processInput = viewModel::addTokens,
|
processInput = viewModel::addTokens,
|
||||||
deleteDigit = viewModel::deleteTokens,
|
deleteDigit = viewModel::deleteTokens,
|
||||||
clearInput = viewModel::clearInput,
|
clearInput = viewModel::clearInput,
|
||||||
onCursorChange = viewModel::onCursorChange,
|
onValueChange = viewModel::updateInput,
|
||||||
onFocusOnInput2 = viewModel::updateFocused,
|
onFocusOnInput2 = viewModel::updateFocused,
|
||||||
onErrorClick = viewModel::updateCurrencyRates,
|
onErrorClick = viewModel::updateCurrencyRates,
|
||||||
addBracket = viewModel::addBracket
|
addBracket = viewModel::addBracket
|
||||||
@ -132,7 +132,7 @@ private fun ConverterScreen(
|
|||||||
processInput: (String) -> Unit,
|
processInput: (String) -> Unit,
|
||||||
deleteDigit: () -> Unit,
|
deleteDigit: () -> Unit,
|
||||||
clearInput: () -> Unit,
|
clearInput: () -> Unit,
|
||||||
onCursorChange: (TextRange) -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
onFocusOnInput2: (Boolean) -> Unit,
|
onFocusOnInput2: (Boolean) -> Unit,
|
||||||
onErrorClick: (AbstractUnit) -> Unit,
|
onErrorClick: (AbstractUnit) -> Unit,
|
||||||
addBracket: () -> Unit,
|
addBracket: () -> Unit,
|
||||||
@ -148,7 +148,7 @@ private fun ConverterScreen(
|
|||||||
NumberBase(
|
NumberBase(
|
||||||
modifier = Modifier.padding(it),
|
modifier = Modifier.padding(it),
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
onCursorChange = onCursorChange,
|
onValueChange = onValueChange,
|
||||||
processInput = processInput,
|
processInput = processInput,
|
||||||
deleteDigit = deleteDigit,
|
deleteDigit = deleteDigit,
|
||||||
navigateToLeftScreen = navigateToLeftScreen,
|
navigateToLeftScreen = navigateToLeftScreen,
|
||||||
@ -167,7 +167,7 @@ private fun ConverterScreen(
|
|||||||
Default(
|
Default(
|
||||||
modifier = Modifier.padding(it),
|
modifier = Modifier.padding(it),
|
||||||
uiState = uiState,
|
uiState = uiState,
|
||||||
onCursorChange = onCursorChange,
|
onValueChange = onValueChange,
|
||||||
onFocusOnInput2 = onFocusOnInput2,
|
onFocusOnInput2 = onFocusOnInput2,
|
||||||
processInput = processInput,
|
processInput = processInput,
|
||||||
deleteDigit = deleteDigit,
|
deleteDigit = deleteDigit,
|
||||||
@ -204,7 +204,7 @@ private fun UnitConverterTopBar(
|
|||||||
private fun NumberBase(
|
private fun NumberBase(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
uiState: UnitConverterUIState.NumberBase,
|
uiState: UnitConverterUIState.NumberBase,
|
||||||
onCursorChange: (TextRange) -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
processInput: (String) -> Unit,
|
processInput: (String) -> Unit,
|
||||||
deleteDigit: () -> Unit,
|
deleteDigit: () -> Unit,
|
||||||
navigateToLeftScreen: () -> Unit,
|
navigateToLeftScreen: () -> Unit,
|
||||||
@ -218,14 +218,12 @@ private fun NumberBase(
|
|||||||
ColumnWithConstraints(modifier = contentModifier) {
|
ColumnWithConstraints(modifier = contentModifier) {
|
||||||
val textFieldModifier = Modifier.weight(2f)
|
val textFieldModifier = Modifier.weight(2f)
|
||||||
|
|
||||||
UnformattedTextField(
|
NumberBaseTextField(
|
||||||
modifier = textFieldModifier,
|
modifier = textFieldModifier,
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
placeholder = Token.Digit._0,
|
placeholder = Token.Digit._0,
|
||||||
value = uiState.input,
|
value = uiState.input,
|
||||||
onCursorChange = onCursorChange,
|
onValueChange = onValueChange,
|
||||||
pasteCallback = processInput,
|
|
||||||
cutCallback = deleteDigit,
|
|
||||||
)
|
)
|
||||||
AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName))
|
AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName))
|
||||||
|
|
||||||
@ -261,7 +259,7 @@ private fun NumberBase(
|
|||||||
private fun Default(
|
private fun Default(
|
||||||
modifier: Modifier,
|
modifier: Modifier,
|
||||||
uiState: UnitConverterUIState.Default,
|
uiState: UnitConverterUIState.Default,
|
||||||
onCursorChange: (TextRange) -> Unit,
|
onValueChange: (TextFieldValue) -> Unit,
|
||||||
onFocusOnInput2: (Boolean) -> Unit,
|
onFocusOnInput2: (Boolean) -> Unit,
|
||||||
processInput: (String) -> Unit,
|
processInput: (String) -> Unit,
|
||||||
deleteDigit: () -> Unit,
|
deleteDigit: () -> Unit,
|
||||||
@ -330,13 +328,11 @@ private fun Default(
|
|||||||
) {
|
) {
|
||||||
ExpressionTextField(
|
ExpressionTextField(
|
||||||
modifier = Modifier.fillMaxWidth().weight(1f),
|
modifier = Modifier.fillMaxWidth().weight(1f),
|
||||||
minRatio = 0.7f,
|
|
||||||
placeholder = Token.Digit._0,
|
|
||||||
value = uiState.input1,
|
value = uiState.input1,
|
||||||
onCursorChange = onCursorChange,
|
minRatio = 0.7f,
|
||||||
pasteCallback = processInput,
|
onValueChange = onValueChange,
|
||||||
cutCallback = deleteDigit,
|
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
|
placeholder = Token.Digit._0,
|
||||||
)
|
)
|
||||||
AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName))
|
AnimatedUnitShortName(stringResource(uiState.unitFrom.shortName))
|
||||||
}
|
}
|
||||||
@ -351,13 +347,11 @@ private fun Default(
|
|||||||
ExpressionTextField(
|
ExpressionTextField(
|
||||||
modifier = Modifier.fillMaxWidth().weight(1f)
|
modifier = Modifier.fillMaxWidth().weight(1f)
|
||||||
.onFocusEvent { state -> onFocusOnInput2(state.hasFocus) },
|
.onFocusEvent { state -> onFocusOnInput2(state.hasFocus) },
|
||||||
minRatio = 0.7f,
|
|
||||||
placeholder = Token.Digit._0,
|
|
||||||
value = uiState.input2,
|
value = uiState.input2,
|
||||||
onCursorChange = onCursorChange,
|
minRatio = 0.7f,
|
||||||
pasteCallback = processInput,
|
onValueChange = onValueChange,
|
||||||
cutCallback = deleteDigit,
|
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
|
placeholder = Token.Digit._0,
|
||||||
)
|
)
|
||||||
AnimatedUnitShortName(stringResource(R.string.unit_inch_short))
|
AnimatedUnitShortName(stringResource(R.string.unit_inch_short))
|
||||||
}
|
}
|
||||||
@ -365,13 +359,11 @@ private fun Default(
|
|||||||
} else {
|
} else {
|
||||||
ExpressionTextField(
|
ExpressionTextField(
|
||||||
modifier = textFieldModifier,
|
modifier = textFieldModifier,
|
||||||
minRatio = 0.7f,
|
|
||||||
placeholder = Token.Digit._0,
|
|
||||||
value = uiState.input1,
|
value = uiState.input1,
|
||||||
onCursorChange = onCursorChange,
|
minRatio = 0.7f,
|
||||||
pasteCallback = processInput,
|
onValueChange = onValueChange,
|
||||||
cutCallback = deleteDigit,
|
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
|
placeholder = Token.Digit._0,
|
||||||
)
|
)
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = calculation.text.isNotEmpty(),
|
visible = calculation.text.isNotEmpty(),
|
||||||
@ -382,10 +374,10 @@ private fun Default(
|
|||||||
ExpressionTextField(
|
ExpressionTextField(
|
||||||
modifier = Modifier,
|
modifier = Modifier,
|
||||||
value = calculation,
|
value = calculation,
|
||||||
onCursorChange = { calculation = calculation.copy(selection = it) },
|
|
||||||
formatterSymbols = uiState.formatterSymbols,
|
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
|
onValueChange = { calculation = it },
|
||||||
textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
|
textColor = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
|
||||||
|
formatterSymbols = uiState.formatterSymbols,
|
||||||
readOnly = true
|
readOnly = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -456,20 +448,20 @@ private fun ConverterResultTextField(
|
|||||||
|
|
||||||
when (result) {
|
when (result) {
|
||||||
is ConverterResult.Loading -> {
|
is ConverterResult.Loading -> {
|
||||||
UnformattedTextField(
|
SimpleTextField(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
value = TextFieldValue(stringResource(R.string.loading_label)),
|
value = TextFieldValue(stringResource(R.string.loading_label)),
|
||||||
onCursorChange = {},
|
onValueChange = {},
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
readOnly = true
|
readOnly = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is ConverterResult.Error -> {
|
is ConverterResult.Error -> {
|
||||||
UnformattedTextField(
|
SimpleTextField(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
value = TextFieldValue(stringResource(R.string.error_label)),
|
value = TextFieldValue(stringResource(R.string.error_label)),
|
||||||
onCursorChange = { onErrorClick() },
|
onValueChange = { onErrorClick() },
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
readOnly = true,
|
readOnly = true,
|
||||||
textColor = MaterialTheme.colorScheme.error,
|
textColor = MaterialTheme.colorScheme.error,
|
||||||
@ -480,20 +472,29 @@ private fun ConverterResultTextField(
|
|||||||
ExpressionTextField(
|
ExpressionTextField(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
value = resultTextField,
|
value = resultTextField,
|
||||||
onCursorChange = { resultTextField = resultTextField.copy(selection = it) },
|
minRatio = 0.7f,
|
||||||
|
onValueChange = { resultTextField = it },
|
||||||
formatterSymbols = formatterSymbols,
|
formatterSymbols = formatterSymbols,
|
||||||
|
readOnly = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is ConverterResult.NumberBase -> {
|
||||||
|
NumberBaseTextField(
|
||||||
|
modifier = modifier,
|
||||||
|
value = resultTextField,
|
||||||
|
onValueChange = { resultTextField = it },
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
readOnly = true
|
readOnly = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
is ConverterResult.NumberBase,
|
|
||||||
is ConverterResult.Time,
|
is ConverterResult.Time,
|
||||||
is ConverterResult.FootInch -> {
|
is ConverterResult.FootInch -> {
|
||||||
UnformattedTextField(
|
SimpleTextField(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
value = resultTextField,
|
value = resultTextField,
|
||||||
onCursorChange = { resultTextField = resultTextField.copy(selection = it) },
|
onValueChange = { resultTextField = it },
|
||||||
minRatio = 0.7f,
|
minRatio = 0.7f,
|
||||||
readOnly = true
|
readOnly = true
|
||||||
)
|
)
|
||||||
@ -585,7 +586,7 @@ private fun PreviewConverterScreen() {
|
|||||||
processInput = {},
|
processInput = {},
|
||||||
deleteDigit = {},
|
deleteDigit = {},
|
||||||
clearInput = {},
|
clearInput = {},
|
||||||
onCursorChange = {},
|
onValueChange = {},
|
||||||
onFocusOnInput2 = {},
|
onFocusOnInput2 = {},
|
||||||
onErrorClick = {},
|
onErrorClick = {},
|
||||||
addBracket = {}
|
addBracket = {}
|
||||||
|
@ -18,7 +18,6 @@
|
|||||||
|
|
||||||
package com.sadellie.unitto.feature.converter
|
package com.sadellie.unitto.feature.converter
|
||||||
|
|
||||||
import androidx.compose.ui.text.TextRange
|
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
@ -321,7 +320,7 @@ internal class ConverterViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onCursorChange(selection: TextRange) = _input1.update { it.copy(selection = selection) }
|
fun updateInput(value: TextFieldValue) = _input1.update { value }
|
||||||
|
|
||||||
fun updateCurrencyRates(unit: AbstractUnit) {
|
fun updateCurrencyRates(unit: AbstractUnit) {
|
||||||
_loadCurrenciesJob = viewModelScope.launch(Dispatchers.IO) {
|
_loadCurrenciesJob = viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user