fix(语音日记): dictation 服务改 @State 防视图重建丢实例
struct View 重建时普通 let 属性会换成全新 SpeechDictationService, stop() 落在没在录音的新实例上返回空串 → 误报「没听清,再试一次」, 且真正在录音的老实例关不掉(麦克风悬挂)。改 @State 保证实例唯一; 停止时若服务仍返回空,用 @State 实时字幕兜底(用户看到什么就用什么)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -53,7 +53,10 @@ struct DiaryQuickSheet: View {
|
|||||||
@State private var voiceDeniedAlert = false
|
@State private var voiceDeniedAlert = false
|
||||||
@State private var voiceFlowTask: Task<Void, Never>?
|
@State private var voiceFlowTask: Task<Void, Never>?
|
||||||
@State private var recordingWatchdog: Task<Void, Never>?
|
@State private var recordingWatchdog: Task<Void, Never>?
|
||||||
private let dictation = SpeechDictationService()
|
/// 必须 @State:struct View 重建(键盘收起/detent 变化都会触发)时普通 let 会换成
|
||||||
|
/// 全新实例,导致 stop() 落在没在录音的新服务上返回空串(「没听清」假错误),
|
||||||
|
/// 且真正在录音的老实例关不掉、麦克风悬挂。@State 保证视图身份期内实例唯一。
|
||||||
|
@State private var dictation = SpeechDictationService()
|
||||||
|
|
||||||
private var hasContent: Bool {
|
private var hasContent: Bool {
|
||||||
!content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
!content.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
||||||
@@ -590,8 +593,13 @@ struct DiaryQuickSheet: View {
|
|||||||
guard voicePhase == .recording else { return }
|
guard voicePhase == .recording else { return }
|
||||||
recordingWatchdog?.cancel()
|
recordingWatchdog?.cancel()
|
||||||
voiceFlowTask = Task { @MainActor in
|
voiceFlowTask = Task { @MainActor in
|
||||||
let transcript = (await dictation.stop())
|
// 防御兜底:服务返回空(极端情况下实例丢失/最终结果丢失)时,
|
||||||
|
// 用 @State 里的实时字幕——那就是用户亲眼看到的已识别文字。
|
||||||
|
var transcript = (await dictation.stop())
|
||||||
.trimmingCharacters(in: .whitespacesAndNewlines)
|
.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
if transcript.isEmpty {
|
||||||
|
transcript = liveTranscript.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
|
}
|
||||||
liveTranscript = transcript
|
liveTranscript = transcript
|
||||||
guard !transcript.isEmpty else {
|
guard !transcript.isEmpty else {
|
||||||
withAnimation(.snappy(duration: 0.2)) { voicePhase = .idle }
|
withAnimation(.snappy(duration: 0.2)) { voicePhase = .idle }
|
||||||
|
|||||||
Reference in New Issue
Block a user