diff --git a/app/src/keyboards/java/be/scri/helpers/SuggestionHandler.kt b/app/src/keyboards/java/be/scri/helpers/SuggestionHandler.kt index 3b836ac5..1c6e4be9 100644 --- a/app/src/keyboards/java/be/scri/helpers/SuggestionHandler.kt +++ b/app/src/keyboards/java/be/scri/helpers/SuggestionHandler.kt @@ -160,6 +160,7 @@ class SuggestionHandler( ime.updateEmojiSuggestion(true, emojis) ime.updateButtonVisibility(true) } else { + ime.autoSuggestEmojis = null ime.updateButtonVisibility(false) } } diff --git a/app/src/keyboards/java/be/scri/services/EnglishKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/EnglishKeyboardIME.kt index 549281da..724792ab 100644 --- a/app/src/keyboards/java/be/scri/services/EnglishKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/EnglishKeyboardIME.kt @@ -5,7 +5,6 @@ package be.scri.services import android.text.InputType import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R -import be.scri.helpers.KeyHandler import be.scri.models.ScribeLanguage /** @@ -30,13 +29,4 @@ class EnglishKeyboardIME : GeneralKeyboardIME(ScribeLanguage.ENGLISH) { override var inputTypeClass: Int = InputType.TYPE_CLASS_TEXT override var enterKeyType: Int = IME_ACTION_NONE override var switchToLetters: Boolean = false - - private val keyHandler by lazy { KeyHandler(this) } - - /** - * Handles key input from the keyboard and delegates it to [KeyHandler]. - */ - override fun onKey(code: Int) { - keyHandler.handleKey(code, language) - } } diff --git a/app/src/keyboards/java/be/scri/services/FrenchKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/FrenchKeyboardIME.kt index bf077ebd..387b5b06 100644 --- a/app/src/keyboards/java/be/scri/services/FrenchKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/FrenchKeyboardIME.kt @@ -5,7 +5,6 @@ package be.scri.services import android.text.InputType import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R -import be.scri.helpers.KeyHandler import be.scri.models.ScribeLanguage /** @@ -33,13 +32,4 @@ class FrenchKeyboardIME : GeneralKeyboardIME(ScribeLanguage.FRENCH) { // so we must remove the overrides here. They are now inherited directly. // override lateinit var binding: KeyboardViewCommandOptionsBinding // REMOVED // override var keyboardView: KeyboardView? = null // REMOVED - - private val keyHandler by lazy { KeyHandler(this) } - - /** - * Handles key press events on the keyboard. - */ - override fun onKey(code: Int) { - keyHandler.handleKey(code, language) - } } diff --git a/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt index 8c91fcf3..d0cef47c 100644 --- a/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/GeneralKeyboardIME.kt @@ -33,6 +33,7 @@ import be.scri.helpers.BackspaceHandler import be.scri.helpers.DatabaseManagers import be.scri.helpers.EmojiUtils.insertEmoji import be.scri.helpers.FloatingKeyboardHandler +import be.scri.helpers.KeyHandler import be.scri.helpers.KeyboardBase import be.scri.helpers.KeyboardDataHandler import be.scri.helpers.KeyboardLanguageMappingConstants @@ -151,6 +152,7 @@ abstract class GeneralKeyboardIME( private lateinit var nativeSuggestionEngine: NativeSuggestionEngine internal lateinit var suggestionHandler: SuggestionHandler internal lateinit var autocompletionHandler: AutocompletionHandler + internal lateinit var keyHandler: KeyHandler internal val floatingKeyboardHandler by lazy { FloatingKeyboardHandler(this) } internal var dataContract: DataContract? @@ -296,6 +298,7 @@ abstract class GeneralKeyboardIME( nativeSuggestionEngine = NativeSuggestionEngine(this) suggestionHandler = SuggestionHandler(this) autocompletionHandler = AutocompletionHandler(this) + keyHandler = KeyHandler(this) clipboardHandler.initClipboardMonitor() } @@ -583,55 +586,7 @@ abstract class GeneralKeyboardIME( * Handles key input from the keyboard. Delegates to specific handlers based on the key code. */ override fun onKey(code: Int) { - when (code) { - KeyboardBase.KEYCODE_EMOJI -> { - openEmojiKeyboard() - return - } - KeyboardBase.KEYCODE_FLOAT_TOGGLE -> { - toggleFloatingMode() - return - } - KeyboardBase.KEYCODE_CLIPBOARD -> { - openClipboardPanel() - return - } - } - val inputConnection = currentInputConnection - if (inputConnection != null) { - when (code) { - KeyboardBase.KEYCODE_DELETE -> handleDelete() - KeyboardBase.KEYCODE_SHIFT -> { - if (keyboardMode == keyboardLetters) { - val shiftState = keyboardView?.mKeyboard?.mShiftState ?: SHIFT_OFF - when { - shiftState == SHIFT_ON_PERMANENT -> keyboardView?.setShifted(SHIFT_OFF) - System.currentTimeMillis() - lastShiftPressTS < shiftPermToggleSpeed -> keyboardView?.setShifted(SHIFT_ON_PERMANENT) - shiftState == SHIFT_ON_ONE_CHAR -> keyboardView?.setShifted(SHIFT_OFF) - shiftState == SHIFT_OFF -> keyboardView?.setShifted(SHIFT_ON_ONE_CHAR) - } - lastShiftPressTS = System.currentTimeMillis() - } else { - handleModeChange(keyboardMode, keyboardView, this) - } - } - - KeyboardBase.KEYCODE_ENTER -> handleKeycodeEnter() - KeyboardBase.KEYCODE_MODE_CHANGE -> handleModeChange(keyboardMode, keyboardView, this) - KeyboardBase.KEYCODE_CLIPBOARD -> openClipboardPanel() - else -> { - if (KeyboardBase.SCRIBE_VIEW_KEYS.contains(code)) { - val keyLabel = keyboardView?.getKeyLabel(code) - if (!keyLabel.isNullOrEmpty()) { - commitText("$keyLabel ") - } - } else { - val commandBarState = currentState != ScribeState.IDLE && currentState != ScribeState.SELECT_COMMAND - handleElseCondition(code, keyboardMode, commandBarState) - } - } - } - } + keyHandler.handleKey(code, language) } // MARK: Helper Methods @@ -692,7 +647,16 @@ abstract class GeneralKeyboardIME( isSubsequentArea: Boolean = false, ) { val sharedPref = applicationContext.getSharedPreferences("keyboard_preferences", MODE_PRIVATE) - val mode = if (!isSubsequentArea) defaultConjugateModeType else "none" + val mode = + if (!isSubsequentArea) { + when (language) { + "English", "Russian", "Swedish" -> "2x2" + "German", "French", "Italian", "Portuguese", "Spanish" -> "2x2" + else -> "none" + } + } else { + "none" + } sharedPref.edit { putString("conjugate_mode_type", mode) } } @@ -1755,7 +1719,11 @@ abstract class GeneralKeyboardIME( val default1 = baseSuggestions.getOrNull(0) ?: "" val default2 = baseSuggestions.getOrNull(1) ?: "" setSuggestionButton(uiManager.binding.conjugateBtn, default1) - uiManager.pluralBtn?.let { setSuggestionButton(it, default2) } + if (autoSuggestEmojis.isNullOrEmpty()) { + uiManager.pluralBtn?.let { setSuggestionButton(it, default2) } + } else { + uiManager.updateButtonVisibility(currentState, true, autoSuggestEmojis) + } } return } @@ -1816,12 +1784,20 @@ abstract class GeneralKeyboardIME( fun updateTypedWordSuggestion(word: String?) { if (currentState != ScribeState.IDLE || word.isNullOrEmpty()) { uiManager.disableAutoSuggest(language) + if (!autoSuggestEmojis.isNullOrEmpty() && emojiAutoSuggestionEnabled) { + updateEmojiSuggestion(true, autoSuggestEmojis) + updateButtonVisibility(true) + } return } setTypedWordButton(uiManager.binding.translateBtn, word) setAutocompleteButton(uiManager.binding.conjugateBtn, "") - uiManager.pluralBtn?.let { setAutocompleteButton(it, "") } + if (autoSuggestEmojis.isNullOrEmpty()) { + uiManager.pluralBtn?.let { setAutocompleteButton(it, "") } + } else { + uiManager.updateButtonVisibility(currentState, true, autoSuggestEmojis) + } uiManager.binding.separator1.visibility = View.VISIBLE uiManager.binding.separator2.visibility = View.VISIBLE @@ -1838,7 +1814,11 @@ abstract class GeneralKeyboardIME( val completion2 = completions.getOrNull(1) ?: "" setAutocompleteButton(uiManager.binding.conjugateBtn, completion1) - uiManager.pluralBtn?.let { setAutocompleteButton(it, completion2) } + if (autoSuggestEmojis.isNullOrEmpty()) { + uiManager.pluralBtn?.let { setAutocompleteButton(it, completion2) } + } else { + uiManager.updateButtonVisibility(currentState, true, autoSuggestEmojis) + } } /** diff --git a/app/src/keyboards/java/be/scri/services/GermanKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/GermanKeyboardIME.kt index ff9a670b..a119b7c7 100644 --- a/app/src/keyboards/java/be/scri/services/GermanKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/GermanKeyboardIME.kt @@ -5,7 +5,6 @@ package be.scri.services import android.text.InputType import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R -import be.scri.helpers.KeyHandler import be.scri.helpers.PreferencesHelper.getIsAccentCharacterDisabled import be.scri.models.ScribeLanguage @@ -49,10 +48,4 @@ class GermanKeyboardIME : GeneralKeyboardIME(ScribeLanguage.GERMAN) { // so we must remove the overrides here. They are now inherited directly. // override lateinit var binding: KeyboardViewCommandOptionsBinding // REMOVED // override var keyboardView: KeyboardView? = null // REMOVED - - private val keyHandler by lazy { KeyHandler(this) } - - override fun onKey(code: Int) { - keyHandler.handleKey(code, language) - } } diff --git a/app/src/keyboards/java/be/scri/services/ItalianKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/ItalianKeyboardIME.kt index a83eac3e..b717a0f3 100644 --- a/app/src/keyboards/java/be/scri/services/ItalianKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/ItalianKeyboardIME.kt @@ -5,7 +5,6 @@ package be.scri.services import android.text.InputType import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R -import be.scri.helpers.KeyHandler import be.scri.models.ScribeLanguage /** @@ -27,10 +26,4 @@ class ItalianKeyboardIME : GeneralKeyboardIME(ScribeLanguage.ITALIAN) { override var inputTypeClass: Int = InputType.TYPE_CLASS_TEXT override var enterKeyType: Int = IME_ACTION_NONE override var switchToLetters: Boolean = false - - private val keyHandler by lazy { KeyHandler(this) } - - override fun onKey(code: Int) { - keyHandler.handleKey(code, language) - } } diff --git a/app/src/keyboards/java/be/scri/services/PortugueseKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/PortugueseKeyboardIME.kt index af3cbb4d..c25e6c8b 100644 --- a/app/src/keyboards/java/be/scri/services/PortugueseKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/PortugueseKeyboardIME.kt @@ -5,7 +5,6 @@ package be.scri.services import android.text.InputType import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R -import be.scri.helpers.KeyHandler import be.scri.models.ScribeLanguage /** @@ -28,10 +27,4 @@ class PortugueseKeyboardIME : GeneralKeyboardIME(ScribeLanguage.PORTUGUESE) { override var enterKeyType: Int = IME_ACTION_NONE override var switchToLetters: Boolean = false override var hasTextBeforeCursor: Boolean = false - - private val keyHandler by lazy { KeyHandler(this) } - - override fun onKey(code: Int) { - keyHandler.handleKey(code, language) - } } diff --git a/app/src/keyboards/java/be/scri/services/RussianKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/RussianKeyboardIME.kt index 088860ee..e3cac9e3 100644 --- a/app/src/keyboards/java/be/scri/services/RussianKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/RussianKeyboardIME.kt @@ -5,7 +5,6 @@ package be.scri.services import android.text.InputType import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R -import be.scri.helpers.KeyHandler import be.scri.models.ScribeLanguage /** @@ -30,10 +29,4 @@ class RussianKeyboardIME : GeneralKeyboardIME(ScribeLanguage.RUSSIAN) { override var inputTypeClass: Int = InputType.TYPE_CLASS_TEXT override var enterKeyType: Int = IME_ACTION_NONE override var switchToLetters: Boolean = false - - private val keyHandler by lazy { KeyHandler(this) } - - override fun onKey(code: Int) { - keyHandler.handleKey(code, language) - } } diff --git a/app/src/keyboards/java/be/scri/services/SpanishKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/SpanishKeyboardIME.kt index 7535de6d..49b25616 100644 --- a/app/src/keyboards/java/be/scri/services/SpanishKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/SpanishKeyboardIME.kt @@ -5,7 +5,6 @@ package be.scri.services import android.text.InputType import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R -import be.scri.helpers.KeyHandler import be.scri.helpers.PreferencesHelper.getIsAccentCharacterDisabled import be.scri.models.ScribeLanguage @@ -38,10 +37,4 @@ class SpanishKeyboardIME : GeneralKeyboardIME(ScribeLanguage.SPANISH) { override var enterKeyType: Int = IME_ACTION_NONE override var switchToLetters: Boolean = false override var hasTextBeforeCursor: Boolean = false - - private val keyHandler by lazy { KeyHandler(this) } - - override fun onKey(code: Int) { - keyHandler.handleKey(code, language) - } } diff --git a/app/src/keyboards/java/be/scri/services/SwedishKeyboardIME.kt b/app/src/keyboards/java/be/scri/services/SwedishKeyboardIME.kt index 081e3719..c9312c1a 100644 --- a/app/src/keyboards/java/be/scri/services/SwedishKeyboardIME.kt +++ b/app/src/keyboards/java/be/scri/services/SwedishKeyboardIME.kt @@ -5,7 +5,6 @@ package be.scri.services import android.text.InputType import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R -import be.scri.helpers.KeyHandler import be.scri.helpers.PreferencesHelper.getIsAccentCharacterDisabled import be.scri.models.ScribeLanguage @@ -40,10 +39,4 @@ class SwedishKeyboardIME : GeneralKeyboardIME(ScribeLanguage.SWEDISH) { override var inputTypeClass: Int = InputType.TYPE_CLASS_TEXT override var enterKeyType: Int = IME_ACTION_NONE override var switchToLetters: Boolean = false - - private val keyHandler by lazy { KeyHandler(this) } - - override fun onKey(code: Int) { - keyHandler.handleKey(code, language) - } } diff --git a/app/src/main/java/be/scri/helpers/data/EmojiDataManager.kt b/app/src/main/java/be/scri/helpers/data/EmojiDataManager.kt index f36c9701..7a40714f 100644 --- a/app/src/main/java/be/scri/helpers/data/EmojiDataManager.kt +++ b/app/src/main/java/be/scri/helpers/data/EmojiDataManager.kt @@ -29,14 +29,22 @@ class EmojiDataManager( val db = fileManager.getLanguageDatabase(language) ?: return emojiMap db.use { - if (!it.tableExists("emoji_keywords")) return emojiMap + // The server contract names the table "emojikeywords", but older local + // databases may use the snake_case form, so accept both. + val tableName = + when { + it.tableExists("emoji_keywords") -> "emoji_keywords" + it.tableExists("emojikeywords") -> "emojikeywords" + else -> return emojiMap + } - it.rawQuery("SELECT MAX(LENGTH(word)) FROM emoji_keywords", null).use { cursor -> + it.rawQuery("SELECT MAX(LENGTH(word)) FROM $tableName", null).use { cursor -> if (cursor.moveToFirst()) { maxKeywordLength = cursor.getInt(0) } } - it.rawQuery("SELECT * FROM emoji_keywords", null).use { cursor -> + + it.rawQuery("SELECT * FROM $tableName", null).use { cursor -> processEmojiCursor(cursor, emojiMap) } } @@ -61,7 +69,8 @@ class EmojiDataManager( .mapNotNull { name -> cursor.getColumnIndex(name).takeIf { it != -1 } } do { - val word = cursor.getString(wordIndex) + // Keys are lowercased so lookups via the user's (lowercased) input match. + val word = cursor.getString(wordIndex)?.lowercase() ?: continue val emojis = emojiIndices .mapNotNull { index -> cursor.getString(index)?.takeIf { it.isNotBlank() } } diff --git a/app/src/main/java/be/scri/helpers/data/SQLiteExtensions.kt b/app/src/main/java/be/scri/helpers/data/SQLiteExtensions.kt index 4d129bc2..587c97ed 100644 --- a/app/src/main/java/be/scri/helpers/data/SQLiteExtensions.kt +++ b/app/src/main/java/be/scri/helpers/data/SQLiteExtensions.kt @@ -6,8 +6,8 @@ import android.database.sqlite.SQLiteDatabase fun SQLiteDatabase.tableExists(tableName: String): Boolean = rawQuery( - "SELECT name FROM sqlite_master WHERE type='table' AND name='$tableName'", - null, + "SELECT name FROM sqlite_master WHERE type='table' AND LOWER(name) = LOWER(?)", + arrayOf(tableName), ).use { it.moveToFirst() } fun SQLiteDatabase.columnExists(