~repos /only-bible-app

#kotlin#android#ios

git clone https://pyrossh.dev/repos/only-bible-app.git

The only bible app you will ever need. No ads. No in-app purchases. No distractions.


c85ec835 Peter John

1 year ago
fix play/pause
app/src/main/java/dev/pyrossh/onlyBible/AppViewModel.kt CHANGED
@@ -31,6 +31,12 @@ internal val Context.dataStore by preferencesDataStore(name = "onlyBible")
31
31
  class AppViewModel(application: Application) : AndroidViewModel(application) {
32
32
  private val context
33
33
  get() = getApplication<Application>()
34
+ val speechService = SpeechSynthesizer(
35
+ SpeechConfig.fromSubscription(
36
+ BuildConfig.subscriptionKey,
37
+ "centralindia"
38
+ )
39
+ )
34
40
  var isLoading by mutableStateOf(true)
35
41
  var isOnError by mutableStateOf(false)
36
42
  var verses by mutableStateOf(listOf<Verse>())
@@ -161,41 +167,6 @@ class AppViewModel(application: Application) : AndroidViewModel(application) {
161
167
  }
162
168
  }
163
169
 
164
- val speechService = SpeechSynthesizer(
165
- SpeechConfig.fromSubscription(
166
- BuildConfig.subscriptionKey,
167
- "centralindia"
168
- )
169
- )
170
-
171
- //suspend fun <T> Future<T>.wait(timeoutMs: Int = 30000): T? {
172
- // val start = System.currentTimeMillis()
173
- // while (!isDone) {
174
- // if (System.currentTimeMillis() - start > timeoutMs)
175
- // return null
176
- // delay(500)
177
- // }
178
- // return withContext(Dispatchers.IO) {
179
- // get()
180
- // }
181
- //}
182
-
183
- fun convertVerseToSpeech(v: Verse) {
184
- speechService.SpeakSsml(
185
- """
186
- <speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
187
- <voice name="en-US-AvaMultilingualNeural">
188
- ${v.text}
189
- </voice>
190
- </speak>
191
- """.trimIndent()
192
- )
193
- }
194
-
195
- fun stopVerses(scope: CoroutineScope, verses: List<Verse>) {
196
- //TODOD
197
- }
198
-
199
170
  fun shareVerses(context: Context, verses: List<Verse>) {
200
171
  val versesThrough =
201
172
  if (verses.size >= 3) "${verses.first().verseIndex + 1}-${verses.last().verseIndex + 1}" else verses.map { it.verseIndex + 1 }
app/src/main/java/dev/pyrossh/onlyBible/ChapterScreen.kt CHANGED
@@ -40,6 +40,7 @@ import androidx.compose.material3.Text
40
40
  import androidx.compose.material3.TextButton
41
41
  import androidx.compose.material3.TopAppBar
42
42
  import androidx.compose.runtime.Composable
43
+ import androidx.compose.runtime.DisposableEffect
43
44
  import androidx.compose.runtime.getValue
44
45
  import androidx.compose.runtime.mutableFloatStateOf
45
46
  import androidx.compose.runtime.mutableStateOf
@@ -61,6 +62,7 @@ import androidx.compose.ui.text.withStyle
61
62
  import androidx.compose.ui.unit.dp
62
63
  import androidx.compose.ui.unit.sp
63
64
  import androidx.navigation.NavController
65
+ import com.microsoft.cognitiveservices.speech.SpeechSynthesisEventArgs
64
66
  import kotlinx.coroutines.Dispatchers
65
67
  import kotlinx.coroutines.Job
66
68
  import kotlinx.coroutines.launch
@@ -114,12 +116,24 @@ fun ChapterScreen(
114
116
  var isPlaying by rememberSaveable {
115
117
  mutableStateOf(false)
116
118
  }
117
- var playingJob by rememberSaveable {
118
- mutableStateOf<Job?>(null)
119
- }
120
119
  var dragAmount by remember {
121
120
  mutableFloatStateOf(0.0f)
122
121
  }
122
+ DisposableEffect(Unit) {
123
+ val started = { _: Any, _: SpeechSynthesisEventArgs ->
124
+ isPlaying = true
125
+ }
126
+ val completed = { _: Any, _: SpeechSynthesisEventArgs ->
127
+ isPlaying = false
128
+ }
129
+ model.speechService.SynthesisStarted.addEventListener(started)
130
+ model.speechService.SynthesisCompleted.addEventListener(completed)
131
+
132
+ onDispose {
133
+ model.speechService.SynthesisStarted.removeEventListener(started)
134
+ model.speechService.SynthesisCompleted.removeEventListener(completed)
135
+ }
136
+ }
123
137
  val chapterVerses =
124
138
  model.verses.filter { it.bookIndex == bookIndex && it.chapterIndex == chapterIndex }
125
139
  val headingColor = MaterialTheme.colorScheme.onSurface // MaterialTheme.colorScheme.primary,
@@ -220,20 +234,13 @@ fun ChapterScreen(
220
234
  }
221
235
  IconButton(onClick = {
222
236
  if (isPlaying) {
223
- isPlaying = false
224
- playingJob?.cancel()
237
+ model.speechService.StopSpeakingAsync()
225
238
  } else {
226
- isPlaying = true
227
- playingJob = scope.launch(Dispatchers.IO) {
239
+ scope.launch(Dispatchers.IO) {
228
240
  for (v in selectedVerses.sortedBy { it.verseIndex }) {
229
- if (playingJob?.isActive == true) {
241
+ model.speechService.StartSpeakingSsml(v.toSSML())
230
- convertVerseToSpeech(v)
231
- }
232
242
  }
233
243
  }
234
- playingJob?.invokeOnCompletion {
235
- isPlaying = false
236
- }
237
244
  }
238
245
  }) {
239
246
  Icon(
app/src/main/java/dev/pyrossh/onlyBible/Verse.kt CHANGED
@@ -80,6 +80,16 @@ data class Verse(
80
80
  val text: String,
81
81
  ) {
82
82
 
83
+ fun toSSML(): String {
84
+ return """
85
+ <speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" xml:lang="en-US">
86
+ <voice name="en-US-AvaMultilingualNeural">
87
+ ${text}
88
+ </voice>
89
+ </speak>
90
+ """.trimIndent()
91
+ }
92
+
83
93
  companion object {
84
94
  val chapterSizes = listOf(
85
95
  50,
readme.md CHANGED
@@ -3,5 +3,3 @@
3
3
  * Fix swipe calculations (look at horizontal pager)
4
4
  * Improve Paging in dark mode
5
5
  * Improve splash screen in dark mode
6
- * Fix Audio play/pause
7
- * Use toolbar for actions