fix(useTextToSpeechBrowser): handle undefined window.speechSynthesis on some android devices

This commit is contained in:
Danny Avila 2024-08-16 02:49:59 -04:00
parent dba704079c
commit 16e1f74a6c
No known key found for this signature in database
GPG key ID: 2DD9CC89B9B50364

View file

@ -1,4 +1,4 @@
import { useRecoilState } from 'recoil';
import { useRecoilValue } from 'recoil';
import { useState, useEffect, useCallback } from 'react';
import type { VoiceOption } from '~/common';
import store from '~/store';
@ -8,13 +8,20 @@ function useTextToSpeechBrowser({
}: {
setIsSpeaking: React.Dispatch<React.SetStateAction<boolean>>;
}) {
const [cloudBrowserVoices] = useRecoilState(store.cloudBrowserVoices);
const [voiceName] = useRecoilState(store.voice);
const voiceName = useRecoilValue(store.voice);
const [voices, setVoices] = useState<VoiceOption[]>([]);
const cloudBrowserVoices = useRecoilValue(store.cloudBrowserVoices);
const [isSpeechSynthesisSupported, setIsSpeechSynthesisSupported] = useState(true);
const updateVoices = useCallback(() => {
const synth = window.speechSynthesis as SpeechSynthesis | undefined;
if (!synth) {
setIsSpeechSynthesisSupported(false);
return;
}
try {
const availableVoices = window.speechSynthesis.getVoices();
const availableVoices = synth.getVoices();
if (!Array.isArray(availableVoices)) {
console.error('getVoices() did not return an array');
return;
@ -31,11 +38,16 @@ function useTextToSpeechBrowser({
setVoices(voiceOptions);
} catch (error) {
console.error('Error updating voices:', error);
setIsSpeechSynthesisSupported(false);
}
}, [cloudBrowserVoices]);
useEffect(() => {
const synth = window.speechSynthesis;
const synth = window.speechSynthesis as SpeechSynthesis | undefined;
if (!synth) {
setIsSpeechSynthesisSupported(false);
return;
}
try {
if (synth.getVoices().length) {
@ -45,14 +57,22 @@ function useTextToSpeechBrowser({
}
} catch (error) {
console.error('Error in useEffect:', error);
setIsSpeechSynthesisSupported(false);
}
return () => {
synth.onvoiceschanged = null;
if (synth.onvoiceschanged) {
synth.onvoiceschanged = null;
}
};
}, [updateVoices]);
const generateSpeechLocal = (text: string) => {
if (!isSpeechSynthesisSupported) {
console.warn('Speech synthesis is not supported');
return;
}
const synth = window.speechSynthesis;
const voice = voices.find((v) => v.value === voiceName);
@ -81,6 +101,10 @@ function useTextToSpeechBrowser({
};
const cancelSpeechLocal = () => {
if (!isSpeechSynthesisSupported) {
return;
}
try {
window.speechSynthesis.cancel();
} catch (error) {
@ -90,7 +114,7 @@ function useTextToSpeechBrowser({
}
};
return { generateSpeechLocal, cancelSpeechLocal, voices };
return { generateSpeechLocal, cancelSpeechLocal, voices, isSpeechSynthesisSupported };
}
export default useTextToSpeechBrowser;