diff --git a/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/Constants.kt b/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/Constants.kt index 383b120..dfd33e7 100644 --- a/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/Constants.kt +++ b/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/Constants.kt @@ -1,5 +1,12 @@ package com.simplemobiletools.keyboard.helpers + +enum class ShiftState { + OFF, + ON_ONE_CHAR, + ON_PERMANENT; +} + // limit the count of alternative characters that show up at long pressing a key const val MAX_KEYS_PER_MINI_ROW = 9 diff --git a/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/MyKeyboard.kt b/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/MyKeyboard.kt index 18bb355..a8325d3 100644 --- a/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/MyKeyboard.kt +++ b/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/MyKeyboard.kt @@ -242,12 +242,7 @@ class MyKeyboard { fun isInside(x: Int, y: Int): Boolean { val leftEdge = edgeFlags and EDGE_LEFT > 0 val rightEdge = edgeFlags and EDGE_RIGHT > 0 - return ( - (x >= this.x || leftEdge && x <= this.x + width) && - (x < this.x + width || rightEdge && x >= this.x) && - (y >= this.y && y <= this.y + height) && - (y < this.y + height && y >= this.y) - ) + return ((x >= this.x || leftEdge && x <= this.x + width) && (x < this.x + width || rightEdge && x >= this.x) && (y >= this.y && y <= this.y + height) && (y < this.y + height && y >= this.y)) } } @@ -258,14 +253,13 @@ class MyKeyboard { * @param enterKeyType determines what icon should we show on Enter key */ @JvmOverloads - constructor(context: Context, @XmlRes xmlLayoutResId: Int, enterKeyType: Int, shiftState: ShiftState = ShiftState.OFF) { + constructor(context: Context, @XmlRes xmlLayoutResId: Int, enterKeyType: Int) { mDisplayWidth = context.resources.displayMetrics.widthPixels mDefaultHorizontalGap = 0 mDefaultWidth = mDisplayWidth / 10 mDefaultHeight = mDefaultWidth mKeyboardHeightMultiplier = getKeyboardHeightMultiplier(context.config.keyboardHeightMultiplier) mKeys = ArrayList() - mShiftState = shiftState mEnterKeyType = enterKeyType loadKeyboard(context, context.resources.getXml(xmlLayoutResId)) } @@ -278,8 +272,7 @@ class MyKeyboard { * @param characters the list of characters to display on the keyboard. One key will be created for each character. * @param keyWidth the width of the popup key, make sure it is the same as the key itself */ - constructor(context: Context, layoutTemplateResId: Int, characters: CharSequence, keyWidth: Int) : - this(context, layoutTemplateResId, 0) { + constructor(context: Context, layoutTemplateResId: Int, characters: CharSequence, keyWidth: Int) : this(context, layoutTemplateResId, 0) { var x = 0 var y = 0 var column = 0 diff --git a/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/ShiftState.kt b/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/ShiftState.kt deleted file mode 100644 index b00b4bc..0000000 --- a/app/src/main/kotlin/com/simplemobiletools/keyboard/helpers/ShiftState.kt +++ /dev/null @@ -1,81 +0,0 @@ -package com.simplemobiletools.keyboard.helpers - -import android.content.Context -import android.text.InputType -import com.simplemobiletools.keyboard.extensions.config - -enum class ShiftState { - OFF, - ON_ONE_CHAR, - ON_PERMANENT; - - companion object { - private val endOfSentenceChars: List = listOf('.', '?', '!') - private const val MIN_TEXT_LENGTH = 2 - - /** - * Input Type exceptions for capitalizing. - */ - private val inputTypeExceptions = listOf( - InputType.TYPE_TEXT_VARIATION_PASSWORD, - InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD, - InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD, - InputType.TYPE_NUMBER_VARIATION_PASSWORD, - InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS, - InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS, - InputType.TYPE_TEXT_VARIATION_URI - ) - - fun getDefaultShiftState(context: Context, inputTypeClassVariation: Int): ShiftState { - if (isInputTypeAllowedCapitalizing(inputTypeClassVariation)) { - return OFF - } - - return if (context.config.enableSentencesCapitalization) { - ON_ONE_CHAR - } else { - OFF - } - } - - fun getShiftStateForText(context: Context, inputTypeClassVariation: Int, text: String?): ShiftState { - if (isInputTypeAllowedCapitalizing(inputTypeClassVariation)) { - return OFF - } - - return if (shouldCapitalize(context, text)) { - ON_ONE_CHAR - } else { - OFF - } - } - - /** - * The function is checking whether there is a need in capitalizing based on the given text - * @param context Used for checking current sentences capitalization setting - * @param text Last text from the input - */ - fun shouldCapitalize(context: Context, text: String?): Boolean { - // check whether it is the first letter in textField - if (text.isNullOrEmpty()) { - return true - } - - if (!context.config.enableSentencesCapitalization) { - return false - } - - val twoLastSymbols = text.takeLast(2) - - if (twoLastSymbols.length < MIN_TEXT_LENGTH) { - return false - } - - return endOfSentenceChars.contains(twoLastSymbols.first()) && twoLastSymbols.last().code == MyKeyboard.KEYCODE_SPACE - } - - fun isInputTypeAllowedCapitalizing(inputTypeVariation: Int): Boolean { - return inputTypeVariation in inputTypeExceptions - } - } -} diff --git a/app/src/main/kotlin/com/simplemobiletools/keyboard/services/SimpleKeyboardIME.kt b/app/src/main/kotlin/com/simplemobiletools/keyboard/services/SimpleKeyboardIME.kt index 05752c8..2148f08 100644 --- a/app/src/main/kotlin/com/simplemobiletools/keyboard/services/SimpleKeyboardIME.kt +++ b/app/src/main/kotlin/com/simplemobiletools/keyboard/services/SimpleKeyboardIME.kt @@ -2,7 +2,6 @@ package com.simplemobiletools.keyboard.services import android.content.SharedPreferences import android.inputmethodservice.InputMethodService -import android.text.InputType import android.text.InputType.* import android.text.TextUtils import android.view.KeyEvent @@ -18,8 +17,7 @@ import com.simplemobiletools.keyboard.extensions.config import com.simplemobiletools.keyboard.extensions.safeStorageContext import com.simplemobiletools.keyboard.helpers.* import com.simplemobiletools.keyboard.views.MyKeyboardView -import kotlinx.android.synthetic.main.keyboard_view_keyboard.view.keyboard_holder -import kotlinx.android.synthetic.main.keyboard_view_keyboard.view.keyboard_view +import kotlinx.android.synthetic.main.keyboard_view_keyboard.view.* // based on https://www.androidauthority.com/lets-build-custom-keyboard-android-832362/ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionListener, SharedPreferences.OnSharedPreferenceChangeListener { @@ -34,8 +32,8 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL private var keyboardView: MyKeyboardView? = null private var lastShiftPressTS = 0L private var keyboardMode = KEYBOARD_LETTERS - private var inputTypeClass = InputType.TYPE_CLASS_TEXT - private var inputTypeClassVariation = InputType.TYPE_CLASS_TEXT + private var inputTypeClass = TYPE_CLASS_TEXT + private var inputTypeClassVariation = TYPE_CLASS_TEXT private var enterKeyType = IME_ACTION_NONE private var switchToLetters = false @@ -63,7 +61,7 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) { super.onStartInput(attribute, restarting) inputTypeClass = attribute!!.inputType and TYPE_MASK_CLASS - inputTypeClassVariation = attribute!!.inputType and TYPE_MASK_VARIATION + inputTypeClassVariation = attribute.inputType and TYPE_MASK_VARIATION enterKeyType = attribute.imeOptions and (IME_MASK_ACTION or IME_FLAG_NO_ENTER_ACTION) keyboard = createNewKeyboard() keyboardView?.setKeyboard(keyboard!!) @@ -72,47 +70,17 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL } private fun updateShiftKeyState(code: Int?) { - if (keyboardMode != KEYBOARD_LETTERS || ShiftState.isInputTypeAllowedCapitalizing(inputTypeClassVariation)) { + if (code == MyKeyboard.KEYCODE_SHIFT) { return } - if (code == MyKeyboard.KEYCODE_SHIFT || code == MyKeyboard.KEYCODE_DELETE) { - return - } - - val text = currentInputConnection.getTextBeforeCursor(2, 0) ?: return - // capitalize first letter on startup or if text is empty - if (code == null || text.isEmpty()) { - keyboard!!.setShifted(ShiftState.ON_ONE_CHAR) - keyboardView?.invalidateAllKeys() - return - } - - // capitalize sentences if needed - if (config.enableSentencesCapitalization) { - - // capitalize on Enter click - if (code == MyKeyboard.KEYCODE_ENTER) { - keyboard!!.setShifted(ShiftState.ON_ONE_CHAR) + val editorInfo = currentInputEditorInfo + if (config.enableSentencesCapitalization && editorInfo != null && editorInfo.inputType != TYPE_NULL) { + if (currentInputConnection.getCursorCapsMode(editorInfo.inputType) != 0) { + keyboard?.setShifted(ShiftState.ON_ONE_CHAR) keyboardView?.invalidateAllKeys() return } - - - if (ShiftState.shouldCapitalize(this, text.toString())) { - keyboard!!.setShifted(ShiftState.ON_ONE_CHAR) - keyboardView?.invalidateAllKeys() - return - } else { - // try capitalizing based on the editor info like google keep or google messenger apps - if (currentInputEditorInfo != null && currentInputEditorInfo.inputType != InputType.TYPE_NULL) { - if (currentInputConnection.getCursorCapsMode(currentInputEditorInfo.inputType) != 0) { - keyboard?.setShifted(ShiftState.ON_ONE_CHAR) - keyboardView?.invalidateAllKeys() - return - } - } - } } keyboard?.setShifted(ShiftState.OFF) @@ -131,25 +99,14 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL when (code) { MyKeyboard.KEYCODE_DELETE -> { - val selectedText = inputConnection.getSelectedText(0) if (TextUtils.isEmpty(selectedText)) { - val text = inputConnection.getTextBeforeCursor(3, 0)?.dropLast(1) - - if (keyboard?.mShiftState != ShiftState.ON_PERMANENT) { - keyboard?.setShifted(ShiftState.getShiftStateForText(this, inputTypeClassVariation, text?.toString())) - keyboardView?.invalidateAllKeys() - } - inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)) inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL)) } else { - - inputConnection.commitText("", 1) } } - MyKeyboard.KEYCODE_SHIFT -> { if (keyboardMode == KEYBOARD_LETTERS) { when { @@ -173,7 +130,6 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL } keyboardView!!.invalidateAllKeys() } - MyKeyboard.KEYCODE_ENTER -> { val imeOptionsActionId = getImeOptionsActionId() if (imeOptionsActionId != IME_ACTION_NONE) { @@ -183,7 +139,6 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER)) } } - MyKeyboard.KEYCODE_MODE_CHANGE -> { val keyboardXml = if (keyboardMode == KEYBOARD_LETTERS) { keyboardMode = KEYBOARD_SYMBOLS @@ -195,11 +150,9 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL keyboard = MyKeyboard(this, keyboardXml, enterKeyType) keyboardView!!.setKeyboard(keyboard!!) } - MyKeyboard.KEYCODE_EMOJI -> { keyboardView?.openEmojiPalette() } - else -> { var codeChar = code.toChar() val originalText = inputConnection.getExtractedText(ExtractedTextRequest(), 0)?.text ?: return @@ -211,7 +164,7 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL // If the keyboard is set to symbols and the user presses space, we usually should switch back to the letters keyboard. // However, avoid doing that in cases when the EditText for example requires numbers as the input. // We can detect that by the text not changing on pressing Space. - if (keyboardMode != KEYBOARD_LETTERS && code == MyKeyboard.KEYCODE_SPACE) { + if (keyboardMode != KEYBOARD_LETTERS && inputTypeClass == TYPE_CLASS_TEXT && code == MyKeyboard.KEYCODE_SPACE) { inputConnection.commitText(codeChar.toString(), 1) val newText = inputConnection.getExtractedText(ExtractedTextRequest(), 0)?.text if (originalText != newText) { @@ -222,6 +175,7 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL } } } + if (keyboard!!.mShiftState != ShiftState.ON_PERMANENT) { updateShiftKeyState(code) } @@ -232,14 +186,10 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL // TODO: Change keyboardMode to enum class keyboardMode = KEYBOARD_LETTERS - //Check if capitalization is needed after switching to letters layout - val text = currentInputConnection?.getTextBeforeCursor(2, 0) - val newShiftState = ShiftState.getShiftStateForText(this, inputTypeClassVariation, text?.toString()) - - keyboard = MyKeyboard(this, getKeyboardLayoutXML(), enterKeyType, shiftState = newShiftState) + keyboard = MyKeyboard(this, getKeyboardLayoutXML(), enterKeyType) val editorInfo = currentInputEditorInfo - if (editorInfo != null && editorInfo.inputType != InputType.TYPE_NULL && keyboard?.mShiftState != ShiftState.ON_PERMANENT) { + if (editorInfo != null && editorInfo.inputType != TYPE_NULL && keyboard?.mShiftState != ShiftState.ON_PERMANENT) { if (currentInputConnection.getCursorCapsMode(editorInfo.inputType) != 0) { keyboard?.setShifted(ShiftState.ON_ONE_CHAR) } @@ -274,24 +224,23 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL keyboardMode = KEYBOARD_NUMBERS R.xml.keys_numbers } - TYPE_CLASS_PHONE -> { keyboardMode = KEYBOARD_PHONE R.xml.keys_phone } - TYPE_CLASS_DATETIME -> { keyboardMode = KEYBOARD_SYMBOLS R.xml.keys_symbols } - else -> { keyboardMode = KEYBOARD_LETTERS getKeyboardLayoutXML() } } return MyKeyboard( - context = this, xmlLayoutResId = keyboardXml, enterKeyType = enterKeyType, shiftState = ShiftState.getDefaultShiftState(this, inputTypeClassVariation) + context = this, + xmlLayoutResId = keyboardXml, + enterKeyType = enterKeyType, ) }