refresh borders of sentences

This commit is contained in:
2026-08-30 11:57:23 +08:00
parent 7cdc637527
commit 0b85a2ed57
3 changed files with 50 additions and 3 deletions

View File

@@ -141,6 +141,28 @@ class OralTrainerController internal constructor(
loadItems(listOf(item))
}
/**
* Replaces sentences without preparing/reloading media, preserving playback
* position and state so a background boundary refresh can apply immediately.
*/
fun updateSentences(mediaId: String, sentences: List<SentenceBoundary>): Boolean {
val index = mediaItems.indexOfFirst { it.id == mediaId }
if (index < 0) {
return false
}
val updatedItem = mediaItems[index].copy(sentences = sentences)
if (mediaItems[index] == updatedItem) {
return true
}
mediaItems[index] = updatedItem
if (index == player.currentMediaItemIndex) {
listeners.forEach { it.onMediaChanged(updatedItem) }
notifySentenceIfChanged(force = true)
notifySnapshot()
}
return true
}
fun play() {
player.play()
}

View File

@@ -111,6 +111,7 @@ class SentenceBoundaryApi internal constructor(
connection.requestMethod = "GET"
connection.connectTimeout = config.connectTimeoutMs
connection.readTimeout = config.readTimeoutMs
connection.useCaches = false
connection.setRequestProperty("Accept", "application/json")
connection.setRequestProperty("User-Agent", config.userAgent)
val statusCode = connection.responseCode

View File

@@ -107,6 +107,7 @@ class MainActivity : Activity() {
private var activeItemId: String = ""
private var currentSentenceCount = 0
private var sentenceBoundaryRequestGeneration = 0
private var catalogVideos: List<TrainingVideoSummary> = emptyList()
private var catalogStatusTextValue = "正在同步"
private var activeModule = Module.TRAIN
@@ -1419,6 +1420,9 @@ class MainActivity : Activity() {
catalogStatusText.text = catalogStatusTextValue
}
renderCatalog()
catalogVideos
.firstOrNull { it.videoHash == activeItemId }
?.let { refreshSentenceBoundaries(it, background = true) }
}
override fun onError(error: Throwable) {
@@ -1460,18 +1464,38 @@ class MainActivity : Activity() {
val loadingItem = video.toTrainingMediaItem()
controller.loadItem(loadingItem)
currentSentenceCount = video.sentenceCount
refreshSentenceBoundaries(video, background = false)
}
private fun refreshSentenceBoundaries(
video: TrainingVideoSummary,
background: Boolean,
) {
val requestGeneration = ++sentenceBoundaryRequestGeneration
if (!background && ::statusText.isInitialized) {
statusText.text = "正在加载云端课程..."
} else if (::statusText.isInitialized) {
statusText.text = "正在刷新句子边界..."
}
sdk.sentenceBoundaryApi.fetch(video.videoHash, object : SentenceBoundaryApiCallback {
override fun onSuccess(result: SentenceBoundaryApiResult) {
if (activeItemId != video.videoHash) {
if (
sentenceBoundaryRequestGeneration != requestGeneration ||
activeItemId != video.videoHash
) {
return
}
currentSentenceCount = result.sentences.size
controller.loadItem(video.toTrainingMediaItem(result.sentences))
controller.updateSentences(video.videoHash, result.sentences)
refreshCurrentUi()
statusText.text = "课程已就绪:${result.sentences.size}"
}
override fun onError(error: Throwable) {
if (activeItemId != video.videoHash) {
if (
sentenceBoundaryRequestGeneration != requestGeneration ||
activeItemId != video.videoHash
) {
return
}
statusText.text = "句子边界加载失败:${error.message.orEmpty()}"