Handle emoji correctly when deleting text (#1169)

This commit is contained in:
Paul Kramer 2024-12-02 18:43:10 +01:00 committed by GitHub
parent 71b3660939
commit 550a0ee3e3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -45,6 +45,7 @@ import com.dessalines.thumbkey.db.LayoutsUpdate
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import java.text.BreakIterator
import java.text.NumberFormat
import kotlin.math.PI
import kotlin.math.abs
@ -363,7 +364,15 @@ fun performKeyAction(
is KeyAction.DeleteKeyAction -> {
if (ime.currentInputConnection.getSelectedText(0)?.isEmpty() != false) {
ime.currentInputConnection.deleteSurroundingText(1, 0)
val textBeforeCursor = ime.currentInputConnection.getTextBeforeCursor(20, 0)?.toString()
if (textBeforeCursor.isNullOrEmpty()) {
return
}
val lastClusterBoundary = findLastGraphemeClusterBoundary(textBeforeCursor)
if (lastClusterBoundary != -1) {
ime.currentInputConnection.deleteSurroundingText(textBeforeCursor.length - lastClusterBoundary, 0)
}
} else {
ime.currentInputConnection.commitText("", 0)
}
@ -1366,3 +1375,33 @@ fun updateLayouts(
),
)
}
fun findLastGraphemeClusterBoundary(text: String): Int {
val boundary = BreakIterator.getCharacterInstance()
boundary.setText(text)
val end = text.length
var lastBoundary = boundary.preceding(end) // Find the previous grapheme boundary
// Check if this boundary is part of a ZWJ sequence
while (lastBoundary > 0 && isPartOfZWJSequence(text, lastBoundary)) {
lastBoundary = boundary.preceding(lastBoundary)
}
return lastBoundary
}
fun isPartOfZWJSequence(
text: String,
index: Int,
): Boolean {
if (index <= 0 || index >= text.length) return false
// Check if the character before this boundary is a ZWJ
val previousChar = text[index - 1]
if (previousChar.code == 0x200D) { // Zero-Width Joiner
return true
}
return false
}