Skip to content

Commit

Permalink
feat: support for playing inserted text as voice (closes #414)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bnyro committed Mar 12, 2024
1 parent aae9f0a commit 3e6313c
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 25 deletions.
51 changes: 51 additions & 0 deletions app/src/main/java/com/bnyro/translate/ui/components/TTSButton.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Copyright (c) 2024 You Apps
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

package com.bnyro.translate.ui.components

import androidx.compose.animation.AnimatedVisibility
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.VolumeUp
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import com.bnyro.translate.ui.models.TranslationModel
import com.bnyro.translate.util.SpeechHelper

@Composable
fun TTSButton(
viewModel: TranslationModel,
languageCode: String,
text: String
) {
val context = LocalContext.current

AnimatedVisibility(visible = text.isNotEmpty(), label = "tts") {
if (viewModel.engine.supportsAudio) {
StyledIconButton(
imageVector = Icons.Default.VolumeUp
) {
viewModel.playAudio(languageCode, text)
}
} else if (SpeechHelper.ttsAvailable) {
StyledIconButton(
imageVector = Icons.Default.VolumeUp
) {
SpeechHelper.speak(context, text, languageCode)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -262,12 +262,12 @@ class TranslationModel : ViewModel() {
)
}

fun playAudio() {
fun playAudio(languageCode: String, text: String) {
releaseMediaPlayer()

viewModelScope.launch(Dispatchers.IO) {
audioFile = runCatching {
engine.getAudioFile(targetLanguage.code, translation.translatedText)
engine.getAudioFile(languageCode, text)
}.getOrElse { return@launch }

withContext(Dispatchers.Main) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ import androidx.compose.material.icons.filled.ArrowUpward
import androidx.compose.material.icons.filled.Clear
import androidx.compose.material.icons.filled.ContentPaste
import androidx.compose.material.icons.filled.Translate
import androidx.compose.material.icons.filled.VolumeUp
import androidx.compose.material3.Divider
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
Expand All @@ -59,20 +58,18 @@ import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.bnyro.translate.R
import com.bnyro.translate.ui.components.ButtonWithIcon
import com.bnyro.translate.ui.components.StyledIconButton
import com.bnyro.translate.ui.components.StyledTextField
import com.bnyro.translate.ui.components.TTSButton
import com.bnyro.translate.ui.models.TranslationModel
import com.bnyro.translate.util.ClipboardHelper
import com.bnyro.translate.util.Preferences
import com.bnyro.translate.util.SimTranslationComponent
import com.bnyro.translate.util.SpeechHelper
import kotlinx.coroutines.launch

@Composable
fun TranslationComponent(
viewModel: TranslationModel
) {
val context = LocalContext.current
val view = LocalView.current
val scrollState = rememberScrollState()
val coroutineScope = rememberCoroutineScope()
Expand Down Expand Up @@ -115,6 +112,17 @@ fun TranslationComponent(
.verticalScroll(scrollState)
.fillMaxSize()
) {
Box(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.CenterEnd
) {
TTSButton(
viewModel,
viewModel.sourceLanguage.code,
viewModel.insertedText
)
}

StyledTextField(
text = viewModel.insertedText,
placeholder = stringResource(R.string.enter_text)
Expand Down Expand Up @@ -144,25 +152,11 @@ fun TranslationComponent(
modifier = Modifier.fillMaxWidth(),
contentAlignment = Alignment.CenterEnd
) {
if (viewModel.translation.translatedText.isNotEmpty()) {
if (viewModel.engine.supportsAudio) {
StyledIconButton(
imageVector = Icons.Default.VolumeUp
) {
viewModel.playAudio()
}
} else if (SpeechHelper.ttsAvailable) {
StyledIconButton(
imageVector = Icons.Default.VolumeUp
) {
SpeechHelper.speak(
context,
viewModel.translation.translatedText,
viewModel.targetLanguage.code
)
}
}
}
TTSButton(
viewModel,
viewModel.targetLanguage.code,
viewModel.translation.translatedText
)
}

if (hasClip && viewModel.insertedText.isBlank()) {
Expand Down

0 comments on commit 3e6313c

Please sign in to comment.