Slowly getting stable
This commit is contained in:
parent
6c59ee4d82
commit
92a4ac541c
@ -15,7 +15,7 @@ interface IME {
|
||||
current: Int? = 0
|
||||
)
|
||||
|
||||
fun onWords(words: List<Word>)
|
||||
fun onWords(words: List<Word>, capMode: Int?)
|
||||
|
||||
fun onNextWord()
|
||||
|
||||
@ -23,6 +23,8 @@ interface IME {
|
||||
|
||||
fun onWordSelected(word: Word)
|
||||
|
||||
fun onDeleteWord(word: Word)
|
||||
|
||||
fun onCommit(text: CharSequence = "", beforeCursor: Int = 0, afterCursor: Int = 0)
|
||||
|
||||
fun onCompose(text: CharSequence)
|
||||
|
@ -2,8 +2,10 @@ package net.mezimmah.wkt9
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.inputmethodservice.InputMethodService
|
||||
import android.provider.Settings
|
||||
import android.text.InputType
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import android.view.View
|
||||
@ -12,14 +14,15 @@ import android.view.inputmethod.EditorInfo
|
||||
import android.view.inputmethod.InputConnection
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.view.inputmethod.InputMethodSubtype
|
||||
import androidx.preference.PreferenceManager
|
||||
import net.mezimmah.wkt9.entity.Word
|
||||
import net.mezimmah.wkt9.inputhandler.IdleInputHandler
|
||||
import net.mezimmah.wkt9.inputhandler.InputHandler
|
||||
import net.mezimmah.wkt9.inputhandler.LetterInputHandler
|
||||
import net.mezimmah.wkt9.inputhandler.NumberInputHandler
|
||||
import net.mezimmah.wkt9.inputhandler.WordInputHandler
|
||||
import net.mezimmah.wkt9.inputmode.InputModeManager
|
||||
import net.mezimmah.wkt9.inputmode.InputMode
|
||||
import net.mezimmah.wkt9.inputmode.InputModeManager
|
||||
import net.mezimmah.wkt9.keypad.Event
|
||||
import net.mezimmah.wkt9.keypad.Key
|
||||
import net.mezimmah.wkt9.keypad.KeyEventStat
|
||||
@ -45,6 +48,8 @@ class WKT9IME: IME, InputMethodService() {
|
||||
private var selectionStart: Int = 0
|
||||
private var selectionEnd: Int = 0
|
||||
|
||||
private var capMode: Int? = null
|
||||
|
||||
override fun onCandidates(candidates: ArrayList<CharSequence>, current: Int?) {
|
||||
// this.candidates?.load(candidates, current)
|
||||
}
|
||||
@ -103,6 +108,10 @@ class WKT9IME: IME, InputMethodService() {
|
||||
deleteText(beforeCursor, afterCursor)
|
||||
}
|
||||
|
||||
override fun onDeleteWord(word: Word) {
|
||||
inputHandler?.onDeleteWord(word)
|
||||
}
|
||||
|
||||
override fun onGetTextBeforeCursor(n: Int): CharSequence? {
|
||||
return this.currentInputConnection?.getTextBeforeCursor(n, 0)
|
||||
}
|
||||
@ -264,12 +273,21 @@ class WKT9IME: IME, InputMethodService() {
|
||||
else showStatusIcon(icon)
|
||||
}
|
||||
|
||||
override fun onWords(words: List<Word>) {
|
||||
override fun onWords(words: List<Word>, capMode: Int?) {
|
||||
this.capMode = capMode
|
||||
|
||||
wordsView?.words = words
|
||||
}
|
||||
|
||||
override fun onWordSelected(word: Word) {
|
||||
this.onCompose(word.word)
|
||||
val compose = when (capMode) {
|
||||
InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS -> word.word.uppercase()
|
||||
InputType.TYPE_TEXT_FLAG_CAP_WORDS,
|
||||
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES -> word.word.replaceFirstChar { it.uppercase() }
|
||||
else -> word.word
|
||||
}
|
||||
|
||||
this.onCompose(compose)
|
||||
this.inputHandler?.onWordSelected(word)
|
||||
}
|
||||
|
||||
@ -301,7 +319,15 @@ class WKT9IME: IME, InputMethodService() {
|
||||
private fun switchInputMode(mode: InputMode) {
|
||||
inputHandler = when(mode) {
|
||||
InputMode.Word -> WordInputHandler(this, this, locale)
|
||||
InputMode.Letter -> LetterInputHandler(this, this, locale)
|
||||
|
||||
InputMode.Letter -> {
|
||||
val prefs: SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
val timeout = prefs.getString(getString(R.string.compose_timeout), "700")
|
||||
val composeTimeout = timeout?.toLong() ?: 700L
|
||||
|
||||
timeout?.let { LetterInputHandler(this, this, locale, composeTimeout) }
|
||||
}
|
||||
|
||||
InputMode.Number -> NumberInputHandler(this, this)
|
||||
else -> IdleInputHandler(this, this)
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ interface WordDao {
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
suspend fun insert(vararg words: Word)
|
||||
|
||||
@Query("DELETE FROM word WHERE word = :word AND locale = :locale")
|
||||
fun delete(word: String, locale: String)
|
||||
@Query("DELETE FROM word WHERE id = :id")
|
||||
fun delete(id: Int)
|
||||
|
||||
@Query("SELECT * FROM word WHERE code LIKE :code || '%' AND locale = :locale " +
|
||||
"ORDER BY length, weight DESC LIMIT :limit")
|
||||
@ -20,4 +20,7 @@ interface WordDao {
|
||||
|
||||
@Query("UPDATE word SET weight = weight + 1 WHERE id=:id")
|
||||
suspend fun increaseWeight(id: Int)
|
||||
|
||||
@Query("SELECT * FROM word WHERE word = :word AND locale = :locale COLLATE NOCASE")
|
||||
suspend fun selectWord(word: String, locale: String): Word?
|
||||
}
|
@ -3,79 +3,73 @@ package net.mezimmah.wkt9.inputhandler
|
||||
import android.text.InputType
|
||||
import android.view.KeyEvent
|
||||
import net.mezimmah.wkt9.WKT9IME
|
||||
import net.mezimmah.wkt9.IME
|
||||
import net.mezimmah.wkt9.inputmode.InputMode
|
||||
import net.mezimmah.wkt9.inputmode.TextPositionInfo
|
||||
import net.mezimmah.wkt9.keypad.Command
|
||||
import net.mezimmah.wkt9.keypad.Key
|
||||
import net.mezimmah.wkt9.keypad.KeyEventStat
|
||||
import net.mezimmah.wkt9.keypad.KeyLayout
|
||||
import net.mezimmah.wkt9.keypad.Keypad
|
||||
import java.util.Locale
|
||||
|
||||
open class DefaultInputHandler(
|
||||
private val wkt9: IME,
|
||||
private val context: WKT9IME
|
||||
private val wkt9: WKT9IME
|
||||
) {
|
||||
protected val tag = "WKT9"
|
||||
|
||||
protected var keypad: Keypad = Keypad()
|
||||
protected var capMode: Int = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
|
||||
|
||||
protected open fun capMode(key: Key): Int? {
|
||||
val modes = listOf(
|
||||
private val capModes = listOf(
|
||||
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES,
|
||||
InputType.TYPE_TEXT_FLAG_CAP_WORDS,
|
||||
InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS,
|
||||
null
|
||||
)
|
||||
var index = modes.indexOf(capMode)
|
||||
|
||||
private var currentCapMode: Int? = null
|
||||
|
||||
protected val punctuationMarks = listOf(" ", ". ", "? ", "! ", ", ", ": ", "; ")
|
||||
|
||||
protected val tag = "WKT9"
|
||||
protected val keypad: Keypad = Keypad()
|
||||
|
||||
protected var wordStart: Boolean = true
|
||||
protected var sentenceStart: Boolean = true
|
||||
|
||||
init {
|
||||
wkt9.currentInputEditorInfo?.let {
|
||||
val inputType = it.inputType
|
||||
val typeFlags = inputType.and(InputType.TYPE_MASK_FLAGS)
|
||||
|
||||
if (typeFlags.and(InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) == InputType.TYPE_TEXT_FLAG_CAP_SENTENCES) {
|
||||
currentCapMode = InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
|
||||
} else if (typeFlags.and(InputType.TYPE_TEXT_FLAG_CAP_WORDS) == InputType.TYPE_TEXT_FLAG_CAP_WORDS) {
|
||||
currentCapMode = InputType.TYPE_TEXT_FLAG_CAP_WORDS
|
||||
} else if (typeFlags.and(InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) == InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) {
|
||||
currentCapMode = InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun effectiveCapMode(): Int? {
|
||||
return when (currentCapMode) {
|
||||
InputType.TYPE_TEXT_FLAG_CAP_WORDS -> {
|
||||
if (wordStart) InputType.TYPE_TEXT_FLAG_CAP_WORDS
|
||||
else null
|
||||
}
|
||||
|
||||
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES -> {
|
||||
if (sentenceStart) InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
|
||||
else null
|
||||
}
|
||||
|
||||
else -> currentCapMode
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun toggleCapMode(key: Key) {
|
||||
var index = capModes.indexOf(currentCapMode)
|
||||
|
||||
when (key) {
|
||||
Key.B2 -> {
|
||||
if (index == 0) index = modes.count()
|
||||
if (index == 0) index = capModes.count()
|
||||
|
||||
index--
|
||||
}
|
||||
else -> index++
|
||||
}
|
||||
|
||||
return modes[index % modes.count()]
|
||||
}
|
||||
|
||||
protected open fun finalizeWordOrSentence(stats: KeyEventStat) {
|
||||
val candidates = ArrayList<CharSequence>()
|
||||
|
||||
wkt9.onCandidates(
|
||||
candidates = candidates,
|
||||
current = stats.repeats % candidates.count()
|
||||
)
|
||||
}
|
||||
|
||||
protected open fun getTextPositionInfo(text: CharSequence): TextPositionInfo {
|
||||
val trimmed = text.trimEnd()
|
||||
val regex = "[.!?]$".toRegex()
|
||||
val startSentence = text.isEmpty() || regex.containsMatchIn(trimmed)
|
||||
val startWord = text.isEmpty() || (startSentence || trimmed.length < text.length)
|
||||
|
||||
return TextPositionInfo(
|
||||
startSentence = startSentence,
|
||||
startWord = startWord
|
||||
)
|
||||
}
|
||||
|
||||
protected fun getDefaultCapMode(typeFlags: Int): Int? {
|
||||
val modes = listOf(
|
||||
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES,
|
||||
InputType.TYPE_TEXT_FLAG_CAP_WORDS,
|
||||
InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS
|
||||
)
|
||||
|
||||
modes.forEach {
|
||||
if (typeFlags.and(it) == it) return it
|
||||
}
|
||||
|
||||
return null
|
||||
currentCapMode = capModes[index % capModes.count()]
|
||||
}
|
||||
|
||||
protected fun triggerKeyEvent(keyCode: Int) {
|
||||
|
@ -6,6 +6,7 @@ import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import net.mezimmah.wkt9.WKT9IME
|
||||
import net.mezimmah.wkt9.IME
|
||||
import net.mezimmah.wkt9.R
|
||||
import net.mezimmah.wkt9.entity.Word
|
||||
import net.mezimmah.wkt9.keypad.Command
|
||||
import net.mezimmah.wkt9.keypad.Key
|
||||
@ -15,12 +16,14 @@ import java.util.Locale
|
||||
class IdleInputHandler(
|
||||
val ime: IME,
|
||||
val wkt9: WKT9IME,
|
||||
) : DefaultInputHandler(ime, wkt9), InputHandler {
|
||||
) : DefaultInputHandler(wkt9), InputHandler {
|
||||
init {
|
||||
wkt9.showStatusIcon(R.drawable.idle_input)
|
||||
}
|
||||
|
||||
override fun onFinishComposing() {}
|
||||
|
||||
override fun onLongClickCandidate(text: String) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
override fun onDeleteWord(word: Word) {}
|
||||
|
||||
override fun onRunCommand(command: Command, key: Key, event: KeyEvent, stats: KeyEventStat) {
|
||||
when (command) {
|
||||
|
@ -8,9 +8,9 @@ import net.mezimmah.wkt9.keypad.KeyEventStat
|
||||
import java.util.Locale
|
||||
|
||||
interface InputHandler {
|
||||
fun onFinishComposing()
|
||||
fun onDeleteWord(word: Word)
|
||||
|
||||
fun onLongClickCandidate(text: String)
|
||||
fun onFinishComposing()
|
||||
|
||||
fun onRunCommand(command: Command, key: Key, event: KeyEvent, stats: KeyEventStat)
|
||||
|
||||
|
@ -30,23 +30,22 @@ class LetterInputHandler(
|
||||
val ime: IME,
|
||||
private var wkt9: WKT9IME,
|
||||
private var locale: Locale,
|
||||
): SpellCheckerSession.SpellCheckerSessionListener, DefaultInputHandler(ime, wkt9), InputHandler {
|
||||
private var composeTimeout: Long
|
||||
): SpellCheckerSession.SpellCheckerSessionListener, DefaultInputHandler(wkt9), InputHandler {
|
||||
private val db = AppDatabase.getInstance(wkt9)
|
||||
private val wordDao = db.getWordDao()
|
||||
|
||||
private val word = StringBuilder()
|
||||
|
||||
private var lastKey: Key? = null
|
||||
private var repeats: Int = 0
|
||||
private var lastComposeChar: Char? = null
|
||||
private var lastIcon: Int? = null
|
||||
|
||||
private var spellCheckerSession: SpellCheckerSession? = null
|
||||
|
||||
private var sentenceStart: Boolean = false
|
||||
private var wordStart: Boolean = false
|
||||
|
||||
private val timeoutScope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||
private var timeoutJob: Job? = null
|
||||
|
||||
private val content = StringBuilder()
|
||||
|
||||
init {
|
||||
val textServiceManager = wkt9.getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE) as TextServicesManager
|
||||
|
||||
@ -56,44 +55,67 @@ class LetterInputHandler(
|
||||
this,
|
||||
false
|
||||
)
|
||||
|
||||
updateIcon()
|
||||
}
|
||||
|
||||
override fun finalizeWordOrSentence(stats: KeyEventStat) {
|
||||
private fun finalizeWordOrSentence(stats: KeyEventStat) {
|
||||
if (word.isNotEmpty()) storeWord()
|
||||
|
||||
timeoutJob?.cancel()
|
||||
|
||||
val ends = listOf(" ", ". ", "? ", "! ", ", ", ": ", "; ")
|
||||
val index = stats.repeats % ends.count()
|
||||
val lastIndex = if (stats.repeats > 0) (stats.repeats - 1) % ends.count() else null
|
||||
val index = stats.repeats % punctuationMarks.count()
|
||||
val lastIndex = if (stats.repeats > 0) (stats.repeats - 1) % punctuationMarks.count() else null
|
||||
var beforeCursor = 0
|
||||
|
||||
if (lastIndex != null) beforeCursor += ends[lastIndex].length
|
||||
if (lastIndex != null) beforeCursor += punctuationMarks[lastIndex].length
|
||||
|
||||
wkt9.onCommit(ends[index], beforeCursor)
|
||||
wordStart = true
|
||||
sentenceStart = index in 1..3
|
||||
|
||||
wkt9.onCommit(punctuationMarks[index], beforeCursor)
|
||||
updateIcon()
|
||||
}
|
||||
|
||||
private fun storeWord() {
|
||||
val str = word.toString()
|
||||
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
|
||||
word.clear()
|
||||
|
||||
scope.launch {
|
||||
val word = Word(
|
||||
word = str,
|
||||
code = keypad.getCodeForWord(str),
|
||||
weight = 0,
|
||||
length = str.length,
|
||||
locale = locale.language
|
||||
)
|
||||
val result = wordDao.selectWord(str, locale.language)
|
||||
|
||||
if (result == null) wordDao.insert(word)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSwitchLocale(locale: Locale) {
|
||||
this.locale = locale
|
||||
}
|
||||
|
||||
override fun onGetSuggestions(results: Array<out SuggestionsInfo>?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
override fun onDeleteWord(word: Word) {}
|
||||
override fun onGetSuggestions(results: Array<out SuggestionsInfo>?) {}
|
||||
override fun onGetSentenceSuggestions(results: Array<out SentenceSuggestionsInfo>?) {}
|
||||
override fun onFinishComposing() {}
|
||||
|
||||
override fun onGetSentenceSuggestions(results: Array<out SentenceSuggestionsInfo>?) {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
override fun toggleCapMode(key: Key) {
|
||||
super.toggleCapMode(key)
|
||||
|
||||
override fun onFinishComposing() {
|
||||
}
|
||||
|
||||
override fun onLongClickCandidate(text: String) {
|
||||
TODO("Not yet implemented")
|
||||
updateIcon()
|
||||
}
|
||||
|
||||
override fun onRunCommand(command: Command, key: Key, event: KeyEvent, stats: KeyEventStat) {
|
||||
when (command) {
|
||||
Command.CAP_MODE -> capMode(key)
|
||||
Command.CHARACTER -> composeCharacter(key, stats)
|
||||
Command.CAP_MODE -> toggleCapMode(key)
|
||||
Command.CHARACTER -> composeCharacter(key)
|
||||
Command.DELETE -> delete()
|
||||
Command.INPUT_MODE -> inputMode(key)
|
||||
Command.NUMBER -> triggerOriginalKeyEvent(key)
|
||||
@ -106,35 +128,75 @@ class LetterInputHandler(
|
||||
|
||||
override fun onWordSelected(word: Word) {}
|
||||
|
||||
private fun composeCharacter(key: Key, stats: KeyEventStat) {
|
||||
if (lastKey == key) repeats++
|
||||
else {
|
||||
wkt9.onCommit()
|
||||
private fun composeCharacter(key: Key) {
|
||||
val composing = timeoutJob?.isActive ?: false
|
||||
|
||||
lastKey = key
|
||||
repeats = 0
|
||||
timeoutJob?.cancel()
|
||||
|
||||
if (lastKey == key) {
|
||||
repeats++
|
||||
|
||||
word.deleteAt(word.length - 1)
|
||||
} else {
|
||||
resetKey(key)
|
||||
|
||||
if (composing) finishComposingChar()
|
||||
}
|
||||
|
||||
val layout = KeyLayout.chars[key] ?: return
|
||||
val index = repeats % layout.count()
|
||||
val char = when(effectiveCapMode()) {
|
||||
null -> layout[index].toString()
|
||||
else -> layout[index].uppercase()
|
||||
}
|
||||
|
||||
wkt9.onCompose(layout[index].toString())
|
||||
lastComposeChar = layout[index]
|
||||
|
||||
word.append(char)
|
||||
wkt9.onCompose(char)
|
||||
setComposeTimeout()
|
||||
}
|
||||
|
||||
private fun setComposeTimeout() {
|
||||
timeoutJob?.cancel()
|
||||
|
||||
timeoutJob = timeoutScope.launch {
|
||||
delay(400L)
|
||||
wkt9.onCommit("")
|
||||
|
||||
lastKey = null
|
||||
private fun resetKey(key: Key? = null) {
|
||||
lastKey = key
|
||||
repeats = 0
|
||||
}
|
||||
|
||||
private fun finishComposingChar() {
|
||||
val wordDelimiters = listOf(' ', ',', ':', ';')
|
||||
val sentenceDelimiters = listOf('.', '?', '!')
|
||||
|
||||
wkt9.onCommit()
|
||||
|
||||
if (sentenceDelimiters.contains(lastComposeChar)) {
|
||||
sentenceStart = true
|
||||
wordStart = true
|
||||
} else if (wordDelimiters.contains(lastComposeChar)) {
|
||||
sentenceStart = false
|
||||
wordStart = true
|
||||
} else {
|
||||
wordStart = false
|
||||
sentenceStart = false
|
||||
}
|
||||
|
||||
updateIcon()
|
||||
}
|
||||
|
||||
private fun setComposeTimeout() {
|
||||
val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||
|
||||
timeoutJob = scope.launch {
|
||||
delay(composeTimeout)
|
||||
resetKey()
|
||||
finishComposingChar()
|
||||
}
|
||||
}
|
||||
|
||||
private fun delete() {
|
||||
if (word.isNotEmpty()) word.deleteAt(word.length - 1)
|
||||
|
||||
resetKey()
|
||||
|
||||
if (timeoutJob?.isActive == true) {
|
||||
timeoutJob?.cancel()
|
||||
wkt9.onCompose("")
|
||||
@ -149,14 +211,18 @@ class LetterInputHandler(
|
||||
}
|
||||
|
||||
private fun updateIcon() {
|
||||
val icon = when (capMode) {
|
||||
val icon = when (effectiveCapMode()) {
|
||||
InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS -> R.drawable.letter_upper
|
||||
InputType.TYPE_TEXT_FLAG_CAP_WORDS,
|
||||
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES -> if (wordStart) R.drawable.letter_cap else R.drawable.letter_lower
|
||||
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES -> R.drawable.letter_cap
|
||||
else -> R.drawable.letter_lower
|
||||
}
|
||||
|
||||
// wkt9.onUpdateStatusIcon(icon)
|
||||
if (icon == lastIcon) return
|
||||
|
||||
wkt9.onUpdateStatusIcon(icon)
|
||||
|
||||
lastIcon = icon
|
||||
}
|
||||
}
|
||||
//
|
||||
|
@ -4,6 +4,7 @@ import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import net.mezimmah.wkt9.WKT9IME
|
||||
import net.mezimmah.wkt9.IME
|
||||
import net.mezimmah.wkt9.R
|
||||
import net.mezimmah.wkt9.entity.Word
|
||||
import net.mezimmah.wkt9.inputmode.InputMode
|
||||
import net.mezimmah.wkt9.keypad.Command
|
||||
@ -17,9 +18,13 @@ class NumberInputHandler(
|
||||
) : InputHandler {
|
||||
private val tag = "WKT9"
|
||||
|
||||
init {
|
||||
wkt9.showStatusIcon(R.drawable.number_input)
|
||||
}
|
||||
|
||||
// We don't need to implement methods below
|
||||
override fun onFinishComposing() {}
|
||||
override fun onLongClickCandidate(text: String) {}
|
||||
override fun onDeleteWord(word: Word) {}
|
||||
override fun onSwitchLocale(locale: Locale) {}
|
||||
override fun onWordSelected(word: Word) {}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.mezimmah.wkt9.inputhandler
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.text.InputType
|
||||
import android.util.Log
|
||||
import android.view.KeyEvent
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@ -23,7 +24,7 @@ class WordInputHandler(
|
||||
val ime: IME,
|
||||
private var wkt9: WKT9IME,
|
||||
private var locale: Locale,
|
||||
) : DefaultInputHandler(ime, wkt9), InputHandler {
|
||||
) : DefaultInputHandler(wkt9), InputHandler {
|
||||
private val codeword = StringBuilder()
|
||||
private var staleCodeword = false
|
||||
private var lastSelectedWord: Word? = null
|
||||
@ -35,11 +36,17 @@ class WordInputHandler(
|
||||
private val ioScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
private var queryJob: Job? = null
|
||||
|
||||
override fun capMode(key: Key): Int? {
|
||||
return super.capMode(key)
|
||||
init {
|
||||
updateIcon()
|
||||
}
|
||||
|
||||
override fun finalizeWordOrSentence(stats: KeyEventStat) {
|
||||
override fun toggleCapMode(key: Key) {
|
||||
super.toggleCapMode(key)
|
||||
|
||||
updateIcon()
|
||||
}
|
||||
|
||||
private fun finalizeWordOrSentence(stats: KeyEventStat) {
|
||||
val ends = listOf(" ", ". ", "? ", "! ", ", ", ": ", "; ")
|
||||
val index = stats.repeats % ends.count()
|
||||
val lastIndex = if (stats.repeats > 0) (stats.repeats - 1) % ends.count() else null
|
||||
@ -48,10 +55,24 @@ class WordInputHandler(
|
||||
if (lastIndex != null) beforeCursor += ends[lastIndex].length
|
||||
|
||||
wkt9.onCommit(ends[index], beforeCursor)
|
||||
|
||||
sentenceStart = index in 1..3
|
||||
|
||||
updateIcon()
|
||||
}
|
||||
|
||||
override fun onDeleteWord(word: Word) {
|
||||
ioScope.launch {
|
||||
wordDao.delete(word.id)
|
||||
|
||||
handleCodewordChange(codeword)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onSwitchLocale(locale: Locale) {
|
||||
this.locale = locale
|
||||
|
||||
updateIcon()
|
||||
}
|
||||
|
||||
override fun onFinishComposing() {
|
||||
@ -63,17 +84,9 @@ class WordInputHandler(
|
||||
lastSelectedWord = null
|
||||
}
|
||||
|
||||
override fun onLongClickCandidate(text: String) {
|
||||
ioScope.launch {
|
||||
wordDao.delete(text, locale.language)
|
||||
|
||||
handleCodewordChange(codeword)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onRunCommand(command: Command, key: Key, event: KeyEvent, stats: KeyEventStat) {
|
||||
when (command) {
|
||||
// Command.CAP_MODE -> capMode(key)
|
||||
Command.CAP_MODE -> toggleCapMode(key)
|
||||
Command.CHARACTER -> buildCodeword(key)
|
||||
Command.DELETE -> delete()
|
||||
Command.ENTER -> enter(key)
|
||||
@ -109,7 +122,8 @@ class WordInputHandler(
|
||||
handleCodewordChange(codeword)
|
||||
} else if (codeword.isNotEmpty()) {
|
||||
codeword.clear()
|
||||
wkt9.onCompose("")
|
||||
wkt9.onCommit()
|
||||
wkt9.onDeleteText(1)
|
||||
} else {
|
||||
wkt9.onDeleteText(1)
|
||||
}
|
||||
@ -129,7 +143,7 @@ class WordInputHandler(
|
||||
// The codeword is stale when it does not yield any candidates in the DB
|
||||
staleCodeword = words.isEmpty()
|
||||
|
||||
if (words.isNotEmpty()) wkt9.onWords(words)
|
||||
if (words.isNotEmpty()) wkt9.onWords(words, effectiveCapMode())
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,15 +168,16 @@ class WordInputHandler(
|
||||
|
||||
@SuppressLint("DiscouragedApi")
|
||||
private fun updateIcon() {
|
||||
// val mode = when (capMode) {
|
||||
// InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS -> "upper"
|
||||
// InputType.TYPE_TEXT_FLAG_CAP_WORDS,
|
||||
// InputType.TYPE_TEXT_FLAG_CAP_SENTENCES -> if (wordStart) "cap" else "lower"
|
||||
// else -> "lower"
|
||||
// }
|
||||
// val name = "word_${locale}_${mode}".replace('-', '_').lowercase()
|
||||
// val icon = context.resources.getIdentifier(name, "drawable", context.packageName)
|
||||
val mode = when (effectiveCapMode()) {
|
||||
InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS -> "upper"
|
||||
InputType.TYPE_TEXT_FLAG_CAP_WORDS,
|
||||
InputType.TYPE_TEXT_FLAG_CAP_SENTENCES -> "cap"
|
||||
else -> "lower"
|
||||
}
|
||||
|
||||
// wkt9.onUpdateStatusIcon(icon)
|
||||
val name = "word_${locale}_${mode}".replace('-', '_').lowercase()
|
||||
val icon = wkt9.resources.getIdentifier(name, "drawable", wkt9.packageName)
|
||||
|
||||
wkt9.onUpdateStatusIcon(icon)
|
||||
}
|
||||
}
|
@ -133,8 +133,7 @@ enum class Key(
|
||||
),
|
||||
|
||||
CommandMapping(
|
||||
events = listOf(Event.keyDown),
|
||||
inputModes = listOf(InputMode.Number),
|
||||
inputModes = listOf(InputMode.Number, InputMode.Idle),
|
||||
overrideConsume = true,
|
||||
consume = null
|
||||
)
|
||||
|
@ -1,10 +1,8 @@
|
||||
package net.mezimmah.wkt9.layout
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent.getActivity
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.util.Log
|
||||
import android.view.ContextThemeWrapper
|
||||
import android.view.View
|
||||
import android.widget.HorizontalScrollView
|
||||
@ -16,7 +14,6 @@ import net.mezimmah.wkt9.WKT9IME
|
||||
import net.mezimmah.wkt9.entity.Word
|
||||
|
||||
class Words(context: Context, attributeSet: AttributeSet): HorizontalScrollView(context, attributeSet), View.OnClickListener, View.OnLongClickListener {
|
||||
private val tag = "WKT9"
|
||||
private var wkt9: WKT9IME
|
||||
private var wordCount: Int = 0
|
||||
private var current: Int = 0
|
||||
@ -94,7 +91,19 @@ class Words(context: Context, attributeSet: AttributeSet): HorizontalScrollView(
|
||||
}
|
||||
|
||||
override fun onLongClick(v: View?): Boolean {
|
||||
Log.d(tag, "We need to delete this word from the db")
|
||||
val words = this.words ?: return true
|
||||
val wordContainer = findViewById<LinearLayout>(R.id.words)
|
||||
|
||||
for (i in 0 until wordCount) {
|
||||
val child: View = wordContainer.getChildAt(i)
|
||||
|
||||
if (v != child) continue
|
||||
|
||||
wordContainer.removeView(child)
|
||||
wkt9.onDeleteWord(words[i])
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
@ -29,6 +29,6 @@
|
||||
<item>400</item>
|
||||
<item>600</item>
|
||||
<item>800</item>
|
||||
<item>900</item>
|
||||
<item>1000</item>
|
||||
</string-array>
|
||||
</resources>
|
@ -20,6 +20,12 @@
|
||||
android:languageTag="es-ES"
|
||||
android:imeSubtypeMode="keyboard" />
|
||||
|
||||
<subtype
|
||||
android:label="Spanish AR"
|
||||
android:imeSubtypeLocale="es_AR"
|
||||
android:languageTag="es-AR"
|
||||
android:imeSubtypeMode="keyboard" />
|
||||
|
||||
<subtype
|
||||
android:label="German DE"
|
||||
android:imeSubtypeLocale="de_DE"
|
||||
@ -32,4 +38,10 @@
|
||||
android:languageTag="pt-PT"
|
||||
android:imeSubtypeMode="keyboard" />
|
||||
|
||||
<subtype
|
||||
android:label="Portuguese BR"
|
||||
android:imeSubtypeLocale="pt_BR"
|
||||
android:languageTag="pt-BR"
|
||||
android:imeSubtypeMode="keyboard" />
|
||||
|
||||
</input-method>
|
||||
|
Loading…
x
Reference in New Issue
Block a user