fixed some bugs on ios

This commit is contained in:
2026-09-13 11:35:46 +08:00
parent 1499db0ed7
commit f810cfedd4
5 changed files with 30 additions and 10 deletions

View File

@@ -318,21 +318,27 @@ final class PlayerController: ObservableObject {
} }
/// 只播放当前句子,播完自动暂停并回到句首(评测“播放原句”)。 /// 只播放当前句子,播完自动暂停并回到句首(评测“播放原句”)。
/// 必须先打上句尾标记再 seek,这样 completion 里的 forwardPlaybackEndTime
/// 会卡在当前句 endMs,而不是等 250ms 观察器才停。
func playCurrentSentenceAndStop() { func playCurrentSentenceAndStop() {
guard let sentence = currentSentence else { guard let sentence = currentSentence else {
return return
} }
performSeek(to: sentenceSeekPosition(sentence))
stopAtSentenceEnd = true stopAtSentenceEnd = true
stopAtSentenceEndIndex = sentence.index stopAtSentenceEndIndex = sentence.index
play() lastSentenceIndex = sentence.index
playbackIntent = true
performSeek(to: sentenceSeekPosition(sentence), resumePlayback: true)
} }
// MARK: - 设置 // MARK: - 设置
func setContinuousPlayback(_ enabled: Bool) { func setContinuousPlayback(_ enabled: Bool) {
config.continuousPlayback = enabled config.continuousPlayback = enabled
refreshSentenceBoundaryGuard() if !enabled {
lastSentenceIndex = currentSentence?.index ?? lastSentenceIndex
}
refreshSentenceBoundaryGuard(force: true)
} }
func setSentenceMode(_ enabled: Bool) { func setSentenceMode(_ enabled: Bool) {
@@ -783,6 +789,13 @@ final class PlayerController: ObservableObject {
tick() tick()
return return
} }
// 评测“播放原句”即使处于连续播放,也要用当前句硬边界,不能滑进下一句。
if stopAtSentenceEnd,
let index = stopAtSentenceEndIndex,
let sentence = mediaItem?.sentences.first(where: { $0.index == index }) {
applySentenceEndAction(sentence)
return
}
// 若最后一个句子的 endMs 就是视频末尾,forwardPlaybackEndTime 和自然结束 // 若最后一个句子的 endMs 就是视频末尾,forwardPlaybackEndTime 和自然结束
// 是同一时间点。此时必须执行“当前句”的句尾动作,而不能整条视频回零。 // 是同一时间点。此时必须执行“当前句”的句尾动作,而不能整条视频回零。
if config.sentenceMode, if config.sentenceMode,

View File

@@ -88,16 +88,20 @@ enum ImitationAssessor {
appendFile(&body, boundary: boundary, name: "audio", filename: filename, mimeType: mimeType, data: recordingData) appendFile(&body, boundary: boundary, name: "audio", filename: filename, mimeType: mimeType, data: recordingData)
body.append(Data("--\(boundary)--\r\n".utf8)) body.append(Data("--\(boundary)--\r\n".utf8))
var headers = [
"Accept": "application/json",
"Content-Type": "multipart/form-data; boundary=\(boundary)",
"X-Client-Key": AppConfig.assessmentAPIKey,
]
if !AppConfig.authToken.isEmpty {
headers["Authorization"] = "Bearer \(AppConfig.authToken)"
}
let result = try await HTTPClient.execute( let result = try await HTTPClient.execute(
baseURL: AppConfig.serverBaseURL, baseURL: AppConfig.serverBaseURL,
path: path, path: path,
method: "POST", method: "POST",
timeout: AppConfig.assessmentTimeout, timeout: AppConfig.assessmentTimeout,
headers: [ headers: headers,
"Accept": "application/json",
"Content-Type": "multipart/form-data; boundary=\(boundary)",
"X-Client-Key": AppConfig.assessmentAPIKey,
],
body: body body: body
) )
guard (200...299).contains(result.statusCode) else { guard (200...299).contains(result.statusCode) else {

View File

@@ -90,6 +90,9 @@ struct RootView: View {
.onChange(of: activeModule) { module in .onChange(of: activeModule) { module in
if module == .train { if module == .train {
controller.setContinuousPlayback(continuousPlayback) controller.setContinuousPlayback(continuousPlayback)
} else if module == .test {
// 与安卓测试页一致:按当前句窗口播放,避免滑进下一句。
controller.setContinuousPlayback(false)
} else { } else {
controller.setContinuousPlayback(true) controller.setContinuousPlayback(true)
} }

View File

@@ -35,7 +35,7 @@ struct TestView: View {
PlayerSectionView( PlayerSectionView(
controller: controller, controller: controller,
showsContinuousToggle: false, showsContinuousToggle: false,
continuousPlayback: .constant(true), continuousPlayback: .constant(false),
showsSubtitle: $testSubtitleVisible, showsSubtitle: $testSubtitleVisible,
onFullscreen: onFullscreen onFullscreen: onFullscreen
) )
@@ -321,7 +321,7 @@ struct TestView: View {
dubSegments[sentence.index] = audioURL dubSegments[sentence.index] = audioURL
dubRawSegments[sentence.index] = rawPersistedURL dubRawSegments[sentence.index] = rawPersistedURL
mergedDubURL = nil mergedDubURL = nil
submitAssessment(recordingURL: url) submitAssessment(recordingURL: audioURL)
} }
private func restorePlaybackAudioSession() { private func restorePlaybackAudioSession() {