diff --git a/app/release/app-release.apk b/app/release/app-release.apk index 4da013a..28ab16b 100644 Binary files a/app/release/app-release.apk and b/app/release/app-release.apk differ diff --git a/app/src/main/java/net/mezimmah/wkt9/IME.kt b/app/src/main/java/net/mezimmah/wkt9/IME.kt index 8bebc41..5615ff3 100644 --- a/app/src/main/java/net/mezimmah/wkt9/IME.kt +++ b/app/src/main/java/net/mezimmah/wkt9/IME.kt @@ -31,8 +31,13 @@ interface IME { fun onDeleteText(beforeCursor: Int = 0, afterCursor: Int = 0, finishComposing: Boolean = false) + fun defaultView() fun onSwitchInputHandler(inputMode: InputMode) fun onUpdateStatusIcon(icon: Int?) + + fun record() + + fun transcribe() } \ No newline at end of file diff --git a/app/src/main/java/net/mezimmah/wkt9/WKT9IME.kt b/app/src/main/java/net/mezimmah/wkt9/WKT9IME.kt index b1b15fb..df3b6df 100644 --- a/app/src/main/java/net/mezimmah/wkt9/WKT9IME.kt +++ b/app/src/main/java/net/mezimmah/wkt9/WKT9IME.kt @@ -26,8 +26,11 @@ import net.mezimmah.wkt9.inputmode.InputModeManager import net.mezimmah.wkt9.keypad.Event import net.mezimmah.wkt9.keypad.Key import net.mezimmah.wkt9.keypad.KeyEventStat -import net.mezimmah.wkt9.layout.Words +import net.mezimmah.wkt9.layout.LoadingLayout +import net.mezimmah.wkt9.layout.MessageLayout +import net.mezimmah.wkt9.layout.WordsLayout import net.mezimmah.wkt9.t9.T9 +import net.mezimmah.wkt9.voice.Whisper import java.util.Locale @@ -35,11 +38,14 @@ class WKT9IME: IME, InputMethodService() { private val tag = "WKT9" private val inputModeManager = InputModeManager(this) + private val whisper: Whisper = Whisper(this) private lateinit var locale: Locale private var inputHandler: InputHandler? = null - private var wordsView: Words? = null + private var wordsLayoutView: WordsLayout? = null + private var loadingLayoutView: LoadingLayout? = null + private var messageLayoutView: MessageLayout? = null private val keyDownStats = KeyEventStat(0, 0) private val keyUpStats = KeyEventStat(0, 0) @@ -88,9 +94,11 @@ class WKT9IME: IME, InputMethodService() { @SuppressLint("InflateParams") override fun onCreateInputView(): View? { - wordsView = layoutInflater.inflate(R.layout.words, null) as Words + wordsLayoutView = layoutInflater.inflate(R.layout.words, null) as WordsLayout + loadingLayoutView = layoutInflater.inflate(R.layout.loading, null) as LoadingLayout + messageLayoutView = layoutInflater.inflate(R.layout.message, null) as MessageLayout - return wordsView + return wordsLayoutView } override fun onCurrentInputMethodSubtypeChanged(newSubtype: InputMethodSubtype?) { @@ -272,7 +280,7 @@ class WKT9IME: IME, InputMethodService() { override fun onWords(words: List, capMode: Int?) { this.capMode = capMode - wordsView?.words = words + wordsLayoutView?.words = words } override fun onWordSelected(word: Word) { @@ -288,11 +296,11 @@ class WKT9IME: IME, InputMethodService() { } override fun onNextWord() { - wordsView?.next() + wordsLayoutView?.next() } override fun onPreviousWord() { - wordsView?.previous() + wordsLayoutView?.previous() } private fun deleteText(beforeCursor: Int, afterCursor: Int) { @@ -301,8 +309,22 @@ class WKT9IME: IME, InputMethodService() { } } + override fun record() { + setInputView(messageLayoutView) + whisper.record() + } + + override fun transcribe() { + setInputView(loadingLayoutView) + whisper.transcribe() + } + + override fun defaultView() { + setInputView(wordsLayoutView) + } + private fun finishComposing() { - wordsView?.clear() + wordsLayoutView?.clear() inputHandler?.onFinishComposing() } diff --git a/app/src/main/java/net/mezimmah/wkt9/inputhandler/WordInputHandler.kt b/app/src/main/java/net/mezimmah/wkt9/inputhandler/WordInputHandler.kt index d6a5c24..ada4551 100644 --- a/app/src/main/java/net/mezimmah/wkt9/inputhandler/WordInputHandler.kt +++ b/app/src/main/java/net/mezimmah/wkt9/inputhandler/WordInputHandler.kt @@ -94,11 +94,26 @@ class WordInputHandler( Command.INPUT_MODE -> inputMode(key) Command.MOVE_CURSOR -> moveCursor(key) Command.NUMBER -> triggerOriginalKeyEvent(key) + Command.RECORD -> record() Command.SPACE -> finalizeWordOrSentence(stats) + Command.TRANSCRIBE -> transcribe() else -> Log.d(tag, "Command not implemented: $command") } } + private fun record() { + if (codeword.isNotEmpty()) { + wkt9.onCommit() + codeword.clear() + } + + wkt9.record() + } + + private fun transcribe() { + wkt9.transcribe() + } + override fun onWordSelected(word: Word) { lastSelectedWord = word } diff --git a/app/src/main/java/net/mezimmah/wkt9/layout/LoadingLayout.kt b/app/src/main/java/net/mezimmah/wkt9/layout/LoadingLayout.kt new file mode 100644 index 0000000..6eda4b8 --- /dev/null +++ b/app/src/main/java/net/mezimmah/wkt9/layout/LoadingLayout.kt @@ -0,0 +1,9 @@ +package net.mezimmah.wkt9.layout + +import android.content.Context +import android.util.AttributeSet +import android.widget.LinearLayout + +class LoadingLayout(context: Context, attributeSet: AttributeSet): LinearLayout(context, attributeSet) { + +} \ No newline at end of file diff --git a/app/src/main/java/net/mezimmah/wkt9/layout/MessageLayout.kt b/app/src/main/java/net/mezimmah/wkt9/layout/MessageLayout.kt new file mode 100644 index 0000000..0e690ff --- /dev/null +++ b/app/src/main/java/net/mezimmah/wkt9/layout/MessageLayout.kt @@ -0,0 +1,9 @@ +package net.mezimmah.wkt9.layout + +import android.content.Context +import android.util.AttributeSet +import android.widget.LinearLayout + +class MessageLayout(context: Context, attributeSet: AttributeSet): LinearLayout(context, attributeSet) { + +} \ No newline at end of file diff --git a/app/src/main/java/net/mezimmah/wkt9/layout/Words.kt b/app/src/main/java/net/mezimmah/wkt9/layout/WordsLayout.kt similarity index 95% rename from app/src/main/java/net/mezimmah/wkt9/layout/Words.kt rename to app/src/main/java/net/mezimmah/wkt9/layout/WordsLayout.kt index 876eee0..d964e16 100644 --- a/app/src/main/java/net/mezimmah/wkt9/layout/Words.kt +++ b/app/src/main/java/net/mezimmah/wkt9/layout/WordsLayout.kt @@ -13,7 +13,7 @@ import net.mezimmah.wkt9.R import net.mezimmah.wkt9.WKT9IME import net.mezimmah.wkt9.entity.Word -class Words(context: Context, attributeSet: AttributeSet): HorizontalScrollView(context, attributeSet), View.OnClickListener, View.OnLongClickListener { +class WordsLayout(context: Context, attributeSet: AttributeSet): HorizontalScrollView(context, attributeSet), View.OnClickListener, View.OnLongClickListener { private var wkt9: WKT9IME private var wordCount: Int = 0 private var current: Int = 0 diff --git a/app/src/main/java/net/mezimmah/wkt9/voice/Whisper.kt b/app/src/main/java/net/mezimmah/wkt9/voice/Whisper.kt index 7ab105a..b81027e 100644 --- a/app/src/main/java/net/mezimmah/wkt9/voice/Whisper.kt +++ b/app/src/main/java/net/mezimmah/wkt9/voice/Whisper.kt @@ -2,17 +2,12 @@ package net.mezimmah.wkt9.voice import android.media.MediaRecorder import android.util.Log -import android.view.View -import android.widget.HorizontalScrollView -import android.widget.LinearLayout import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch -import net.mezimmah.wkt9.R import net.mezimmah.wkt9.WKT9IME -import net.mezimmah.wkt9.inputhandler.InputHandler import okhttp3.MediaType.Companion.toMediaType import okhttp3.MultipartBody import okhttp3.OkHttpClient @@ -23,17 +18,11 @@ import java.io.IOException import java.util.concurrent.TimeUnit class Whisper( - private val context: WKT9IME, - private val inputHandler: InputHandler?, - private val ui: View + private val wkt9: WKT9IME, ) { private val tag = "WKT9" - private val ioScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) - private val mainScope = CoroutineScope(Dispatchers.Main + SupervisorJob()) - private var ioJob: Job? = null - private var recorder: MediaRecorder? = null private var recording: File? = null @@ -47,19 +36,18 @@ class Whisper( stopRecording() val recording = this.recording ?: return - - showTranscribing() + val ioScope = CoroutineScope(Dispatchers.IO + SupervisorJob()) ioJob?.cancel() ioJob = ioScope.launch { try { val transcription = run(recording) + val mainScope = CoroutineScope(Dispatchers.Main + SupervisorJob()) mainScope.launch { - showCandidates() + wkt9.onCommit(transcription) + wkt9.defaultView() } - -// inputHandler?.onInsertText(transcription.plus(" ")) } catch (e: IOException) { Log.d(tag, "A failure occurred in the communication with the speech-to-text server", e) } @@ -70,9 +58,7 @@ class Whisper( fun record() { if (recorder != null) stopRecording() - showMessage() - - recording = File.createTempFile("recording.3gp", null, context.cacheDir) + recording = File.createTempFile("recording.3gp", null, wkt9.cacheDir) recorder = MediaRecorder().also { it.setAudioSource(MediaRecorder.AudioSource.MIC) it.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP) @@ -88,36 +74,6 @@ class Whisper( } } - private fun showCandidates() { -// val candidatesView = ui.findViewById(R.id.suggestion_container) -// val loadingView = ui.findViewById(R.id.loading_container) -// val messageView = ui.findViewById(R.id.message_container) -// -// candidatesView.visibility = View.VISIBLE -// loadingView.visibility = View.GONE -// messageView.visibility = View.GONE - } - - private fun showMessage() { -// val candidatesView = ui.findViewById(R.id.suggestion_container) -// val loadingView = ui.findViewById(R.id.loading_container) -// val messageView = ui.findViewById(R.id.message_container) -// -// candidatesView.visibility = View.GONE -// loadingView.visibility = View.GONE -// messageView.visibility = View.VISIBLE - } - - private fun showTranscribing() { -// val candidatesView = ui.findViewById(R.id.suggestion_container) -// val loadingView = ui.findViewById(R.id.loading_container) -// val messageView = ui.findViewById(R.id.message_container) -// -// candidatesView.visibility = View.GONE -// loadingView.visibility = View.VISIBLE -// messageView.visibility = View.GONE - } - private fun stopRecording() { recorder?.run { stop() diff --git a/app/src/main/res/layout/loading.xml b/app/src/main/res/layout/loading.xml new file mode 100644 index 0000000..91da916 --- /dev/null +++ b/app/src/main/res/layout/loading.xml @@ -0,0 +1,29 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/message.xml b/app/src/main/res/layout/message.xml index cbb4f63..f6c0257 100644 --- a/app/src/main/res/layout/message.xml +++ b/app/src/main/res/layout/message.xml @@ -1,5 +1,5 @@ - - + android:src="@drawable/mic"/> + + android:text="Recording..." /> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/suggestion.xml b/app/src/main/res/layout/suggestion.xml deleted file mode 100644 index cbf5b32..0000000 --- a/app/src/main/res/layout/suggestion.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/words.xml b/app/src/main/res/layout/words.xml index 972d07f..5144e78 100644 --- a/app/src/main/res/layout/words.xml +++ b/app/src/main/res/layout/words.xml @@ -1,5 +1,5 @@ - - +