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:
parent
de6e704453
commit
aef91d8a42
2 changed files with 96 additions and 56 deletions
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue