fix(frontend): 修复 speechSynthesis.cancel() 未守卫导致的页面崩溃
This commit is contained in:
@@ -131,13 +131,13 @@ export function useSpeechSynthesis(): UseSpeechSynthesisReturn {
|
||||
|
||||
// Chrome bug 规避:定期 resume 避免长时间不调用后暂停
|
||||
useEffect(() => {
|
||||
if (isSpeaking && !isPaused) {
|
||||
resumeIntervalRef.current = setInterval(() => {
|
||||
if (window.speechSynthesis.speaking && window.speechSynthesis.paused) {
|
||||
window.speechSynthesis.resume();
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
if (!isSupported || !isSpeaking || isPaused) return;
|
||||
|
||||
resumeIntervalRef.current = setInterval(() => {
|
||||
if (window.speechSynthesis.speaking && window.speechSynthesis.paused) {
|
||||
window.speechSynthesis.resume();
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
return () => {
|
||||
if (resumeIntervalRef.current) {
|
||||
@@ -145,7 +145,7 @@ export function useSpeechSynthesis(): UseSpeechSynthesisReturn {
|
||||
resumeIntervalRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [isSpeaking, isPaused]);
|
||||
}, [isSupported, isSpeaking, isPaused]);
|
||||
|
||||
/** 朗读下一段 */
|
||||
const speakNextChunk = useCallback(() => {
|
||||
@@ -221,29 +221,37 @@ export function useSpeechSynthesis(): UseSpeechSynthesisReturn {
|
||||
|
||||
/** 停止朗读 */
|
||||
const stop = useCallback(() => {
|
||||
window.speechSynthesis.cancel();
|
||||
if (!isSupported) {
|
||||
console.warn('[useSpeechSynthesis] stop: speechSynthesis not supported');
|
||||
return;
|
||||
}
|
||||
if (utteranceRef.current) {
|
||||
window.speechSynthesis.cancel();
|
||||
}
|
||||
setIsSpeaking(false);
|
||||
setIsPaused(false);
|
||||
utteranceRef.current = null;
|
||||
chunksRef.current = [];
|
||||
chunkIndexRef.current = 0;
|
||||
}, []);
|
||||
}, [isSupported]);
|
||||
|
||||
/** 暂停 */
|
||||
const pause = useCallback(() => {
|
||||
if (!isSupported) return;
|
||||
if (isSpeaking && !isPaused) {
|
||||
window.speechSynthesis.pause();
|
||||
setIsPaused(true);
|
||||
}
|
||||
}, [isSpeaking, isPaused]);
|
||||
}, [isSupported, isSpeaking, isPaused]);
|
||||
|
||||
/** 恢复 */
|
||||
const resume = useCallback(() => {
|
||||
if (!isSupported) return;
|
||||
if (isPaused) {
|
||||
window.speechSynthesis.resume();
|
||||
setIsPaused(false);
|
||||
}
|
||||
}, [isPaused]);
|
||||
}, [isSupported, isPaused]);
|
||||
|
||||
/** 设置语音 */
|
||||
const setVoice = useCallback((voice: SpeechSynthesisVoice) => {
|
||||
@@ -253,12 +261,14 @@ export function useSpeechSynthesis(): UseSpeechSynthesisReturn {
|
||||
// 组件卸载时停止
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
window.speechSynthesis.cancel();
|
||||
if (isSupported && utteranceRef.current) {
|
||||
window.speechSynthesis.cancel();
|
||||
}
|
||||
if (resumeIntervalRef.current) {
|
||||
clearInterval(resumeIntervalRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}, [isSupported]);
|
||||
|
||||
return {
|
||||
isSpeaking,
|
||||
|
||||
Reference in New Issue
Block a user