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)) 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() { fun play() {
player.play() player.play()
} }

View File

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

View File

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