diff --git a/java/src/org/futo/inputmethod/latin/LatinIME.kt b/java/src/org/futo/inputmethod/latin/LatinIME.kt index 03e130427..0441f34a8 100644 --- a/java/src/org/futo/inputmethod/latin/LatinIME.kt +++ b/java/src/org/futo/inputmethod/latin/LatinIME.kt @@ -65,6 +65,7 @@ import kotlinx.coroutines.runBlocking import org.futo.inputmethod.latin.common.Constants import org.futo.inputmethod.latin.uix.Action import org.futo.inputmethod.latin.uix.ActionBar +import org.futo.inputmethod.latin.uix.ActionInputTransaction import org.futo.inputmethod.latin.uix.ActionWindow import org.futo.inputmethod.latin.uix.BasicThemeProvider import org.futo.inputmethod.latin.uix.DynamicThemeProvider @@ -235,6 +236,9 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save } private fun onActionActivated(action: Action) { + // Finish what we are typing so far + latinIMELegacy.onFinishInputViewInternal(false) + if (action.windowImpl != null) { enterActionWindowView(action) } else if (action.simplePressImpl != null) { @@ -589,12 +593,46 @@ class LatinIME : InputMethodService(), LifecycleOwner, ViewModelStoreOwner, Save setContent() } - override fun typePartialText(v: String) { - latinIMELegacy.mInputLogic.mConnection.setComposingText(v, 1) + private class LatinIMEActionInputTransaction( + private val latinIME: LatinIME, + shouldApplySpace: Boolean + ): ActionInputTransaction { + private val isSpaceNecessary: Boolean + init { + val priorText = latinIME.latinIMELegacy.mInputLogic.mConnection.getTextBeforeCursor(1, 0) + isSpaceNecessary = shouldApplySpace && !priorText.isNullOrEmpty() && !priorText.last().isWhitespace() + } + + private fun transformText(text: String): String { + return if(isSpaceNecessary) { " $text" } else { text } + } + + override fun updatePartial(text: String) { + latinIME.latinIMELegacy.mInputLogic.mConnection.setComposingText( + transformText(text), + 1 + ) + } + + override fun commit(text: String) { + latinIME.latinIMELegacy.mInputLogic.mConnection.commitText( + transformText(text), + 1 + ) + } + + override fun cancel() { + // TODO: Do we want to leave the composing text as-is, or delete it? + latinIME.latinIMELegacy.mInputLogic.mConnection.finishComposingText() + } + } + + override fun createInputTransaction(applySpaceIfNeeded: Boolean): ActionInputTransaction { + return LatinIMEActionInputTransaction(this, applySpaceIfNeeded) } override fun typeText(v: String) { - latinIMELegacy.onTextInput(v) + latinIMELegacy.mInputLogic.mConnection.commitText(v, 1) } override fun closeActionWindow() { diff --git a/java/src/org/futo/inputmethod/latin/uix/Action.kt b/java/src/org/futo/inputmethod/latin/uix/Action.kt index 57ce0ec30..19dfcc312 100644 --- a/java/src/org/futo/inputmethod/latin/uix/Action.kt +++ b/java/src/org/futo/inputmethod/latin/uix/Action.kt @@ -7,6 +7,11 @@ import androidx.compose.runtime.Composable import androidx.lifecycle.LifecycleCoroutineScope import org.futo.inputmethod.latin.uix.theme.ThemeOption +interface ActionInputTransaction { + fun updatePartial(text: String) + fun commit(text: String) + fun cancel() +} interface KeyboardManagerForAction { fun getContext(): Context @@ -14,7 +19,7 @@ interface KeyboardManagerForAction { fun triggerContentUpdate() - fun typePartialText(v: String) + fun createInputTransaction(applySpaceIfNeeded: Boolean): ActionInputTransaction fun typeText(v: String) diff --git a/java/src/org/futo/inputmethod/latin/uix/actions/VoiceInputAction.kt b/java/src/org/futo/inputmethod/latin/uix/actions/VoiceInputAction.kt index 1a2539c13..41b314fc6 100644 --- a/java/src/org/futo/inputmethod/latin/uix/actions/VoiceInputAction.kt +++ b/java/src/org/futo/inputmethod/latin/uix/actions/VoiceInputAction.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import org.futo.inputmethod.latin.R import org.futo.inputmethod.latin.uix.Action +import org.futo.inputmethod.latin.uix.ActionInputTransaction import org.futo.inputmethod.latin.uix.ActionWindow import org.futo.inputmethod.latin.uix.KeyboardManagerForAction import org.futo.inputmethod.latin.uix.PersistentActionState @@ -67,6 +68,15 @@ val VoiceInputAction = Action( recognizerView.start() } + private var inputTransaction: ActionInputTransaction? = null + private fun getOrStartInputTransaction(): ActionInputTransaction { + if(inputTransaction == null) { + inputTransaction = manager.createInputTransaction(true) + } + + return inputTransaction!! + } + @Composable override fun windowName(): String { return "Voice Input" @@ -96,6 +106,7 @@ val VoiceInputAction = Action( override fun cancelled() { if(!wasFinished) { state.soundPlayer.playCancelSound() + getOrStartInputTransaction().cancel() } } @@ -106,12 +117,12 @@ val VoiceInputAction = Action( override fun finished(result: String) { wasFinished = true - manager.typeText(result) + getOrStartInputTransaction().commit(result) manager.closeActionWindow() } override fun partialResult(result: String) { - manager.typePartialText(result) + getOrStartInputTransaction().updatePartial(result) } override fun requestPermission(onGranted: () -> Unit, onRejected: () -> Unit): Boolean {