add chinese subtitles
This commit is contained in:
@@ -9,6 +9,10 @@ struct RootView: View {
|
||||
@StateObject private var historyManager = TrainingHistoryManager()
|
||||
@State private var activeModule: Module = .course
|
||||
@State private var continuousPlayback = false
|
||||
@State private var showChineseSubtitles = false
|
||||
@State private var chineseTranslationLoading = false
|
||||
@State private var chineseTranslationError = ""
|
||||
@State private var chineseTranslationTask: Task<Void, Never>?
|
||||
@State private var showImporter = false
|
||||
@State private var showFullscreenPlayer = false
|
||||
@State private var courses: [Course] = []
|
||||
@@ -53,6 +57,8 @@ struct RootView: View {
|
||||
controller: controller,
|
||||
catalogVM: catalogVM,
|
||||
continuousPlayback: $continuousPlayback,
|
||||
showChineseSubtitles: $showChineseSubtitles,
|
||||
chineseSubtitlePlaceholder: chineseSubtitlePlaceholder,
|
||||
onFullscreen: enterFullscreen
|
||||
)
|
||||
case .test:
|
||||
@@ -88,9 +94,24 @@ struct RootView: View {
|
||||
Task { await loadCourses() }
|
||||
}
|
||||
}
|
||||
.onChange(of: showChineseSubtitles) { enabled in
|
||||
if enabled {
|
||||
ensureChineseTranslations()
|
||||
} else {
|
||||
chineseTranslationTask?.cancel()
|
||||
chineseTranslationLoading = false
|
||||
}
|
||||
}
|
||||
.onChange(of: controller.currentItem?.id) { _ in
|
||||
ensureChineseTranslations()
|
||||
}
|
||||
.onChange(of: controller.currentItem?.sentences.count) { _ in
|
||||
ensureChineseTranslations()
|
||||
}
|
||||
.onChange(of: activeModule) { module in
|
||||
if module == .train {
|
||||
controller.setContinuousPlayback(continuousPlayback)
|
||||
ensureChineseTranslations()
|
||||
} else if module == .test {
|
||||
// 与安卓测试页一致:按当前句窗口播放,避免滑进下一句。
|
||||
controller.setContinuousPlayback(false)
|
||||
@@ -115,7 +136,9 @@ struct RootView: View {
|
||||
.fullScreenCover(isPresented: $showFullscreenPlayer) {
|
||||
FullscreenPlayerView(
|
||||
controller: controller,
|
||||
showsLessonTitle: activeModule != .train
|
||||
showsLessonTitle: activeModule != .train,
|
||||
showChineseSubtitles: showChineseSubtitles,
|
||||
chineseSubtitlePlaceholder: chineseSubtitlePlaceholder
|
||||
) {
|
||||
exitFullscreen()
|
||||
}
|
||||
@@ -593,4 +616,59 @@ struct RootView: View {
|
||||
AppDelegate.lockOrientation(restored)
|
||||
showFullscreenPlayer = false
|
||||
}
|
||||
|
||||
private var chineseSubtitlePlaceholder: String {
|
||||
if chineseTranslationLoading {
|
||||
return "正在翻译中文字幕…"
|
||||
}
|
||||
if !chineseTranslationError.isEmpty {
|
||||
return chineseTranslationError
|
||||
}
|
||||
return "暂无中文字幕"
|
||||
}
|
||||
|
||||
private func ensureChineseTranslations() {
|
||||
guard showChineseSubtitles, activeModule == .train else {
|
||||
return
|
||||
}
|
||||
guard let item = controller.currentItem else {
|
||||
return
|
||||
}
|
||||
let needsTranslation = item.sentences.contains {
|
||||
!($0.text ?? "").trimmingCharacters(in: .whitespacesAndNewlines).isEmpty &&
|
||||
($0.zhText ?? "").trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
||||
}
|
||||
guard needsTranslation else {
|
||||
chineseTranslationLoading = false
|
||||
chineseTranslationError = ""
|
||||
return
|
||||
}
|
||||
chineseTranslationTask?.cancel()
|
||||
chineseTranslationLoading = true
|
||||
chineseTranslationError = ""
|
||||
let mediaId = item.id
|
||||
chineseTranslationTask = Task {
|
||||
do {
|
||||
let map = try await SentenceBoundaryAPI.translateSubtitles(videoHash: mediaId)
|
||||
guard !Task.isCancelled else { return }
|
||||
await MainActor.run {
|
||||
guard controller.currentItem?.id == mediaId else { return }
|
||||
let updated = (controller.currentItem?.sentences ?? []).map { sentence in
|
||||
sentence.withZhText(map[sentence.index] ?? sentence.zhText)
|
||||
}
|
||||
controller.updateBoundaries(updated)
|
||||
chineseTranslationLoading = false
|
||||
chineseTranslationError = ""
|
||||
controller.showTransientMessage("已加载中文字幕")
|
||||
}
|
||||
} catch {
|
||||
guard !Task.isCancelled else { return }
|
||||
await MainActor.run {
|
||||
chineseTranslationLoading = false
|
||||
chineseTranslationError = "中文字幕翻译失败"
|
||||
controller.showTransientMessage("中文字幕翻译失败:\(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user