This commit is contained in:
Nehemiah of Zebulun 2023-08-31 10:02:01 +02:00
parent cb250e64de
commit f805d8dcf3
4 changed files with 64 additions and 82 deletions

View File

@ -88,10 +88,9 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
private var timeout: Int? = null
private var lastComposedString: String? = null
private val commitHistory: MutableList<String> = mutableListOf()
private var trackCommits = false
// Spell checker
private var locale: Locale? = null
private lateinit var locale: Locale
private var spellCheckerSession: SpellCheckerSession? = null
// UI
@ -104,12 +103,17 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
private var recording: File? = null
override fun onCreate() {
Log.d(tag, "WKT9 is loading")
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
val inputMethodSubtype = inputMethodManager.currentInputMethodSubtype
locale = Locale.forLanguageTag(inputMethodSubtype.languageTag)
Log.d(tag, "WKT9 is loading: $locale")
db = AppDatabase.getInstance(this)
wordDao = db.getWordDao()
settingDao = db.getSettingDao()
keypad = Keypad(KeyCodeMapping(KeyCodeMapping.basic), KeyLayout.en_US)
keypad = Keypad(KeyCodeMapping(KeyCodeMapping.basic), KeyLayout.en_US, KeyLayout.numeric)
t9 = T9(this, keypad, settingDao, wordDao)
alphaInputMode = AlphaInputMode()
numericInputMode = NumericInputMode()
@ -117,7 +121,6 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
longPressTimeout = ViewConfiguration.getLongPressTimeout()
lastComposedString = null
commitHistory.clear()
trackCommits = false
t9.initializeWords(languageTag)
@ -143,7 +146,6 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
cursorPosition = 0
inputStatus = Status.CAP
spellCheckerSession = null
locale = null
}
override fun onFinishInputView(finishingInput: Boolean) {
@ -194,22 +196,26 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
}
override fun onStartInput(attribute: EditorInfo?, restarting: Boolean) {
val inputType = attribute?.inputType?.and(InputType.TYPE_MASK_CLASS) ?: 0
val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
val inputMethodSubtype = inputMethodManager.currentInputMethodSubtype
val textServiceManager = getSystemService(TEXT_SERVICES_MANAGER_SERVICE) as TextServicesManager
val inputType = attribute?.inputType
val inputClass = inputType?.and(InputType.TYPE_MASK_CLASS) ?: 0
val typeVariation = inputType?.and(InputType.TYPE_MASK_VARIATION) ?: 0
// val textServiceManager = getSystemService(TEXT_SERVICES_MANAGER_SERVICE) as TextServicesManager
cursorPosition = attribute?.initialSelEnd ?: 0
locale = Locale.forLanguageTag(inputMethodSubtype.languageTag)
spellCheckerSession = textServiceManager.newSpellCheckerSession(null, locale, this, false)
// spellCheckerSession = textServiceManager.newSpellCheckerSession(null, locale, this, false)
when (inputType) {
when (inputClass) {
InputType.TYPE_CLASS_DATETIME,
InputType.TYPE_CLASS_NUMBER,
InputType.TYPE_CLASS_PHONE -> enableInputMode(WKT9InputMode.NUMERIC)
InputType.TYPE_CLASS_TEXT ->
InputType.TYPE_CLASS_TEXT -> {
if (typeVariation == InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS) {
Log.d(tag, "Heja")
}
if (lastInputMode == WKT9InputMode.ALPHA) enableInputMode(WKT9InputMode.ALPHA)
else enableInputMode(WKT9InputMode.WORD)
}
else -> Log.d(tag, "Mode without input...")
}
@ -318,9 +324,11 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
return if (composing) {
composing = false
val lastComposed = lastComposedString
lastComposedString?.let {
commitHistory.add(it)
if (trackCommits && !lastComposed.isNullOrEmpty()) commitHistory.add(lastComposed)
lastComposedString = null
}
updateInputStatus()
@ -330,20 +338,12 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
@SuppressLint("DiscouragedApi")
private fun getIconResource(): Int {
val mode = inputMode?.mode
val language = locale?.language
val country = locale?.country
if (mode == null ||language == null || country == null) {
return resources.getIdentifier("wkt9", "drawable", packageName)
}
val mode = inputMode?.mode ?: return resources.getIdentifier("wkt9", "drawable", packageName)
val name = mode.plus("_")
.plus(language)
.plus("_")
.plus(country)
.plus(locale.toString())
.plus("_")
.plus(inputStatus.toString())
.replace('-', '_')
.lowercase()
return resources.getIdentifier(name, "drawable", packageName)
@ -375,9 +375,7 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
private fun handleKeyEventResult(res: KeyEventResult): Boolean {
if (res.finishComposing) finishComposingText()
if (res.startComposing) markComposingRegion()
trackCommits = res.trackCommits
if (res.increaseWeight) onIncreaseWeight()
if (!res.codeWord.isNullOrEmpty()) onCodeWordUpdate(res.codeWord, res.timeout)
if (!res.candidates.isNullOrEmpty()) onCandidates(res.candidates, res.timeout)
if (!res.commit.isNullOrEmpty()) onCommit(res.commit)
@ -479,6 +477,16 @@ class WKT9: InputMethodService(), SpellCheckerSession.SpellCheckerSessionListene
requestShowSelf(InputMethodManager.SHOW_IMPLICIT)
}
private fun onIncreaseWeight() {
val word = commitHistory.last()
if (word.isEmpty()) return
queryScope.launch {
wordDao.increaseWeight(word)
}
}
private fun onLeft() {
if (candidates.isEmpty()) return

View File

@ -58,7 +58,7 @@ class WordInputMode: InputMode {
override fun afterKeyDown(key: Key, composing: Boolean): KeyEventResult {
return when(keyCommandResolver.getCommand(key, after = true)) {
Command.BACK -> goBack(composing)
Command.CHARACTER -> buildCodeWord(key)
Command.CHARACTER -> buildCodeWord(key, composing)
Command.SHIFT_MODE -> shiftMode(composing)
Command.SPACE -> finalizeWordOrSentence(composing)
else -> KeyEventResult()
@ -72,7 +72,7 @@ class WordInputMode: InputMode {
}
}
private fun buildCodeWord(key: Key): KeyEventResult {
private fun buildCodeWord(key: Key, composing: Boolean): KeyEventResult {
val startComposing = codeWord.isEmpty()
val code = KeyLayout.numeric[key]
@ -80,7 +80,7 @@ class WordInputMode: InputMode {
return KeyEventResult(
codeWord = codeWord,
finishComposing = startComposing,
finishComposing = startComposing && composing,
startComposing = startComposing
)
}
@ -107,13 +107,14 @@ class WordInputMode: InputMode {
private fun finalizeWordOrSentence(composing: Boolean): KeyEventResult {
if (composing && !newKey) return navigateRight()
val finishComposing = codeWord.isNotEmpty()
val finishComposing = codeWord.isNotEmpty() && composing
codeWord.clear()
return KeyEventResult(
finishComposing = finishComposing,
startComposing = true,
increaseWeight = true,
candidates = listOf(" ", ". ", "? ", "! ", ", ", ": ", "; "),
timeout = 700
)

View File

@ -7,7 +7,7 @@ data class KeyEventResult(
val consumed: Boolean = true,
val finishComposing: Boolean = false,
val startComposing: Boolean = false,
val trackCommits: Boolean = false,
val increaseWeight: Boolean = false,
val codeWord: StringBuilder? = null,
val candidates: List<String>? = null,
val commit: String? = null,

View File

@ -6,41 +6,36 @@ import java.lang.StringBuilder
class Keypad(
private val keyCodeMapping: KeyCodeMapping,
private val letterLayout: Map<Key, List<Char>>
private val letterLayout: Map<Key, List<Char>>,
numericLayout: Map<Key, Int>
) {
private lateinit var letterKeyMap: Map<Char, Key>
private lateinit var keyIsLetterMap: Map<Key, Boolean>
private var emojiCodes = mapOf(
"❤️" to "143278",
"\uD83D\uDE18" to "15477"
)
private val tag = "WKT9"
private val letterCodeMap: MutableMap<Char, Int> = mutableMapOf()
init {
initKeyMaps(letterLayout)
Log.d(tag, "Keypad")
numericLayout.forEach { (key, code) ->
indexKeyLetters(key, code)
}
}
fun getKey(keyCode: Int): Key? {
return keyCodeMapping.key(keyCode)
private fun indexKeyLetters(key: Key, code: Int) {
letterLayout[key]?.map { letter ->
letterCodeMap[letter] = code
}
}
fun getCharacter(key: Key, idx: Int): Char {
val chars = letterLayout[key]!!
val length = chars.size
val wrappedIdx = idx % (length - 1) + 1
return chars[wrappedIdx]
}
fun getDigit(key: Key): Char? {
val letters = letterLayout[key] ?: return null
return if (letters.isNotEmpty() && letters[0].isDigit()) letters[0] else null
fun getKey(code: Int): Key? {
return keyCodeMapping.key(code)
}
fun getCodeForWord(word: String): String {
if (emojiCodes.keys.contains(word)) return emojiCodes[word]!!
val builder = StringBuilder()
val normalized = word.lowercase()
for (letter in word) {
for (letter in normalized) {
val code = codeForLetter(letter) ?: throw MissingLetterCode("No code found for '$letter'")
builder.append(code)
@ -49,29 +44,7 @@ class Keypad(
return builder.toString()
}
private fun codeForLetter(letter: Char): Char? {
Log.d("wkt9", "Letter key map: letterKeyMap")
return ' ' //letterKeyMap[letter]?.code
}
private fun initKeyMaps(layout: Map<Key, List<Char>>): Map<Char, Key> {
val letterKeyMap = HashMap<Char, Key>()
val keyIsLetterMap = HashMap<Key, Boolean>()
this.letterKeyMap = letterKeyMap
this.keyIsLetterMap = keyIsLetterMap
for ((key, characters) in layout) {
for (char in characters) {
letterKeyMap[char] = key
if (!KeyLayout.nonAlphaNumeric.contains(char)) {
letterKeyMap[char.uppercaseChar()] = key
keyIsLetterMap[key] = true
} else if (keyIsLetterMap[key] == null) keyIsLetterMap[key] = false
}
}
return letterKeyMap
private fun codeForLetter(letter: Char): Int? {
return letterCodeMap[letter]
}
}