From c9199326bbfea7062ef0f738b3faf36817be982d Mon Sep 17 00:00:00 2001 From: bhanu-dev82 Date: Fri, 28 Feb 2025 01:17:06 +0530 Subject: [PATCH 01/16] fixed Different Keyboard Layouts for Larger Devices like tablets #280 --- .../main/java/be/scri/helpers/KeyboardBase.kt | 31 ++- .../be/scri/services/EnglishKeyboardIME.kt | 58 ++++- .../main/java/be/scri/views/KeyboardView.kt | 17 +- app/src/main/res/values-land/dimens.xml | 75 +++++- app/src/main/res/values-w1240dp/dimens.xml | 75 +++++- app/src/main/res/values-w600dp/dimens.xml | 75 +++++- .../res/xml/keys_letters_english_tablet.xml | 235 ++++++++++++++++++ 7 files changed, 529 insertions(+), 37 deletions(-) create mode 100644 app/src/main/res/xml/keys_letters_english_tablet.xml diff --git a/app/src/main/java/be/scri/helpers/KeyboardBase.kt b/app/src/main/java/be/scri/helpers/KeyboardBase.kt index 92025682..8f8f7ac2 100644 --- a/app/src/main/java/be/scri/helpers/KeyboardBase.kt +++ b/app/src/main/java/be/scri/helpers/KeyboardBase.kt @@ -73,6 +73,13 @@ class KeyboardBase { const val KEYCODE_DELETE = -5 const val KEYCODE_SPACE = 32 const val SCALING_CONSTANT = 150 + const val KEYCODE_TAB = -30 + const val KEYCODE_CAPS_LOCK = -50 + const val KEYCODE_LEFT_ARROW = -55 + const val KEYCODE_RIGHT_ARROW = -56 + const val SHIFT_OFF = 0 + const val SHIFT_ON = 1 + const val SHIFT_LOCKED = 2 fun getDimensionOrFraction( a: TypedArray, @@ -269,9 +276,10 @@ class KeyboardBase { label = a.getText(R.styleable.KeyboardBase_Key_keyLabel) ?: "" topSmallNumber = a.getString(R.styleable.KeyboardBase_Key_topSmallNumber) ?: "" - if (label.isNotEmpty() && code != KEYCODE_MODE_CHANGE && code != KEYCODE_SHIFT) { + if (label.isNotEmpty() && code == 0) { code = label[0].code } + a.recycle() } @@ -318,18 +326,7 @@ class KeyboardBase { @XmlRes xmlLayoutResId: Int, enterKeyType: Int, ) { - mDisplayWidth = - when (context.resources.configuration.orientation) { - Configuration.ORIENTATION_LANDSCAPE -> { - context.resources.displayMetrics.widthPixels - SCALING_CONSTANT - } - Configuration.ORIENTATION_PORTRAIT -> { - context.resources.displayMetrics.widthPixels - } - else -> { - context.resources.displayMetrics.widthPixels - } - } + mDisplayWidth = context.resources.displayMetrics.widthPixels mDefaultHorizontalGap = 0 mDefaultWidth = mDisplayWidth / WIDTH_DIVIDER mDefaultHeight = mDefaultWidth @@ -387,11 +384,13 @@ class KeyboardBase { } fun setShifted(shiftState: Int): Boolean { - if (this.mShiftState != shiftState) { - this.mShiftState = shiftState + if (mShiftState != shiftState) { + mShiftState = when (shiftState) { + SHIFT_ON_PERMANENT -> SHIFT_LOCKED + else -> shiftState and 0x1 // Normal shift handling + } return true } - return false } diff --git a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt index b1eaf52f..7f302473 100644 --- a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt @@ -8,6 +8,7 @@ package be.scri.services import android.text.InputType import android.util.Log +import android.view.KeyEvent import android.view.View import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R @@ -16,12 +17,15 @@ import be.scri.helpers.KeyboardBase import be.scri.views.KeyboardView class EnglishKeyboardIME : GeneralKeyboardIME("English") { - override fun getKeyboardLayoutXML(): Int = - if (getEnablePeriodAndCommaABC()) { - R.xml.keys_letters_english - } else { - R.xml.keys_letters_english_without_period_and_comma - } + private fun isTablet(): Boolean { + return resources.configuration.smallestScreenWidthDp >= 600 + } + + override fun getKeyboardLayoutXML(): Int = when { + isTablet() -> R.xml.keys_letters_english_tablet + getEnablePeriodAndCommaABC() -> R.xml.keys_letters_english + else -> R.xml.keys_letters_english_without_period_and_comma + } override val keyboardLetters = 0 override val keyboardSymbols = 1 @@ -66,6 +70,25 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { } when (code) { + + KeyboardBase.KEYCODE_TAB -> { + currentInputConnection?.commitText("\t", 1) + return + } + + KeyboardBase.KEYCODE_CAPS_LOCK -> { + keyboard?.let { + val newState = when (it.mShiftState) { + KeyboardBase.SHIFT_OFF -> KeyboardBase.SHIFT_LOCKED + else -> KeyboardBase.SHIFT_OFF + } + if (it.setShifted(newState)) { + keyboardView?.invalidateAllKeys() + } + } + return + } + KeyboardBase.KEYCODE_DELETE -> { handleKeycodeDelete() keyboardView!!.invalidateAllKeys() @@ -93,6 +116,9 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { handleKeycodeSpace() } + KeyboardBase.KEYCODE_LEFT_ARROW -> handleLeftArrow() + KeyboardBase.KEYCODE_RIGHT_ARROW -> handleRightArrow() + else -> { if (currentState == ScribeState.IDLE || currentState == ScribeState.SELECT_COMMAND) { handleElseCondition(code, keyboardMode, binding = null) @@ -118,6 +144,23 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { } } + private fun handleLeftArrow() { + currentInputConnection?.let { ic -> + val currentPos = ic.getTextBeforeCursor(1000, 0)?.length ?: 0 + val newPos = (currentPos - 1).coerceAtLeast(0) + ic.setSelection(newPos, newPos) + } + } + + private fun handleRightArrow() { + currentInputConnection?.let { ic -> + val currentPos = ic.getTextBeforeCursor(1000, 0)?.length ?: 0 + val textAfter = ic.getTextAfterCursor(1000, 0)?.toString() ?: "" + val newPos = (currentPos + 1).coerceAtMost(currentPos + textAfter.length + 1) + ic.setSelection(newPos, newPos) + } + } + fun handleKeycodeDelete() { if (currentState == ScribeState.IDLE || currentState == ScribeState.SELECT_COMMAND) { handleDelete(false, keyboardBinding) @@ -150,7 +193,8 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { override fun onCreate() { super.onCreate() - keyboard = KeyboardBase(this, getKeyboardLayoutXML(), enterKeyType) + keyboard = KeyboardBase(this, getKeyboardLayoutXML(), enterKeyType).apply { + } onCreateInputView() setupCommandBarTheme(binding) } diff --git a/app/src/main/java/be/scri/views/KeyboardView.kt b/app/src/main/java/be/scri/views/KeyboardView.kt index d60c8ebf..fdf7c110 100644 --- a/app/src/main/java/be/scri/views/KeyboardView.kt +++ b/app/src/main/java/be/scri/views/KeyboardView.kt @@ -521,14 +521,15 @@ class KeyboardView } } - private fun adjustCase(label: CharSequence?): CharSequence? = - label?.takeIf { it.length in 1..2 }?.let { - if (mKeyboard?.mShiftState?.let { state -> state > SHIFT_OFF } == true) { - label.toString().uppercase(Locale.getDefault()) - } else { - label - } - } ?: label + private fun adjustCase(label: CharSequence?): CharSequence? { + if (label == null) return null + return when { + label.toString() in listOf("tab", "caps lock") -> label // Preserve special labels + mKeyboard?.mShiftState == KeyboardBase.SHIFT_LOCKED || mKeyboard?.mShiftState == KeyboardBase.SHIFT_ON -> + label.toString().uppercase(Locale.getDefault()) + else -> label + } + } public override fun onMeasure( widthMeasureSpec: Int, diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml index 29b71220..936f9dab 100644 --- a/app/src/main/res/values-land/dimens.xml +++ b/app/src/main/res/values-land/dimens.xml @@ -1,3 +1,74 @@ + - 48dp - + 56dp + 10dp + 16dp + 40dp + 36dp + 38dp + 40dp + 40dp + -8dp + 26dp + + 12dp + + 20sp + 24sp + 15sp + + + 1dp + 2dp + 3dp + 5dp + 7dp + 10dp + 14dp + 18dp + 22dp + 28dp + + 38dp + 28dp + 60dp + 220dp + 252dp + 28dp + 28dp + 65dp + + 44dp + 68dp + 52dp + 72dp + 50dp + 38dp + 56dp + 90dp + 3dp + 8dp + 20dp + 44dp + + 52dp + 24dp + 48dp + 72dp + 8dp + 60dp + + 7sp + 9sp + 11sp + 13sp + 15sp + 16sp + 17sp + 19sp + 21sp + + 160dp + 80dp + 14dp + diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml index dc9b7a7d..12a26027 100644 --- a/app/src/main/res/values-w1240dp/dimens.xml +++ b/app/src/main/res/values-w1240dp/dimens.xml @@ -1,3 +1,74 @@ + - 200dp - + 72dp + 14dp + 20dp + 48dp + 44dp + 48dp + 72dp + 48dp + -12dp + 32dp + + 16dp + + 26sp + 30sp + 18sp + + + 1dp + 2dp + 4dp + 8dp + 10dp + 14dp + 20dp + 24dp + 28dp + 40dp + + 48dp + 36dp + 72dp + 280dp + 312dp + 36dp + 36dp + 80dp + + 56dp + 80dp + 64dp + 88dp + 60dp + 48dp + 72dp + 120dp + 6dp + 12dp + 28dp + 56dp + + 64dp + 30dp + 60dp + 96dp + 12dp + 72dp + + 10sp + 12sp + 14sp + 16sp + 18sp + 19sp + 20sp + 22sp + 24sp + + 192dp + 96dp + 20dp + diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml index 29b71220..7aaf1280 100644 --- a/app/src/main/res/values-w600dp/dimens.xml +++ b/app/src/main/res/values-w600dp/dimens.xml @@ -1,3 +1,74 @@ + - 48dp - + 64dp + 12dp + 18dp + 44dp + 40dp + 42dp + 64dp + 44dp + -10dp + 30dp + + 14dp + + 24sp + 28sp + 17sp + + + 1dp + 2dp + 4dp + 6dp + 8dp + 12dp + 16dp + 20dp + 24dp + 32dp + + 42dp + 32dp + 68dp + 256dp + 288dp + 32dp + 32dp + 75dp + + 50dp + 76dp + 60dp + 80dp + 56dp + 42dp + 64dp + 108dp + 4dp + 10dp + 24dp + 50dp + + 60dp + 28dp + 54dp + 84dp + 10dp + 68dp + + 9sp + 11sp + 13sp + 15sp + 17sp + 18sp + 19sp + 21sp + 23sp + + 176dp + 88dp + 18dp + diff --git a/app/src/main/res/xml/keys_letters_english_tablet.xml b/app/src/main/res/xml/keys_letters_english_tablet.xml new file mode 100644 index 00000000..4f2d1137 --- /dev/null +++ b/app/src/main/res/xml/keys_letters_english_tablet.xml @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f189c3278d8902a18a1ae52bda3155a6109dab16 Mon Sep 17 00:00:00 2001 From: bhanu-dev82 Date: Fri, 28 Feb 2025 04:43:38 +0530 Subject: [PATCH 02/16] fixed some ./gradlew lintKotlin detekt test --- .../main/java/be/scri/helpers/KeyboardBase.kt | 17 +- .../be/scri/services/EnglishKeyboardIME.kt | 238 +++++++++--------- .../main/java/be/scri/views/KeyboardView.kt | 22 +- 3 files changed, 148 insertions(+), 129 deletions(-) diff --git a/app/src/main/java/be/scri/helpers/KeyboardBase.kt b/app/src/main/java/be/scri/helpers/KeyboardBase.kt index 8f8f7ac2..5f6ef61f 100644 --- a/app/src/main/java/be/scri/helpers/KeyboardBase.kt +++ b/app/src/main/java/be/scri/helpers/KeyboardBase.kt @@ -139,9 +139,11 @@ class KeyboardBase { Configuration.ORIENTATION_LANDSCAPE -> { res.getDimension(R.dimen.key_height_landscape).toInt() } + Configuration.ORIENTATION_PORTRAIT -> { res.getDimension(R.dimen.key_height).toInt() } + else -> { res.getDimension(R.dimen.key_height).toInt() } @@ -385,10 +387,11 @@ class KeyboardBase { fun setShifted(shiftState: Int): Boolean { if (mShiftState != shiftState) { - mShiftState = when (shiftState) { - SHIFT_ON_PERMANENT -> SHIFT_LOCKED - else -> shiftState and 0x1 // Normal shift handling - } + mShiftState = + when (shiftState) { + SHIFT_ON_PERMANENT -> SHIFT_LOCKED + else -> shiftState and 0x1 + } return true } return false @@ -431,6 +434,7 @@ class KeyboardBase { currentRow = createRowFromXml(res, parser) mRows.add(currentRow) } + TAG_KEY -> { inKey = true key = createKeyFromXml(res, currentRow!!, x, y, parser) @@ -440,14 +444,18 @@ class KeyboardBase { when (mEnterKeyType) { EditorInfo.IME_ACTION_SEARCH -> R.drawable.ic_search_vector + EditorInfo.IME_ACTION_NEXT, EditorInfo.IME_ACTION_GO, -> R.drawable.ic_arrow_right_vector + EditorInfo.IME_ACTION_SEND -> R.drawable.ic_send_vector + MyCustomActions.IME_ACTION_COMMAND -> R.drawable.play_button + else -> R.drawable.ic_enter_vector } @@ -455,6 +463,7 @@ class KeyboardBase { } currentRow.mKeys.add(key) } + TAG_KEYBOARD -> { parseKeyboardAttributes(res, parser) } diff --git a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt index 7f302473..b9c3e083 100644 --- a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt @@ -8,7 +8,6 @@ package be.scri.services import android.text.InputType import android.util.Log -import android.view.KeyEvent import android.view.View import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R @@ -17,15 +16,20 @@ import be.scri.helpers.KeyboardBase import be.scri.views.KeyboardView class EnglishKeyboardIME : GeneralKeyboardIME("English") { - private fun isTablet(): Boolean { - return resources.configuration.smallestScreenWidthDp >= 600 + companion object { + private const val SMALLEST_SCREEN_WIDTH_TABLET = 600 + private const val MAX_TEXT_LENGTH = 1000 + private const val COMMIT_TEXT_CURSOR_POSITION = 1 } - override fun getKeyboardLayoutXML(): Int = when { - isTablet() -> R.xml.keys_letters_english_tablet - getEnablePeriodAndCommaABC() -> R.xml.keys_letters_english - else -> R.xml.keys_letters_english_without_period_and_comma - } + private fun isTablet(): Boolean = resources.configuration.smallestScreenWidthDp >= SMALLEST_SCREEN_WIDTH_TABLET + + override fun getKeyboardLayoutXML(): Int = + when { + isTablet() -> R.xml.keys_letters_english_tablet + getEnablePeriodAndCommaABC() -> R.xml.keys_letters_english + else -> R.xml.keys_letters_english_without_period_and_comma + } override val keyboardLetters = 0 override val keyboardSymbols = 1 @@ -41,6 +45,9 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { override var hasTextBeforeCursor = false override lateinit var binding: KeyboardViewCommandOptionsBinding + // Key handling logic extracted to a separate class + private val keyHandler = KeyHandler(this) + override fun onCreateInputView(): View { binding = KeyboardViewCommandOptionsBinding.inflate(layoutInflater) setupCommandBarTheme(binding) @@ -61,141 +68,138 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { } override fun onKey(code: Int) { - val inputConnection = currentInputConnection - if (keyboard == null || inputConnection == null) { - return - } - if (code != KeyboardBase.KEYCODE_SHIFT) { - lastShiftPressTS = 0 - } - - when (code) { + keyHandler.handleKey(code) + } - KeyboardBase.KEYCODE_TAB -> { - currentInputConnection?.commitText("\t", 1) - return - } + override fun onCreate() { + super.onCreate() + keyboard = KeyboardBase(this, getKeyboardLayoutXML(), enterKeyType) + onCreateInputView() + setupCommandBarTheme(binding) + } - KeyboardBase.KEYCODE_CAPS_LOCK -> { - keyboard?.let { - val newState = when (it.mShiftState) { - KeyboardBase.SHIFT_OFF -> KeyboardBase.SHIFT_LOCKED - else -> KeyboardBase.SHIFT_OFF - } - if (it.setShifted(newState)) { - keyboardView?.invalidateAllKeys() - } - } + // Inner class to handle key events + inner class KeyHandler( + private val ime: EnglishKeyboardIME, + ) { + fun handleKey(code: Int) { + val inputConnection = ime.currentInputConnection + if (ime.keyboard == null || inputConnection == null) { return } - - KeyboardBase.KEYCODE_DELETE -> { - handleKeycodeDelete() - keyboardView!!.invalidateAllKeys() - disableAutoSuggest() - } - - KeyboardBase.KEYCODE_SHIFT -> { - super.handleKeyboardLetters(keyboardMode, keyboardView) - keyboardView!!.invalidateAllKeys() - disableAutoSuggest() + if (code != KeyboardBase.KEYCODE_SHIFT) { + ime.lastShiftPressTS = 0 } - KeyboardBase.KEYCODE_ENTER -> { - disableAutoSuggest() - handleKeycodeEnter() - updateAutoSuggestText(isPlural = checkIfPluralWord, nounTypeSuggestion = nounTypeSuggestion) - } - - KeyboardBase.KEYCODE_MODE_CHANGE -> { - handleModeChange(keyboardMode, keyboardView, this) - disableAutoSuggest() + when (code) { + KeyboardBase.KEYCODE_TAB -> inputConnection.commitText("\t", COMMIT_TEXT_CURSOR_POSITION) + KeyboardBase.KEYCODE_CAPS_LOCK -> handleCapsLock() + KeyboardBase.KEYCODE_DELETE -> handleDeleteKey() + KeyboardBase.KEYCODE_SHIFT -> handleShiftKey() + KeyboardBase.KEYCODE_ENTER -> handleEnterKey() + KeyboardBase.KEYCODE_MODE_CHANGE -> handleModeChangeKey() + KeyboardBase.KEYCODE_SPACE -> handleKeycodeSpace() + KeyboardBase.KEYCODE_LEFT_ARROW -> handleArrowKey(false) + KeyboardBase.KEYCODE_RIGHT_ARROW -> handleArrowKey(true) + else -> handleDefaultKey(code) } + updateKeyboardState(code) + } - KeyboardBase.KEYCODE_SPACE -> { - handleKeycodeSpace() + private fun updateKeyboardState(code: Int) { + ime.lastWord = ime.getLastWordBeforeCursor() + Log.d("Debug", "${ime.lastWord}") + ime.autosuggestEmojis = ime.findEmojisForLastWord(ime.emojiKeywords, ime.lastWord) + ime.checkIfPluralWord = ime.findWheatherWordIsPlural(ime.pluralWords, ime.lastWord) + + Log.i("MY-TAG", "${ime.checkIfPluralWord}") + Log.d("Debug", "${ime.autosuggestEmojis}") + Log.d("MY-TAG", "${ime.nounTypeSuggestion}") + ime.updateButtonText(ime.isAutoSuggestEnabled, ime.autosuggestEmojis) + if (code != KeyboardBase.KEYCODE_SHIFT) { + ime.updateShiftKeyState() } + } - KeyboardBase.KEYCODE_LEFT_ARROW -> handleLeftArrow() - KeyboardBase.KEYCODE_RIGHT_ARROW -> handleRightArrow() - - else -> { - if (currentState == ScribeState.IDLE || currentState == ScribeState.SELECT_COMMAND) { - handleElseCondition(code, keyboardMode, binding = null) - disableAutoSuggest() - } else { - handleElseCondition(code, keyboardMode, keyboardBinding, commandBarState = true) - disableAutoSuggest() + private fun handleCapsLock() { + ime.keyboard?.let { + val newState = + when (it.mShiftState) { + KeyboardBase.SHIFT_OFF -> KeyboardBase.SHIFT_LOCKED + else -> KeyboardBase.SHIFT_OFF + } + if (it.setShifted(newState)) { + ime.keyboardView?.invalidateAllKeys() } } } - lastWord = getLastWordBeforeCursor() - Log.d("Debug", "$lastWord") - autosuggestEmojis = findEmojisForLastWord(emojiKeywords, lastWord) - checkIfPluralWord = findWheatherWordIsPlural(pluralWords, lastWord) - - Log.i("MY-TAG", "$checkIfPluralWord") - Log.d("Debug", "$autosuggestEmojis") - Log.d("MY-TAG", "$nounTypeSuggestion") - updateButtonText(isAutoSuggestEnabled, autosuggestEmojis) - if (code != KeyboardBase.KEYCODE_SHIFT) { - super.updateShiftKeyState() + private fun handleDefaultKey(code: Int) { + if (ime.currentState == ScribeState.IDLE || ime.currentState == ScribeState.SELECT_COMMAND) { + ime.handleElseCondition(code, ime.keyboardMode, binding = null) + } else { + ime.handleElseCondition(code, ime.keyboardMode, ime.keyboardBinding, commandBarState = true) + } + ime.disableAutoSuggest() } - } - private fun handleLeftArrow() { - currentInputConnection?.let { ic -> - val currentPos = ic.getTextBeforeCursor(1000, 0)?.length ?: 0 - val newPos = (currentPos - 1).coerceAtLeast(0) - ic.setSelection(newPos, newPos) + private fun handleDeleteKey() { + val shouldDelete = + when (ime.currentState) { + ScribeState.IDLE, ScribeState.SELECT_COMMAND -> false + else -> true + } + ime.handleDelete(shouldDelete, ime.keyboardBinding) + ime.keyboardView!!.invalidateAllKeys() + ime.disableAutoSuggest() } - } - private fun handleRightArrow() { - currentInputConnection?.let { ic -> - val currentPos = ic.getTextBeforeCursor(1000, 0)?.length ?: 0 - val textAfter = ic.getTextAfterCursor(1000, 0)?.toString() ?: "" - val newPos = (currentPos + 1).coerceAtMost(currentPos + textAfter.length + 1) - ic.setSelection(newPos, newPos) + private fun handleShiftKey() { + ime.handleKeyboardLetters(ime.keyboardMode, ime.keyboardView) + ime.keyboardView!!.invalidateAllKeys() + ime.disableAutoSuggest() } - } - fun handleKeycodeDelete() { - if (currentState == ScribeState.IDLE || currentState == ScribeState.SELECT_COMMAND) { - handleDelete(false, keyboardBinding) - } else { - handleDelete(true, keyboardBinding) + private fun handleEnterKey() { + if (ime.currentState == ScribeState.IDLE || ime.currentState == ScribeState.SELECT_COMMAND) { + ime.handleKeycodeEnter(ime.keyboardBinding, false) + } else { + ime.handleKeycodeEnter(ime.keyboardBinding, true) + ime.currentState = ScribeState.IDLE + ime.switchToCommandToolBar() + ime.updateUI() + } + ime.disableAutoSuggest() } - } - fun handleKeycodeEnter() { - if (currentState == ScribeState.IDLE || currentState == ScribeState.SELECT_COMMAND) { - handleKeycodeEnter(keyboardBinding, false) - } else { - handleKeycodeEnter(keyboardBinding, true) - currentState = ScribeState.IDLE - switchToCommandToolBar() - updateUI() + private fun handleModeChangeKey() { + ime.handleModeChange(ime.keyboardMode, ime.keyboardView, ime) + ime.disableAutoSuggest() } - } - fun handleKeycodeSpace() { - val code = KeyboardBase.KEYCODE_SPACE - if (currentState == ScribeState.IDLE || currentState == ScribeState.SELECT_COMMAND) { - handleElseCondition(code, keyboardMode, binding = null) - updateAutoSuggestText(isPlural = checkIfPluralWord) - } else { - handleElseCondition(code, keyboardMode, keyboardBinding, commandBarState = true) - disableAutoSuggest() + private fun handleArrowKey(isRight: Boolean) { + ime.currentInputConnection?.let { ic -> + val currentPos = ic.getTextBeforeCursor(MAX_TEXT_LENGTH, 0)?.length ?: 0 + val newPos = + if (isRight) { + val textAfter = ic.getTextAfterCursor(MAX_TEXT_LENGTH, 0)?.toString() ?: "" + (currentPos + 1).coerceAtMost(currentPos + textAfter.length) + } else { + (currentPos - 1).coerceAtLeast(0) + } + ic.setSelection(newPos, newPos) + } } - } - override fun onCreate() { - super.onCreate() - keyboard = KeyboardBase(this, getKeyboardLayoutXML(), enterKeyType).apply { + private fun handleKeycodeSpace() { + val code = KeyboardBase.KEYCODE_SPACE + if (ime.currentState == ScribeState.IDLE || ime.currentState == ScribeState.SELECT_COMMAND) { + ime.handleElseCondition(code, ime.keyboardMode, binding = null) + ime.updateAutoSuggestText(isPlural = ime.checkIfPluralWord) + } else { + ime.handleElseCondition(code, ime.keyboardMode, ime.keyboardBinding, commandBarState = true) + ime.disableAutoSuggest() + } } - onCreateInputView() - setupCommandBarTheme(binding) } } diff --git a/app/src/main/java/be/scri/views/KeyboardView.kt b/app/src/main/java/be/scri/views/KeyboardView.kt index fdf7c110..6c3d2f25 100644 --- a/app/src/main/java/be/scri/views/KeyboardView.kt +++ b/app/src/main/java/be/scri/views/KeyboardView.kt @@ -521,15 +521,21 @@ class KeyboardView } } - private fun adjustCase(label: CharSequence?): CharSequence? { - if (label == null) return null - return when { - label.toString() in listOf("tab", "caps lock") -> label // Preserve special labels - mKeyboard?.mShiftState == KeyboardBase.SHIFT_LOCKED || mKeyboard?.mShiftState == KeyboardBase.SHIFT_ON -> - label.toString().uppercase(Locale.getDefault()) - else -> label + private fun adjustCase(label: CharSequence?): CharSequence? { + if (label == null) return null + return when { + label.toString() in listOf("tab", "caps lock") -> label + + mKeyboard?.mShiftState in + setOf( + KeyboardBase.SHIFT_LOCKED, + KeyboardBase.SHIFT_ON, + ) + -> label.toString().uppercase(Locale.getDefault()) + + else -> label + } } - } public override fun onMeasure( widthMeasureSpec: Int, From b9cf2dbc21d2dfe18bf0b06c56ac2fd073b54ceb Mon Sep 17 00:00:00 2001 From: bhanu-dev82 Date: Fri, 28 Feb 2025 15:16:14 +0530 Subject: [PATCH 03/16] made a sperate helper file from EnglishKeyboardIme and 20 percent increase in key heigth for tablet mode --- .../be/scri/services/EnglishKeyboardIME.kt | 132 +---------------- .../be/scri/services/GeneralKeyboardIME.kt | 6 +- .../main/java/be/scri/services/KeyHandler.kt | 136 ++++++++++++++++++ app/src/main/res/values-land/dimens.xml | 4 +- app/src/main/res/values-w1240dp/dimens.xml | 4 +- app/src/main/res/values-w600dp/dimens.xml | 2 +- 6 files changed, 147 insertions(+), 137 deletions(-) create mode 100644 app/src/main/java/be/scri/services/KeyHandler.kt diff --git a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt index b9c3e083..26bf8039 100644 --- a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt @@ -7,7 +7,6 @@ package be.scri.services import android.text.InputType -import android.util.Log import android.view.View import android.view.inputmethod.EditorInfo.IME_ACTION_NONE import be.scri.R @@ -17,9 +16,9 @@ import be.scri.views.KeyboardView class EnglishKeyboardIME : GeneralKeyboardIME("English") { companion object { - private const val SMALLEST_SCREEN_WIDTH_TABLET = 600 - private const val MAX_TEXT_LENGTH = 1000 - private const val COMMIT_TEXT_CURSOR_POSITION = 1 + const val SMALLEST_SCREEN_WIDTH_TABLET = 600 + const val MAX_TEXT_LENGTH = 1000 + const val COMMIT_TEXT_CURSOR_POSITION = 1 } private fun isTablet(): Boolean = resources.configuration.smallestScreenWidthDp >= SMALLEST_SCREEN_WIDTH_TABLET @@ -77,129 +76,4 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { onCreateInputView() setupCommandBarTheme(binding) } - - // Inner class to handle key events - inner class KeyHandler( - private val ime: EnglishKeyboardIME, - ) { - fun handleKey(code: Int) { - val inputConnection = ime.currentInputConnection - if (ime.keyboard == null || inputConnection == null) { - return - } - if (code != KeyboardBase.KEYCODE_SHIFT) { - ime.lastShiftPressTS = 0 - } - - when (code) { - KeyboardBase.KEYCODE_TAB -> inputConnection.commitText("\t", COMMIT_TEXT_CURSOR_POSITION) - KeyboardBase.KEYCODE_CAPS_LOCK -> handleCapsLock() - KeyboardBase.KEYCODE_DELETE -> handleDeleteKey() - KeyboardBase.KEYCODE_SHIFT -> handleShiftKey() - KeyboardBase.KEYCODE_ENTER -> handleEnterKey() - KeyboardBase.KEYCODE_MODE_CHANGE -> handleModeChangeKey() - KeyboardBase.KEYCODE_SPACE -> handleKeycodeSpace() - KeyboardBase.KEYCODE_LEFT_ARROW -> handleArrowKey(false) - KeyboardBase.KEYCODE_RIGHT_ARROW -> handleArrowKey(true) - else -> handleDefaultKey(code) - } - updateKeyboardState(code) - } - - private fun updateKeyboardState(code: Int) { - ime.lastWord = ime.getLastWordBeforeCursor() - Log.d("Debug", "${ime.lastWord}") - ime.autosuggestEmojis = ime.findEmojisForLastWord(ime.emojiKeywords, ime.lastWord) - ime.checkIfPluralWord = ime.findWheatherWordIsPlural(ime.pluralWords, ime.lastWord) - - Log.i("MY-TAG", "${ime.checkIfPluralWord}") - Log.d("Debug", "${ime.autosuggestEmojis}") - Log.d("MY-TAG", "${ime.nounTypeSuggestion}") - ime.updateButtonText(ime.isAutoSuggestEnabled, ime.autosuggestEmojis) - if (code != KeyboardBase.KEYCODE_SHIFT) { - ime.updateShiftKeyState() - } - } - - private fun handleCapsLock() { - ime.keyboard?.let { - val newState = - when (it.mShiftState) { - KeyboardBase.SHIFT_OFF -> KeyboardBase.SHIFT_LOCKED - else -> KeyboardBase.SHIFT_OFF - } - if (it.setShifted(newState)) { - ime.keyboardView?.invalidateAllKeys() - } - } - } - - private fun handleDefaultKey(code: Int) { - if (ime.currentState == ScribeState.IDLE || ime.currentState == ScribeState.SELECT_COMMAND) { - ime.handleElseCondition(code, ime.keyboardMode, binding = null) - } else { - ime.handleElseCondition(code, ime.keyboardMode, ime.keyboardBinding, commandBarState = true) - } - ime.disableAutoSuggest() - } - - private fun handleDeleteKey() { - val shouldDelete = - when (ime.currentState) { - ScribeState.IDLE, ScribeState.SELECT_COMMAND -> false - else -> true - } - ime.handleDelete(shouldDelete, ime.keyboardBinding) - ime.keyboardView!!.invalidateAllKeys() - ime.disableAutoSuggest() - } - - private fun handleShiftKey() { - ime.handleKeyboardLetters(ime.keyboardMode, ime.keyboardView) - ime.keyboardView!!.invalidateAllKeys() - ime.disableAutoSuggest() - } - - private fun handleEnterKey() { - if (ime.currentState == ScribeState.IDLE || ime.currentState == ScribeState.SELECT_COMMAND) { - ime.handleKeycodeEnter(ime.keyboardBinding, false) - } else { - ime.handleKeycodeEnter(ime.keyboardBinding, true) - ime.currentState = ScribeState.IDLE - ime.switchToCommandToolBar() - ime.updateUI() - } - ime.disableAutoSuggest() - } - - private fun handleModeChangeKey() { - ime.handleModeChange(ime.keyboardMode, ime.keyboardView, ime) - ime.disableAutoSuggest() - } - - private fun handleArrowKey(isRight: Boolean) { - ime.currentInputConnection?.let { ic -> - val currentPos = ic.getTextBeforeCursor(MAX_TEXT_LENGTH, 0)?.length ?: 0 - val newPos = - if (isRight) { - val textAfter = ic.getTextAfterCursor(MAX_TEXT_LENGTH, 0)?.toString() ?: "" - (currentPos + 1).coerceAtMost(currentPos + textAfter.length) - } else { - (currentPos - 1).coerceAtLeast(0) - } - ic.setSelection(newPos, newPos) - } - } - - private fun handleKeycodeSpace() { - val code = KeyboardBase.KEYCODE_SPACE - if (ime.currentState == ScribeState.IDLE || ime.currentState == ScribeState.SELECT_COMMAND) { - ime.handleElseCondition(code, ime.keyboardMode, binding = null) - ime.updateAutoSuggestText(isPlural = ime.checkIfPluralWord) - } else { - ime.handleElseCondition(code, ime.keyboardMode, ime.keyboardBinding, commandBarState = true) - ime.disableAutoSuggest() - } - } - } } diff --git a/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt b/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt index 0628e613..5cf3b00e 100644 --- a/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/GeneralKeyboardIME.kt @@ -127,8 +127,8 @@ abstract class GeneralKeyboardIME( ), ) - protected var currentState: ScribeState = ScribeState.IDLE - protected lateinit var keyboardBinding: KeyboardViewKeyboardBinding + internal var currentState: ScribeState = ScribeState.IDLE + internal lateinit var keyboardBinding: KeyboardViewKeyboardBinding enum class ScribeState { IDLE, @@ -238,7 +238,7 @@ abstract class GeneralKeyboardIME( } } - protected fun switchToCommandToolBar() { + internal fun switchToCommandToolBar() { val binding = KeyboardViewCommandOptionsBinding.inflate(layoutInflater) this.binding = binding val keyboardHolder = binding.root diff --git a/app/src/main/java/be/scri/services/KeyHandler.kt b/app/src/main/java/be/scri/services/KeyHandler.kt new file mode 100644 index 00000000..bc2d8714 --- /dev/null +++ b/app/src/main/java/be/scri/services/KeyHandler.kt @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +package be.scri.services + +import android.util.Log +import be.scri.helpers.KeyboardBase +import be.scri.services.GeneralKeyboardIME.ScribeState + +/** + * Handles key events for the EnglishKeyboardIME. + */ +class KeyHandler( + private val ime: EnglishKeyboardIME, +) { + /** + * Processes the given key code and performs the corresponding action. + */ + fun handleKey(code: Int) { + val inputConnection = ime.currentInputConnection + if (ime.keyboard == null || inputConnection == null) { + return + } + if (code != KeyboardBase.KEYCODE_SHIFT) { + ime.lastShiftPressTS = 0 + } + + when (code) { + KeyboardBase.KEYCODE_TAB -> inputConnection.commitText("\t", EnglishKeyboardIME.COMMIT_TEXT_CURSOR_POSITION) + KeyboardBase.KEYCODE_CAPS_LOCK -> handleCapsLock() + KeyboardBase.KEYCODE_DELETE -> handleDeleteKey() + KeyboardBase.KEYCODE_SHIFT -> handleShiftKey() + KeyboardBase.KEYCODE_ENTER -> handleEnterKey() + KeyboardBase.KEYCODE_MODE_CHANGE -> handleModeChangeKey() + KeyboardBase.KEYCODE_SPACE -> handleKeycodeSpace() + KeyboardBase.KEYCODE_LEFT_ARROW -> handleArrowKey(false) + KeyboardBase.KEYCODE_RIGHT_ARROW -> handleArrowKey(true) + else -> handleDefaultKey(code) + } + updateKeyboardState(code) + } + + private fun updateKeyboardState(code: Int) { + ime.lastWord = ime.getLastWordBeforeCursor() + Log.d("Debug", "${ime.lastWord}") + ime.autosuggestEmojis = ime.findEmojisForLastWord(ime.emojiKeywords, ime.lastWord) + ime.checkIfPluralWord = ime.findWheatherWordIsPlural(ime.pluralWords, ime.lastWord) + + Log.i("MY-TAG", "${ime.checkIfPluralWord}") + Log.d("Debug", "${ime.autosuggestEmojis}") + Log.d("MY-TAG", "${ime.nounTypeSuggestion}") + ime.updateButtonText(ime.isAutoSuggestEnabled, ime.autosuggestEmojis) + if (code != KeyboardBase.KEYCODE_SHIFT) { + ime.updateShiftKeyState() + } + } + + private fun handleCapsLock() { + ime.keyboard?.let { + val newState = + when (it.mShiftState) { + KeyboardBase.SHIFT_OFF -> KeyboardBase.SHIFT_LOCKED + else -> KeyboardBase.SHIFT_OFF + } + if (it.setShifted(newState)) { + ime.keyboardView?.invalidateAllKeys() + } + } + } + + private fun handleDefaultKey(code: Int) { + if (ime.currentState == ScribeState.IDLE || ime.currentState == ScribeState.SELECT_COMMAND) { + ime.handleElseCondition(code, ime.keyboardMode, binding = null) + } else { + ime.handleElseCondition(code, ime.keyboardMode, ime.keyboardBinding, commandBarState = true) + } + ime.disableAutoSuggest() + } + + private fun handleDeleteKey() { + val shouldDelete = + when (ime.currentState) { + ScribeState.IDLE, ScribeState.SELECT_COMMAND -> false + else -> true + } + ime.handleDelete(shouldDelete, ime.keyboardBinding) + ime.keyboardView!!.invalidateAllKeys() + ime.disableAutoSuggest() + } + + private fun handleShiftKey() { + ime.handleKeyboardLetters(ime.keyboardMode, ime.keyboardView) + ime.keyboardView!!.invalidateAllKeys() + ime.disableAutoSuggest() + } + + private fun handleEnterKey() { + if (ime.currentState == ScribeState.IDLE || ime.currentState == ScribeState.SELECT_COMMAND) { + ime.handleKeycodeEnter(ime.keyboardBinding, false) + } else { + ime.handleKeycodeEnter(ime.keyboardBinding, true) + ime.currentState = ScribeState.IDLE + ime.switchToCommandToolBar() + ime.updateUI() + } + ime.disableAutoSuggest() + } + + private fun handleModeChangeKey() { + ime.handleModeChange(ime.keyboardMode, ime.keyboardView, ime) + ime.disableAutoSuggest() + } + + private fun handleArrowKey(isRight: Boolean) { + ime.currentInputConnection?.let { ic -> + val currentPos = ic.getTextBeforeCursor(EnglishKeyboardIME.MAX_TEXT_LENGTH, 0)?.length ?: 0 + val newPos = + if (isRight) { + val textAfter = ic.getTextAfterCursor(EnglishKeyboardIME.MAX_TEXT_LENGTH, 0)?.toString() ?: "" + (currentPos + 1).coerceAtMost(currentPos + textAfter.length) + } else { + (currentPos - 1).coerceAtLeast(0) + } + ic.setSelection(newPos, newPos) + } + } + + private fun handleKeycodeSpace() { + val code = KeyboardBase.KEYCODE_SPACE + if (ime.currentState == ScribeState.IDLE || ime.currentState == ScribeState.SELECT_COMMAND) { + ime.handleElseCondition(code, ime.keyboardMode, binding = null) + ime.updateAutoSuggestText(isPlural = ime.checkIfPluralWord) + } else { + ime.handleElseCondition(code, ime.keyboardMode, ime.keyboardBinding, commandBarState = true) + ime.disableAutoSuggest() + } + } +} diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml index 936f9dab..2e855916 100644 --- a/app/src/main/res/values-land/dimens.xml +++ b/app/src/main/res/values-land/dimens.xml @@ -6,8 +6,8 @@ 40dp 36dp 38dp - 40dp - 40dp + 50dp + 50dp -8dp 26dp diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml index 12a26027..ea776d20 100644 --- a/app/src/main/res/values-w1240dp/dimens.xml +++ b/app/src/main/res/values-w1240dp/dimens.xml @@ -6,8 +6,8 @@ 48dp 44dp 48dp - 72dp - 48dp + 80dp + 56dp -12dp 32dp diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml index 7aaf1280..07903000 100644 --- a/app/src/main/res/values-w600dp/dimens.xml +++ b/app/src/main/res/values-w600dp/dimens.xml @@ -7,7 +7,7 @@ 40dp 42dp 64dp - 44dp + 50dp -10dp 30dp From eb02b9122c4c2adec4e18e229358bc40812badee Mon Sep 17 00:00:00 2001 From: bhanu-dev82 Date: Fri, 28 Feb 2025 18:05:48 +0530 Subject: [PATCH 04/16] fixed the merge conflit errors --- app/src/main/java/be/scri/services/EnglishKeyboardIME.kt | 6 +++--- app/src/main/java/be/scri/services/KeyHandler.kt | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt index 7bba3208..045c93db 100644 --- a/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt +++ b/app/src/main/java/be/scri/services/EnglishKeyboardIME.kt @@ -28,7 +28,7 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { } private fun isTablet(): Boolean = resources.configuration.smallestScreenWidthDp >= SMALLEST_SCREEN_WIDTH_TABLET - + /** * Returns the XML layout resource for the keyboard based on user preferences. * @return The resource ID of the keyboard layout XML. @@ -36,7 +36,7 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { override fun getKeyboardLayoutXML(): Int = when { isTablet() -> R.xml.keys_letters_english_tablet - getEnablePeriodAndCommaABC() -> R.xml.keys_letters_english + getEnablePeriodAndCommaABC(applicationContext, language) -> R.xml.keys_letters_english else -> R.xml.keys_letters_english_without_period_and_comma } @@ -56,7 +56,7 @@ class EnglishKeyboardIME : GeneralKeyboardIME("English") { // Key handling logic extracted to a separate class private val keyHandler = KeyHandler(this) - + /** * Creates and returns the input view for the keyboard. * @return The root view of the keyboard layout. diff --git a/app/src/main/java/be/scri/services/KeyHandler.kt b/app/src/main/java/be/scri/services/KeyHandler.kt index bc2d8714..1d18a2d1 100644 --- a/app/src/main/java/be/scri/services/KeyHandler.kt +++ b/app/src/main/java/be/scri/services/KeyHandler.kt @@ -41,13 +41,13 @@ class KeyHandler( private fun updateKeyboardState(code: Int) { ime.lastWord = ime.getLastWordBeforeCursor() Log.d("Debug", "${ime.lastWord}") - ime.autosuggestEmojis = ime.findEmojisForLastWord(ime.emojiKeywords, ime.lastWord) - ime.checkIfPluralWord = ime.findWheatherWordIsPlural(ime.pluralWords, ime.lastWord) + ime.autoSuggestEmojis = ime.findEmojisForLastWord(ime.emojiKeywords, ime.lastWord) + ime.checkIfPluralWord = ime.findWhetherWordIsPlural(ime.pluralWords, ime.lastWord) Log.i("MY-TAG", "${ime.checkIfPluralWord}") - Log.d("Debug", "${ime.autosuggestEmojis}") + Log.d("Debug", "${ime.autoSuggestEmojis}") Log.d("MY-TAG", "${ime.nounTypeSuggestion}") - ime.updateButtonText(ime.isAutoSuggestEnabled, ime.autosuggestEmojis) + ime.updateButtonText(ime.emojiAutoSuggestionEnabled, ime.autoSuggestEmojis) if (code != KeyboardBase.KEYCODE_SHIFT) { ime.updateShiftKeyState() } From be7ca0c41984301f59658318fc7ba7fe5ef7c793 Mon Sep 17 00:00:00 2001 From: bhanu-dev82 Date: Fri, 28 Feb 2025 19:09:02 +0530 Subject: [PATCH 05/16] increased the width of scribe button --- app/src/main/res/layout/keyboard_view_command_options.xml | 2 +- app/src/main/res/values-land/dimens.xml | 1 + app/src/main/res/values/dimens.xml | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/layout/keyboard_view_command_options.xml b/app/src/main/res/layout/keyboard_view_command_options.xml index 7bb095d4..38a0e6b9 100644 --- a/app/src/main/res/layout/keyboard_view_command_options.xml +++ b/app/src/main/res/layout/keyboard_view_command_options.xml @@ -15,7 +15,7 @@