@dr33m/react-native-readium 5.0.0-rc.22 → 5.0.0-rc.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -42,6 +42,11 @@ abstract class BaseReaderFragment : Fragment() {
|
|
|
42
42
|
// TTS
|
|
43
43
|
private var ttsManager: TTSManager? = null
|
|
44
44
|
|
|
45
|
+
// True while the user has an active text selection.
|
|
46
|
+
// applyDecorations injects JS into the EPUB WebView; doing so while the user
|
|
47
|
+
// is dragging selection handles causes the selection to jump or reset.
|
|
48
|
+
private var isUserSelecting = false
|
|
49
|
+
|
|
45
50
|
// Track active decoration listeners to avoid duplicates
|
|
46
51
|
private val activeDecorationGroups = mutableSetOf<String>()
|
|
47
52
|
|
|
@@ -275,29 +280,33 @@ abstract class BaseReaderFragment : Fragment() {
|
|
|
275
280
|
|
|
276
281
|
private fun applyTTSDecoration(locator: Locator) {
|
|
277
282
|
if (!isNavigatorReady) return
|
|
283
|
+
if (isUserSelecting) return // skip DOM update while user drags selection handles
|
|
278
284
|
val decorableNavigator = navigator as? DecorableNavigator ?: return
|
|
279
|
-
//
|
|
280
|
-
//
|
|
281
|
-
//
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
285
|
+
// applyDecorations is suspend in Readium 3.x — must be called from a coroutine.
|
|
286
|
+
// viewLifecycleOwner.lifecycleScope dispatches to Dispatchers.Main, matching
|
|
287
|
+
// the observeWhenStarted pattern used by the Readium test app.
|
|
288
|
+
viewLifecycleOwner.lifecycleScope.launch {
|
|
289
|
+
decorableNavigator.applyDecorations(
|
|
290
|
+
listOf(
|
|
291
|
+
Decoration(
|
|
292
|
+
id = "tts",
|
|
293
|
+
locator = locator,
|
|
294
|
+
style = Decoration.Style.Highlight(
|
|
295
|
+
tint = android.graphics.Color.argb(89, 0xF2, 0xCA, 0x50) // #f2ca50 @ 35%
|
|
296
|
+
)
|
|
290
297
|
)
|
|
291
|
-
)
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
298
|
+
),
|
|
299
|
+
"tts"
|
|
300
|
+
)
|
|
301
|
+
}
|
|
295
302
|
}
|
|
296
303
|
|
|
297
304
|
private fun clearTTSDecoration() {
|
|
298
305
|
if (!isNavigatorReady) return
|
|
299
306
|
val decorableNavigator = navigator as? DecorableNavigator ?: return
|
|
300
|
-
|
|
307
|
+
viewLifecycleOwner.lifecycleScope.launch {
|
|
308
|
+
decorableNavigator.applyDecorations(emptyList(), "tts")
|
|
309
|
+
}
|
|
301
310
|
}
|
|
302
311
|
|
|
303
312
|
override fun onDestroyView() {
|
|
@@ -341,6 +350,10 @@ abstract class BaseReaderFragment : Fragment() {
|
|
|
341
350
|
val currentLocator = currentSelection?.locator
|
|
342
351
|
val currentText = currentLocator?.text?.highlight
|
|
343
352
|
|
|
353
|
+
// Keep the guard flag in sync so TTS decoration skips DOM updates
|
|
354
|
+
// while the user is dragging selection handles.
|
|
355
|
+
isUserSelecting = currentLocator != null
|
|
356
|
+
|
|
344
357
|
// Check if selection has changed
|
|
345
358
|
val hasChanged = when {
|
|
346
359
|
previousSelection == null && currentLocator == null -> false
|
|
@@ -3,7 +3,9 @@ package com.reactnativereadium.reader
|
|
|
3
3
|
import android.app.Application
|
|
4
4
|
import kotlinx.coroutines.CoroutineScope
|
|
5
5
|
import kotlinx.coroutines.Job
|
|
6
|
+
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
6
7
|
import kotlinx.coroutines.flow.launchIn
|
|
8
|
+
import kotlinx.coroutines.flow.map
|
|
7
9
|
import kotlinx.coroutines.flow.onEach
|
|
8
10
|
import kotlinx.coroutines.launch
|
|
9
11
|
import org.readium.navigator.media.common.MediaNavigator
|
|
@@ -108,8 +110,14 @@ class TTSManager(
|
|
|
108
110
|
}
|
|
109
111
|
.launchIn(this)
|
|
110
112
|
|
|
111
|
-
// Observe
|
|
112
|
-
|
|
113
|
+
// Observe utterance-level locator (sentence, not word).
|
|
114
|
+
// TtsNavigator.currentLocator returns tokenLocator ?: utteranceLocator — the
|
|
115
|
+
// word-level locator — which has incomplete CSS selectors and cannot be rendered
|
|
116
|
+
// by the EPUB decorator. utteranceLocator is the sentence-level locator and
|
|
117
|
+
// matches what the Readium test app (TtsViewModel.highlight) uses.
|
|
118
|
+
ttsNavigator.location
|
|
119
|
+
.map { it.utteranceLocator }
|
|
120
|
+
.distinctUntilChanged()
|
|
113
121
|
.onEach { locator ->
|
|
114
122
|
val text = locator.text.highlight ?: ""
|
|
115
123
|
onUtterance(locator, text)
|