fixed review

This commit is contained in:
Vladimir 2020-08-27 14:17:11 +05:00
parent 66189db56a
commit 6ee1867235
1 changed files with 56 additions and 54 deletions

View File

@ -9,7 +9,6 @@ import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow
@Suppress("detekt.LabeledExpression")
class AmountWithDecimalDecorator(
val editText: EditText,
val decimalSeparator: String = DEFAULT_DECIMAL_SEPARATOR,
@ -20,7 +19,8 @@ class AmountWithDecimalDecorator(
companion object {
private const val COMMON_MONEY_MASK = "###,##0"
private const val DEFAULT_DECIMAL_SEPARATOR = "."
private const val DOT_SYMBOL = "."
private const val DEFAULT_DECIMAL_SEPARATOR = DOT_SYMBOL
private const val GROUPING_SEPARATOR = ' '
private const val DEFAULT_DECIMAL_PART_LENGTH = 2
private val hardcodedSymbols = listOf(GROUPING_SEPARATOR)
@ -38,57 +38,59 @@ class AmountWithDecimalDecorator(
throw IllegalArgumentException("Not allowed decimal separator. Supports only: $possibleDecimalSeparators")
}
@Suppress("detekt.TooGenericExceptionCaught")
editText.doOnTextChanged { text, _, _, _ ->
if (isTextWasArtificiallyChanged) {
isTextWasArtificiallyChanged = false
val cursorPosition = editText.selectionStart
try {
var currentText = text.toString()
possibleDecimalSeparators.forEach {
currentText = currentText.replace(it, decimalSeparator)
}
if (isTextFormatIncorrect(currentText)) {
setTextWhenNewInputIncorrect(currentText, cursorPosition)
return@doOnTextChanged
}
if (isTextHasHeadZero(currentText)) {
setTextWithHeadZero(currentText, cursorPosition)
return@doOnTextChanged
}
val currentDecimalPartLength = currentText.split(decimalSeparator).getOrNull(1)?.length
if (isDecimalPathTooLong(currentDecimalPartLength)) {
setTextWhenNewInputIncorrect(currentText, cursorPosition)
return@doOnTextChanged
}
val textAfter = if (currentText.isNotEmpty()) {
currentText.withoutFormatting().formatMoney(currentDecimalPartLength)
} else ""
if (!isTextErased(textBefore, textAfter)) {
onTextErased(textAfter, cursorPosition)
} else {
onTextInserted(textAfter, cursorPosition)
}
} catch (e: Throwable) {
editText.setText(textBefore)
editText.setSelection(textBefore.length)
}
} else {
textBefore = text.toString()
isTextWasArtificiallyChanged = true
onTextChanged(text.toString())
}
}
editText.doOnTextChanged { text, _, _, _ -> doOnTextChanged(text.toString()) }
}
fun getTextWithoutFormatting(decimalSeparatorToReplace: String = decimalSeparator): String =
textBefore.withoutFormatting(decimalSeparatorToReplace)
@Suppress("detekt.TooGenericExceptionCaught")
private fun doOnTextChanged(text: String) {
if (isTextWasArtificiallyChanged) {
isTextWasArtificiallyChanged = false
val cursorPosition = editText.selectionStart
try {
var currentText = text
possibleDecimalSeparators.forEach {
currentText = currentText.replace(it, decimalSeparator)
}
if (isTextFormatIncorrect(currentText)) {
setTextWhenNewInputIncorrect(currentText, cursorPosition)
return
}
if (isTextHasHeadZero(currentText)) {
setTextWithHeadZero(currentText, cursorPosition)
return
}
val currentDecimalPartLength = currentText.split(decimalSeparator).getOrNull(1)?.length
if (isDecimalPathTooLong(currentDecimalPartLength)) {
setTextWhenNewInputIncorrect(currentText, cursorPosition)
return
}
val formattedText = if (currentText.isNotEmpty()) {
currentText.withoutFormatting().formatMoney(currentDecimalPartLength)
} else ""
if (!isTextErased(textBefore, formattedText)) {
onTextErased(formattedText, cursorPosition)
} else {
onNewUserInput(formattedText, cursorPosition)
}
} catch (e: Throwable) {
editText.setText(textBefore)
editText.setSelection(textBefore.length)
}
} else {
textBefore = text
isTextWasArtificiallyChanged = true
onTextChanged(text)
}
}
private fun isTextFormatIncorrect(currentText: String) =
currentText == decimalSeparator || currentText.count { it == decimalSeparator[0] } > 1 || currentText.take(2) == "00"
@ -97,7 +99,7 @@ class AmountWithDecimalDecorator(
private fun setTextWithHeadZero(text: String, cursorPos: Int) {
if (abs(textBefore.length - text.length) > 1) {
setTextWhichWasPasted(text)
setTextWhichWasInserted(text)
} else {
editText.setText(text.substring(1, text.length))
editText.setSelection(max(cursorPos - 1, 0))
@ -106,7 +108,7 @@ class AmountWithDecimalDecorator(
private fun setTextWhenNewInputIncorrect(text: String, cursorPos: Int) {
if (abs(textBefore.length - text.length) > 1) {
setTextWhichWasPasted(text)
setTextWhichWasInserted(text)
} else {
editText.setText(textBefore)
editText.setSelection(max(cursorPos - 1, 0))
@ -119,7 +121,7 @@ class AmountWithDecimalDecorator(
editText.setSelection(min(cursorPos + diff, textAfter.length))
}
private fun onTextInserted(textAfter: String, cursorPos: Int) {
private fun onNewUserInput(textAfter: String, cursorPos: Int) {
if (!textBefore.contains(decimalSeparator)
&& textAfter.contains(decimalSeparator)
) {
@ -141,7 +143,7 @@ class AmountWithDecimalDecorator(
!isSeparatorCutInvalidDecimalLength && currentDecimalPartLength != null
&& currentDecimalPartLength > decimalPartLength
private fun setTextWhichWasPasted(text: String) {
private fun setTextWhichWasInserted(text: String) {
var result = ""
var decimalLength = -1
var index = 0
@ -173,7 +175,7 @@ class AmountWithDecimalDecorator(
private fun String.replaceSeparatorsToDot(): String {
var result = this
possibleDecimalSeparators.forEach {
result = result.replace(it, ".")
result = result.replace(it, DOT_SYMBOL)
}
return result.withoutFormatting()
}
@ -184,7 +186,7 @@ class AmountWithDecimalDecorator(
private fun String.formatMoney(currentDecimalPartLength: Int?): String {
var mask = COMMON_MONEY_MASK
if (currentDecimalPartLength != null && decimalPartLength != 0) {
mask += "." + "0".repeat(min(currentDecimalPartLength, decimalPartLength))
mask += DOT_SYMBOL + "0".repeat(min(currentDecimalPartLength, decimalPartLength))
}
val formatter = DecimalFormat(mask)