regenerate something when the sentences changed
This commit is contained in:
@@ -2,6 +2,7 @@ package cn.learningpad.oraltrainer.sample
|
||||
|
||||
import cn.learningpad.oraltrainer.sdk.OralTrainerController
|
||||
import cn.learningpad.oraltrainer.sdk.OralTrainerSdk
|
||||
import cn.learningpad.oraltrainer.sdk.SentenceBoundary
|
||||
import cn.learningpad.oraltrainer.sdk.SentenceBoundaryApiCallback
|
||||
import cn.learningpad.oraltrainer.sdk.SentenceBoundaryApiResult
|
||||
import cn.learningpad.oraltrainer.sdk.TrainingVideoSummary
|
||||
@@ -26,6 +27,7 @@ internal class CourseCatalogController(
|
||||
fun onSentencePlaceholder(meta: String, text: String)
|
||||
fun refreshPlayerUi()
|
||||
fun openTrainingModule()
|
||||
fun syncSentenceExplanations(videoHash: String, sentences: List<SentenceBoundary>)
|
||||
}
|
||||
|
||||
fun loadCatalog() {
|
||||
@@ -101,6 +103,7 @@ internal class CourseCatalogController(
|
||||
override fun onSuccess(result: SentenceBoundaryApiResult) {
|
||||
if (!screenState.isCurrentCatalogRequest(generation)) return
|
||||
screenState.courseBoundaries[result.videoHash] = result
|
||||
host.syncSentenceExplanations(result.videoHash, result.sentences)
|
||||
updateCatalogVideo(video.videoHash, result)
|
||||
if (screenState.activeItemId == result.videoHash) {
|
||||
controller.updateSentences(result.videoHash, result.sentences)
|
||||
@@ -174,6 +177,9 @@ internal class CourseCatalogController(
|
||||
host.onCatalogChanged()
|
||||
|
||||
val cachedBoundary = screenState.courseBoundaries[video.videoHash]
|
||||
if (cachedBoundary != null) {
|
||||
host.syncSentenceExplanations(cachedBoundary.videoHash, cachedBoundary.sentences)
|
||||
}
|
||||
controller.loadItem(video.toTrainingMediaItem(cachedBoundary?.sentences.orEmpty()))
|
||||
screenState.currentSentenceCount = cachedBoundary?.sentences?.size ?: video.sentenceCount
|
||||
if (cachedBoundary == null) {
|
||||
@@ -198,6 +204,7 @@ internal class CourseCatalogController(
|
||||
return
|
||||
}
|
||||
screenState.courseBoundaries[result.videoHash] = result
|
||||
host.syncSentenceExplanations(result.videoHash, result.sentences)
|
||||
updateCatalogVideo(video.videoHash, result)
|
||||
screenState.currentSentenceCount = result.sentences.size
|
||||
controller.updateSentences(video.videoHash, result.sentences)
|
||||
|
||||
@@ -480,10 +480,12 @@ class MainActivity : Activity() {
|
||||
val sentence = controller.currentSentence() ?: return
|
||||
if (sentence.text.isNullOrBlank()) return
|
||||
controller.pause()
|
||||
val item = controller.currentTrainingItem()
|
||||
explanationOverlay.show(
|
||||
sentence,
|
||||
controller.currentTrainingItem()?.title.orEmpty(),
|
||||
controller.currentTrainingItem()?.id.orEmpty(),
|
||||
item?.title.orEmpty(),
|
||||
item?.id.orEmpty(),
|
||||
item?.sentences.orEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -561,6 +563,13 @@ class MainActivity : Activity() {
|
||||
screenFactory.renderCatalog()
|
||||
refreshCurrentUi()
|
||||
}
|
||||
|
||||
override fun syncSentenceExplanations(
|
||||
videoHash: String,
|
||||
sentences: List<SentenceBoundary>,
|
||||
) {
|
||||
SentenceExplanationStore(this@MainActivity).sync(videoHash, sentences)
|
||||
}
|
||||
}
|
||||
|
||||
private fun testHost() = object : TestSessionController.Host {
|
||||
|
||||
@@ -23,7 +23,15 @@ internal class SentenceExplanationOverlay(
|
||||
private var currentRequest: CancellableExplanationRequest? = null
|
||||
private var requestGeneration = 0
|
||||
|
||||
fun show(sentence: SentenceBoundary, courseTitle: String, mediaId: String) {
|
||||
fun show(
|
||||
sentence: SentenceBoundary,
|
||||
courseTitle: String,
|
||||
mediaId: String,
|
||||
sentences: List<SentenceBoundary> = emptyList(),
|
||||
) {
|
||||
if (sentences.isNotEmpty()) {
|
||||
store.sync(mediaId, sentences)
|
||||
}
|
||||
close()
|
||||
val generation = ++requestGeneration
|
||||
val root = FrameLayout(activity).apply {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package cn.learningpad.oraltrainer.sample
|
||||
|
||||
import android.content.Context
|
||||
import cn.learningpad.oraltrainer.sdk.SentenceBoundary
|
||||
import java.io.File
|
||||
import java.util.Locale
|
||||
|
||||
@@ -23,12 +24,34 @@ internal class SentenceExplanationStore(context: Context) {
|
||||
return file.isFile && file.length() > 0L
|
||||
}
|
||||
|
||||
fun sync(mediaId: String, sentences: List<SentenceBoundary>) {
|
||||
if (sentences.isEmpty()) return
|
||||
val directoryName = sanitize(mediaId) ?: return
|
||||
val dir = File(rootDir, directoryName)
|
||||
val revision = revisionFor(sentences)
|
||||
val marker = File(dir, REVISION_FILE)
|
||||
val previous = marker.takeIf { it.isFile }?.readText()?.trim().orEmpty()
|
||||
if (previous == revision) return
|
||||
if (dir.exists()) {
|
||||
dir.deleteRecursively()
|
||||
}
|
||||
dir.mkdirs()
|
||||
marker.writeText(revision)
|
||||
}
|
||||
|
||||
private fun fileFor(mediaId: String, sentenceIndex: Int): File? {
|
||||
val directoryName = sanitize(mediaId) ?: return null
|
||||
return File(File(rootDir, directoryName), "$sentenceIndex.txt")
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val REVISION_FILE = "revision.txt"
|
||||
|
||||
fun revisionFor(sentences: List<SentenceBoundary>): String =
|
||||
sentences.joinToString("\n") { sentence ->
|
||||
"${sentence.index}\t${sentence.text.orEmpty().trim()}"
|
||||
}
|
||||
|
||||
fun sanitize(mediaId: String): String? {
|
||||
val filtered = mediaId.trim().lowercase(Locale.US)
|
||||
.replace(Regex("[^a-z0-9._-]"), "_")
|
||||
|
||||
Reference in New Issue
Block a user