Moved capitalization logic in a separate function

Added inputTypeClassVariation for controlling whether keyboard is in password mode to turn off capitalization
This commit is contained in:
merkost 2023-05-23 13:18:52 +10:00
parent de6e704453
commit aef91d8a42
2 changed files with 96 additions and 56 deletions

View file

@ -1,6 +1,7 @@
package com.simplemobiletools.keyboard.helpers package com.simplemobiletools.keyboard.helpers
import android.content.Context import android.content.Context
import android.text.InputType
import com.simplemobiletools.keyboard.extensions.config import com.simplemobiletools.keyboard.extensions.config
import com.simplemobiletools.keyboard.helpers.MyKeyboard.Companion.KEYCODE_SPACE import com.simplemobiletools.keyboard.helpers.MyKeyboard.Companion.KEYCODE_SPACE
@ -10,23 +11,25 @@ enum class ShiftState {
ON_PERMANENT; ON_PERMANENT;
companion object { companion object {
private val MIN_TEXT_LENGTH = 2
private val endOfSentenceChars: List<Char> = listOf('.', '?', '!') private val endOfSentenceChars: List<Char> = listOf('.', '?', '!')
fun getDefaultShiftState(context: Context): ShiftState { fun getDefaultShiftState(context: Context, inputTypeClassVariation: Int): ShiftState {
if (isInputTypePassword(inputTypeClassVariation)) {
return OFF
}
return when (context.config.enableSentencesCapitalization) { return when (context.config.enableSentencesCapitalization) {
true -> ON_ONE_CHAR true -> ON_ONE_CHAR
else -> OFF else -> OFF
} }
} }
fun getShiftStateForText(context: Context, newText: String?): ShiftState { fun getShiftStateForText(context: Context, inputTypeClassVariation: Int, text: String?): ShiftState {
if (!context.config.enableSentencesCapitalization) { if (isInputTypePassword(inputTypeClassVariation)) {
return OFF return OFF
} }
val twoLastSymbols = newText?.takeLast(2)
return when { return when {
shouldCapitalizeSentence(previousChar = twoLastSymbols?.getOrNull(0), currentChar = twoLastSymbols?.getOrNull(1)) -> { shouldCapitalize(context, text) -> {
ON_ONE_CHAR ON_ONE_CHAR
} }
else -> { else -> {
@ -35,24 +38,30 @@ enum class ShiftState {
} }
} }
fun getCapitalizationOnDelete(context: Context, text: CharSequence?): ShiftState { fun shouldCapitalize(context: Context, text: String?): Boolean {
//To capitalize first letter in textField
if (text.isNullOrEmpty()) {
return true
}
if (!context.config.enableSentencesCapitalization) { if (!context.config.enableSentencesCapitalization) {
return OFF
}
return if (text.isNullOrEmpty() || shouldCapitalizeSentence(currentChar = text.last(), previousChar = text.getOrNull(text.lastIndex - 1))) {
ON_ONE_CHAR
} else {
OFF
}
}
private fun shouldCapitalizeSentence(previousChar: Char?, currentChar: Char?): Boolean {
if (previousChar == null || currentChar == null) {
return false return false
} }
return currentChar.code == KEYCODE_SPACE && endOfSentenceChars.contains(previousChar) val twoLastSymbols = text.takeLast(2)
if (twoLastSymbols.length < MIN_TEXT_LENGTH) {
return false
}
return endOfSentenceChars.contains(twoLastSymbols.first()) && twoLastSymbols.last().code == KEYCODE_SPACE
}
fun isInputTypePassword(inputTypeVariation: Int): Boolean {
return inputTypeVariation == InputType.TYPE_TEXT_VARIATION_PASSWORD
|| inputTypeVariation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
|| inputTypeVariation == InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD
|| inputTypeVariation == InputType.TYPE_NUMBER_VARIATION_PASSWORD
} }
} }
} }

View file

@ -3,10 +3,7 @@ package com.simplemobiletools.keyboard.services
import android.content.SharedPreferences import android.content.SharedPreferences
import android.inputmethodservice.InputMethodService import android.inputmethodservice.InputMethodService
import android.text.InputType import android.text.InputType
import android.text.InputType.TYPE_CLASS_DATETIME import android.text.InputType.*
import android.text.InputType.TYPE_CLASS_NUMBER
import android.text.InputType.TYPE_CLASS_PHONE
import android.text.InputType.TYPE_MASK_CLASS
import android.text.TextUtils import android.text.TextUtils
import android.view.KeyEvent import android.view.KeyEvent
import android.view.View import android.view.View
@ -37,6 +34,7 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
private var lastShiftPressTS = 0L private var lastShiftPressTS = 0L
private var keyboardMode = KEYBOARD_LETTERS private var keyboardMode = KEYBOARD_LETTERS
private var inputTypeClass = InputType.TYPE_CLASS_TEXT private var inputTypeClass = InputType.TYPE_CLASS_TEXT
private var inputTypeClassVariation = InputType.TYPE_CLASS_TEXT
private var enterKeyType = IME_ACTION_NONE private var enterKeyType = IME_ACTION_NONE
private var switchToLetters = false private var switchToLetters = false
@ -64,23 +62,64 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) { override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) {
super.onStartInput(attribute, restarting) super.onStartInput(attribute, restarting)
inputTypeClass = attribute!!.inputType and TYPE_MASK_CLASS inputTypeClass = attribute!!.inputType and TYPE_MASK_CLASS
inputTypeClassVariation = attribute!!.inputType and TYPE_MASK_VARIATION
enterKeyType = attribute.imeOptions and (IME_MASK_ACTION or IME_FLAG_NO_ENTER_ACTION) enterKeyType = attribute.imeOptions and (IME_MASK_ACTION or IME_FLAG_NO_ENTER_ACTION)
keyboard = createNewKeyboard() keyboard = createNewKeyboard()
keyboardView?.setKeyboard(keyboard!!) keyboardView?.setKeyboard(keyboard!!)
keyboardView?.setEditorInfo(attribute) keyboardView?.setEditorInfo(attribute)
updateShiftKeyState() updateShiftKeyState(null)
} }
private fun updateShiftKeyState() { private fun updateShiftKeyState(code: Int?) {
if (keyboardMode == KEYBOARD_LETTERS) { if (code == MyKeyboard.KEYCODE_SHIFT || code == MyKeyboard.KEYCODE_DELETE) {
val editorInfo = currentInputEditorInfo return
if (editorInfo != null && editorInfo.inputType != InputType.TYPE_NULL && keyboard?.mShiftState != ShiftState.ON_PERMANENT) { }
if (currentInputConnection.getCursorCapsMode(editorInfo.inputType) != 0) {
keyboard?.setShifted(ShiftState.ON_ONE_CHAR) if (keyboardMode != KEYBOARD_LETTERS || ShiftState.isInputTypePassword(inputTypeClassVariation)) {
keyboardView?.invalidateAllKeys() 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)
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
val editorInfo = currentInputEditorInfo
if (editorInfo != null && editorInfo.inputType != InputType.TYPE_NULL && keyboard?.mShiftState != ShiftState.ON_PERMANENT) {
if (currentInputConnection.getCursorCapsMode(editorInfo.inputType) != 0) {
keyboard?.setShifted(ShiftState.ON_ONE_CHAR)
keyboardView?.invalidateAllKeys()
return
}
} }
} }
} }
//Else just reset shift to OFF
keyboard?.setShifted(ShiftState.OFF)
keyboardView?.invalidateAllKeys()
} }
override fun onKey(code: Int) { override fun onKey(code: Int) {
@ -96,19 +135,22 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
when (code) { when (code) {
MyKeyboard.KEYCODE_DELETE -> { MyKeyboard.KEYCODE_DELETE -> {
if (keyboard!!.mShiftState != ShiftState.ON_PERMANENT) {
val extractedText = inputConnection.getTextBeforeCursor(3, 0)?.dropLast(1)
keyboard!!.setShifted(ShiftState.getCapitalizationOnDelete(context = this, text = extractedText))
}
val selectedText = inputConnection.getSelectedText(0) val selectedText = inputConnection.getSelectedText(0)
if (TextUtils.isEmpty(selectedText)) { 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_DOWN, KeyEvent.KEYCODE_DEL))
inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL)) inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL))
} else { } else {
inputConnection.commitText("", 1) inputConnection.commitText("", 1)
} }
keyboardView!!.invalidateAllKeys()
} }
MyKeyboard.KEYCODE_SHIFT -> { MyKeyboard.KEYCODE_SHIFT -> {
@ -142,11 +184,6 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
} else { } else {
inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER)) inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER))
inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER)) inputConnection.sendKeyEvent(KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER))
if (config.enableSentencesCapitalization) {
keyboard!!.setShifted(ShiftState.ON_ONE_CHAR)
keyboardView!!.invalidateAllKeys()
}
} }
} }
@ -186,17 +223,10 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
} else { } else {
inputConnection.commitText(codeChar.toString(), 1) inputConnection.commitText(codeChar.toString(), 1)
} }
if (keyboardMode == KEYBOARD_LETTERS && keyboard!!.mShiftState != ShiftState.ON_PERMANENT) {
keyboard!!.setShifted(ShiftState.getShiftStateForText(this, newText = "$originalText$codeChar"))
keyboardView!!.invalidateAllKeys()
}
} }
} }
if (keyboard!!.mShiftState != ShiftState.ON_PERMANENT) {
if (code != MyKeyboard.KEYCODE_SHIFT && config.enableSentencesCapitalization) { updateShiftKeyState(code)
updateShiftKeyState()
} }
} }
@ -204,8 +234,10 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
if (switchToLetters) { if (switchToLetters) {
// TODO: Change keyboardMode to enum class // TODO: Change keyboardMode to enum class
keyboardMode = KEYBOARD_LETTERS keyboardMode = KEYBOARD_LETTERS
val text = currentInputConnection?.getExtractedText(ExtractedTextRequest(), 0)?.text
val newShiftState = ShiftState.getShiftStateForText(this, text?.toString().orEmpty()) //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, shiftState = newShiftState)
@ -261,9 +293,8 @@ class SimpleKeyboardIME : InputMethodService(), MyKeyboardView.OnKeyboardActionL
getKeyboardLayoutXML() getKeyboardLayoutXML()
} }
} }
return MyKeyboard( return MyKeyboard(
context = this, xmlLayoutResId = keyboardXml, enterKeyType = enterKeyType, shiftState = ShiftState.getDefaultShiftState(this) context = this, xmlLayoutResId = keyboardXml, enterKeyType = enterKeyType, shiftState = ShiftState.getDefaultShiftState(this, inputTypeClassVariation)
) )
} }