From c5207cb8a6381209745a68a163c49afaeb59af82 Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Mon, 6 Jan 2025 13:00:31 -0400 Subject: [PATCH] Ensure filter is not retriggered when formatting. Fixes #13876 --- .../settings/app/subscription/boost/Boost.kt | 36 +++++++++++-------- .../boost/BoostTest__MoneyFilter.kt | 16 +++++++++ 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/Boost.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/Boost.kt index 2a4a31bad3..9a068eaf4f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/Boost.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/Boost.kt @@ -297,17 +297,15 @@ data class Boost( if (value != null) { val formatted = formatter.format(value) - text?.removeTextChangedListener(this) - - s.replace(0, s.length, formatted) - if (formatted.endsWith(symbol)) { - val result: MatchResult? = symbolPattern.find(formatted) - if (result != null && result.range.first < s.length) { - text?.setSelection(result.range.first) + modifyEditable { + s.replace(0, s.length, formatted) + if (formatted.endsWith(symbol)) { + val result: MatchResult? = symbolPattern.find(formatted) + if (result != null && result.range.first < s.length) { + text?.setSelection(result.range.first) + } } } - - text?.addTextChangedListener(this) } } @@ -325,16 +323,24 @@ data class Boost( } if (withoutSymbol != withoutLeadingZeroes) { - text?.removeTextChangedListener(this) - - val start = s.indexOf(withoutSymbol) - s.replace(start, start + withoutSymbol.length, withoutLeadingZeroes) - - text?.addTextChangedListener(this) + modifyEditable { + val start = s.indexOf(withoutSymbol) + s.replace(start, start + withoutSymbol.length, withoutLeadingZeroes) + } } onCustomAmountChanged(s.removePrefix(symbol).removeSuffix(symbol).trim().toString()) } + + private fun modifyEditable(modification: () -> Unit) { + text?.removeTextChangedListener(this) + text?.keyListener = null + + modification() + + text?.addTextChangedListener(this) + text?.keyListener = this + } } companion object { diff --git a/app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostTest__MoneyFilter.kt b/app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostTest__MoneyFilter.kt index 83e09f7edd..5572466736 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostTest__MoneyFilter.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/components/settings/app/subscription/boost/BoostTest__MoneyFilter.kt @@ -2,6 +2,9 @@ package org.thoughtcrime.securesms.components.settings.app.subscription.boost import android.app.Application import android.text.SpannableStringBuilder +import android.widget.TextView +import androidx.appcompat.widget.AppCompatEditText +import androidx.test.core.app.ApplicationProvider import org.junit.Assert.assertEquals import org.junit.Assert.assertNotNull import org.junit.Assert.assertNull @@ -96,6 +99,19 @@ class BoostTest__MoneyFilter { assertNull(filterResult) } + @Test + fun `Given USD, when I enter 1000, then I expect successful filter`() { + val view = AppCompatEditText(ApplicationProvider.getApplicationContext()) + val testSubject = Boost.MoneyFilter(usd, text = view) + + view.keyListener = testSubject + view.addTextChangedListener(testSubject) + + view.setText("1000", TextView.BufferType.EDITABLE) + + assertEquals("$1,000", view.text.toString()) + } + @Test fun `Given JPY, when I enter 5, then I expect yen 5`() { val testSubject = Boost.MoneyFilter(yen)