@@ -14,15 +14,16 @@ import { UseSpeechSynthesis, SpeechSynthesisSpeakParam, UseSpeechSynthesisProps
1414 * @param {SpeechSynthesisUtterance["onerror"] } [opts.onError] - function that will be executed when _error_ event is fired.
1515 * @param {SpeechSynthesisUtterance["onend"] } [opts.onEnd] - function that will be executed when _end_ event is fired.
1616 * @param {SpeechSynthesisonCancel } [opts.onCancel] - function that will be executed when _cancel_ event is fired.
17- * @param {LanguageBCP47Tags } [opts.lang] - [MDN Reference](https://developer.mozilla.org/docs/Web/API/SpeechSynthesisUtterance/lang.
17+ * @param {LanguageBCP47Tags } [opts.lang] - [MDN Reference](https://developer.mozilla.org/docs/Web/API/SpeechSynthesisUtterance/lang) .
1818 * @param {SpeechSynthesisUtterance["pitch"] } [opts.pitch] - [MDN Reference](https://developer.mozilla.org/docs/Web/API/SpeechSynthesisUtterance/pitch).
1919 * @param {SpeechSynthesisUtterance["rate"] } [opts.rate] - [MDN Reference](https://developer.mozilla.org/docs/Web/API/SpeechSynthesisUtterance/rate).
2020 * @param {SpeechSynthesisUtterance["voice"] } [opts.voice] - [MDN Reference](https://developer.mozilla.org/docs/Web/API/SpeechSynthesisUtterance/voice).
2121 * @param {SpeechSynthesisUtterance["volume"] } [opts.volume] - [MDN Reference](https://developer.mozilla.org/docs/Web/API/SpeechSynthesisUtterance/volume).
2222 * @returns {ReturnType<UseSpeechSynthesis> } return - Object with these properties:
2323 * - __state__: object with these properties:
2424 * - _isSupported_: Returns a boolean value indicating SpeechSynthesis availability.
25- * - _status_: Returns the current status of SpeechSynthesis.
25+ * - _status_: Returns the current status of SpeechSynthesis between: _ready_ _speaking_ _paused_ _error_ _end_ and _unavailable_.
26+ * - _hasPending_: Returns a boolean indicating the presence of texts to speech.
2627 * - _voices_: Returns the list of available voices.
2728 * - __speak__: Function to start speaking.
2829 * - __pause__: Function to keep in pause speaking.
@@ -35,32 +36,36 @@ export const useSpeechSynthesis = (opts?: UseSpeechSynthesisProps): ReturnType<U
3536 const synth = useRef ( window && ( window as any ) . speechSynthesis as SpeechSynthesis ) ;
3637
3738 const notifRef = useRef < ( ) => void > ( ) ;
38- const error = useRef ( false ) ;
39+ const status = useRef < ReturnType < UseSpeechSynthesis > [ "state" ] [ "status" ] > ( isSupported ? "ready" : "unavailable" ) ;
3940
4041 const onStart = useRef < ( handler ?: UseSpeechSynthesisProps [ "onStart" ] ) => SpeechSynthesisUtterance [ "onstart" ] > ( ( handler ) => {
4142 return ( evt : SpeechSynthesisEvent ) => {
42- error . current = false ;
43+ status . current = "speaking" ;
4344 notifRef . current && notifRef . current ( ) ;
4445 handler && handler . call ( evt . utterance , evt ) ;
4546 }
4647 } ) ;
4748
4849 const onPause = useRef < ( handler ?: UseSpeechSynthesisProps [ "onPause" ] ) => SpeechSynthesisUtterance [ "onpause" ] > ( ( handler ) => {
4950 return ( evt : SpeechSynthesisEvent ) => {
51+ status . current = "paused" ;
5052 notifRef . current && notifRef . current ( ) ;
5153 handler && handler . call ( evt . utterance , evt ) ;
5254 }
5355 } ) ;
5456
5557 const onResume = useRef < ( handler ?: UseSpeechSynthesisProps [ "onResume" ] ) => SpeechSynthesisUtterance [ "onresume" ] > ( ( handler ) => {
5658 return ( evt : SpeechSynthesisEvent ) => {
59+ status . current = "speaking" ;
5760 notifRef . current && notifRef . current ( ) ;
5861 handler && handler . call ( evt . utterance , evt ) ;
5962 }
6063 } ) ;
6164
6265 const onEnd = useRef < ( handler ?: UseSpeechSynthesisProps [ "onEnd" ] ) => SpeechSynthesisUtterance [ "onend" ] > ( ( handler ) => {
6366 return ( evt : SpeechSynthesisEvent ) => {
67+ status . current === "paused" && synth . current . cancel ( ) ;
68+ status . current = "end" ;
6469 notifRef . current && notifRef . current ( ) ;
6570 handler && handler . call ( evt . utterance , evt ) ;
6671 }
@@ -69,10 +74,11 @@ export const useSpeechSynthesis = (opts?: UseSpeechSynthesisProps): ReturnType<U
6974 const onError = useRef < ( handler ?: UseSpeechSynthesisProps [ "onError" ] ) => SpeechSynthesisUtterance [ "onerror" ] > ( ( handler ) => {
7075 return ( evt : SpeechSynthesisErrorEvent ) => {
7176 if ( opts ?. onCancel && [ "canceled" , "interrupted" ] . includes ( evt . error ) ) {
77+ status . current = "ready" ;
7278 const { charIndex, charLength, elapsedTime, utterance} = evt ;
7379 opts . onCancel . call ( evt . utterance , { charIndex, charLength, elapsedTime, utterance, name : "oncancel" } )
7480 } else {
75- error . current = true ;
81+ status . current = "error" ;
7682 handler && handler . call ( evt . utterance , evt ) ;
7783 }
7884 notifRef . current && notifRef . current ( ) ;
@@ -105,18 +111,18 @@ export const useSpeechSynthesis = (opts?: UseSpeechSynthesisProps): ReturnType<U
105111 ! ! onBoundaryHandler && ( utterance . onboundary = onBoundaryHandler ) ;
106112 ! ! onMarkHandler && ( utterance . onmark = onMarkHandler ) ;
107113
108- if ( synth . current . paused || rest . startImmediatly ) {
114+ if ( status . current === " paused" || rest . startImmediatly ) {
109115 synth . current . cancel ( ) ;
110116 }
111117
112- ! synth . current . speaking && opts ?. onSpeak && opts ?. onSpeak ( ) ;
118+ [ "ready" , "end" , "error" ] . includes ( status . current ) && opts ?. onSpeak && opts ?. onSpeak ( ) ;
113119
114120 synth . current . speak ( utterance ) ;
115121 } ) ;
116122
117- const pause = useRef ( ( ) => isSupported . current && synth . current . speaking && synth . current . pause ( ) ) ;
123+ const pause = useRef ( ( ) => isSupported . current && status . current === " speaking" && synth . current . pause ( ) ) ;
118124
119- const resume = useRef ( ( ) => isSupported . current && synth . current . paused && synth . current . resume ( ) ) ;
125+ const resume = useRef ( ( ) => isSupported . current && status . current === " paused" && synth . current . resume ( ) ) ;
120126
121127 const cancel = useRef ( ( ) => isSupported . current && synth . current . cancel ( ) ) ;
122128
@@ -133,19 +139,22 @@ export const useSpeechSynthesis = (opts?: UseSpeechSynthesisProps): ReturnType<U
133139 useMemo ( ( ) => {
134140 let cached :ReturnType < UseSpeechSynthesis > [ "state" ] = {
135141 isSupported : isSupported . current ,
136- status : isSupported . current ? synth . current . speaking ? "speaking" : synth . current . paused ? "paused" : error . current ? "error" : synth . current . pending ? "pending" : "end" : "unavailable" ,
142+ status : status . current ,
143+ hasPending : isSupported . current ? synth . current . pending : false ,
137144 voices : isSupported . current ? synth . current . getVoices ( ) : null ,
138145 }
139146
140147 return ( ) => {
141148 const current = {
142- status : isSupported . current ? synth . current . speaking ? "speaking" : synth . current . paused ? "paused" : error . current ? "error" : synth . current . pending ? "pending" : "end" : "unavailable" ,
149+ status : status . current ,
150+ hasPending : isSupported . current ? synth . current . pending : false ,
143151 voices : isSupported . current ? synth . current . getVoices ( ) : null ,
144152 }
145- if ( current . status !== cached . status || current . voices ?. length !== cached . voices ?. length ) {
153+ if ( current . status !== cached . status || current . hasPending !== cached . hasPending || current . voices ?. length !== cached . voices ?. length ) {
146154 cached = {
147155 isSupported : isSupported . current ,
148156 status : current . status as typeof cached [ "status" ] ,
157+ hasPending : current . hasPending ,
149158 voices : current . voices
150159 }
151160 }
0 commit comments