Last active
July 1, 2022 16:16
-
-
Save carterhudson/b9d274d95e208352d8a71d451abbe97f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class PhoneNumberVisualTransformation(locale: Locale = Locale.getDefault()) : VisualTransformation { | |
private val phoneNumberFormatter = | |
PhoneNumberUtil.getInstance().getAsYouTypeFormatter(locale.country) | |
override fun filter(text: AnnotatedString): TransformedText { | |
phoneNumberFormatter.clear() | |
var formatted = "" | |
text.forEach { formatted = phoneNumberFormatter.inputDigit(it) } | |
val separatorCount = formatted.count { !PhoneNumberUtils.isNonSeparator(it) } | |
return TransformedText( | |
AnnotatedString(text = formatted), | |
object : OffsetMapping { | |
override fun originalToTransformed(offset: Int): Int = | |
formatted | |
// Cursor offsets are always 1 more than the index they are to | |
// the right of. | |
// We construct a list of non-separator indices, adding 1 to turn | |
// them into offsets | |
.mapIndexedNotNull { index, c -> | |
index | |
.takeIf { PhoneNumberUtils.isNonSeparator(c) } | |
?.plus(1) | |
} | |
// We want to coalesce to null if the list is empty | |
.takeIf { offsetList -> | |
offsetList.isNotEmpty() | |
} | |
// We want to support an offset of 0, so we prepend | |
?.let { offsetList -> | |
listOf(0) + offsetList | |
} | |
// We can now retrieve the transformed offset by using "offset" as our index | |
?.get(offset) | |
// If the list was empty (takeIf), we just use the un-adjusted offset | |
?: offset | |
override fun transformedToOriginal(offset: Int): Int = | |
formatted | |
// This creates a list of all separator indices | |
.mapIndexedNotNull { index, c -> | |
index.takeIf { !PhoneNumberUtils.isNonSeparator(c) } | |
} | |
// We want to count how many separators are present to the left of the offset | |
.count { separatorIndex -> | |
separatorIndex < offset | |
} | |
// We find the original offset by subtracting the number of separators | |
.let { separatorCount -> | |
offset - separatorCount | |
} | |
} | |
) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment