diff --git a/app/src/main/java/be/scri/helpers/DatabaseHelper.kt b/app/src/main/java/be/scri/helpers/DatabaseHelper.kt index 10d124d8..56cb41cc 100644 --- a/app/src/main/java/be/scri/helpers/DatabaseHelper.kt +++ b/app/src/main/java/be/scri/helpers/DatabaseHelper.kt @@ -63,6 +63,8 @@ class DatabaseHelper( getRequiredData(language), ) + fun getEmojiMaxKeywordLength(): Int = dbManagers.emojiManager.maxKeywordLength + fun findCaseAnnnotationForPreposition(language: String): HashMap> = if (language != "DE" && language != "RU") { hashMapOf() diff --git a/app/src/main/java/be/scri/helpers/keyboardDBHelper/EmojiDataManager.kt b/app/src/main/java/be/scri/helpers/keyboardDBHelper/EmojiDataManager.kt index 12027361..31b0055f 100644 --- a/app/src/main/java/be/scri/helpers/keyboardDBHelper/EmojiDataManager.kt +++ b/app/src/main/java/be/scri/helpers/keyboardDBHelper/EmojiDataManager.kt @@ -11,6 +11,9 @@ import android.database.sqlite.SQLiteDatabase class EmojiDataManager( private val context: Context, ) { + // Track max keyword length. + var maxKeywordLength = 0 + fun getEmojiKeywords(language: String): HashMap> { val dbFile = context.getDatabasePath("${language}LanguageData.sqlite") return processEmojiKeywords(dbFile.path) @@ -18,10 +21,17 @@ class EmojiDataManager( private fun processEmojiKeywords(dbPath: String): HashMap> { val hashMap = HashMap>() - val db = SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY) - db.use { database -> - database.rawQuery("SELECT * FROM emoji_keywords", null).use { cursor -> + SQLiteDatabase.openDatabase(dbPath, null, SQLiteDatabase.OPEN_READONLY).use { db -> + // Get max keyword length. + db.rawQuery("SELECT MAX(LENGTH(word)) FROM emoji_keywords", null).use { cursor -> + if (cursor.moveToFirst()) { + maxKeywordLength = cursor.getInt(0) + } + } + + // Keyword processing. + db.rawQuery("SELECT * FROM emoji_keywords", null).use { cursor -> processEmojiCursor(cursor, hashMap) } } diff --git a/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt b/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt index 9de7836f..bc630f78 100644 --- a/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt @@ -93,6 +93,7 @@ abstract class GeneralKeyboardIME( private lateinit var dbHelper: DatabaseHelper lateinit var emojiKeywords: HashMap> + var emojiMaxKeywordLength: Int = 0 lateinit var nounKeywords: HashMap> lateinit var pluralWords: List lateinit var caseAnnotation: HashMap> @@ -295,6 +296,7 @@ abstract class GeneralKeyboardIME( dbHelper = DatabaseHelper(this) dbHelper.loadDatabase(languageAlias) emojiKeywords = dbHelper.getEmojiKeywords(languageAlias) + emojiMaxKeywordLength = dbHelper.getEmojiMaxKeywordLength() pluralWords = dbHelper.checkIfWordIsPlural(languageAlias)!! nounKeywords = dbHelper.findGenderOfWord(languageAlias) @@ -1229,12 +1231,52 @@ abstract class GeneralKeyboardIME( /** * Inserts the specified emoji into the current input field. + * Replaces the last word if there's no trailing space. * * @param emoji The emoji character to be inserted. */ private fun insertEmoji(emoji: String) { val inputConnection = currentInputConnection ?: return - inputConnection.commitText(emoji, 1) + val maxLookBack = emojiMaxKeywordLength.coerceAtLeast(1) + + inputConnection.beginBatchEdit() + try { + val previousText = inputConnection.getTextBeforeCursor(maxLookBack, 0)?.toString() ?: "" + + // Find last word boundary efficiently + val lastSpaceIndex = previousText.lastIndexOf(' ') + val hasSpace = lastSpaceIndex != -1 + + when { + // Case 1: Ends with space or empty + previousText.isEmpty() || hasSpace && lastSpaceIndex == previousText.length - 1 -> { + inputConnection.commitText(emoji, 1) + } + + // Case 2: Has previous word + hasSpace -> { + val lastWord = previousText.substring(lastSpaceIndex + 1) + if (emojiKeywords.containsKey(lastWord.lowercase())) { + inputConnection.deleteSurroundingText(lastWord.length, 0) + inputConnection.commitText(emoji, 1) + } else { + inputConnection.commitText(emoji, 1) + } + } + + // Case 3: Entire text is the word + else -> { + if (emojiKeywords.containsKey(previousText.lowercase())) { + inputConnection.deleteSurroundingText(previousText.length, 0) + inputConnection.commitText(emoji, 1) + } else { + inputConnection.commitText(emoji, 1) + } + } + } + } finally { + inputConnection.endBatchEdit() + } } /**