@@ -58,7 +58,7 @@ export class TextSelectionTooltipComponent implements OnInit, OnDestroy {
5858 @HostBinding ( 'class.bottom-placement' )
5959 bottomPlacement = false ;
6060
61- utterance : SpeechSynthesisUtterance ;
61+ utterances : SpeechSynthesisUtterance [ ] = [ ] ;
6262 isPaused = false ;
6363
6464 boundCheckPosition = this . checkPosition . bind ( this ) ;
@@ -98,20 +98,28 @@ export class TextSelectionTooltipComponent implements OnInit, OnDestroy {
9898 }
9999
100100 public textToSpeech ( ) : void {
101- if ( this . utterance ) {
101+ if ( this . utterances . length ) {
102102 speechSynthesis . cancel ( ) ;
103103 }
104- this . utterance = new SpeechSynthesisUtterance ( this . text ) ;
105- this . utterance . lang = this . translate . currentLang ;
106- this . utterance . onend = ( ) => {
107- this . utterance = null ;
108- this . changeDetectorRef . detectChanges ( ) ;
109- } ;
110- speechSynthesis . speak ( this . utterance ) ;
104+ // split the text in phrases (ending with . or ! or ?), include any leftover text
105+ const phrases = this . text . match ( / [ ^ . ! ? ] + [ . ! ? ] ? / g) ;
106+ this . utterances = phrases . map ( phrase => new SpeechSynthesisUtterance ( phrase ) ) ;
107+ this . utterances . forEach ( ( utterance , i ) => {
108+ utterance . lang = this . translate . currentLang ;
109+ utterance . onend = ( ) => {
110+ if ( i < this . utterances . length - 1 ) {
111+ speechSynthesis . speak ( this . utterances [ i + 1 ] ) ;
112+ } else {
113+ this . utterances = [ ] ;
114+ this . changeDetectorRef . detectChanges ( ) ;
115+ }
116+ } ;
117+ } ) ;
118+ speechSynthesis . speak ( this . utterances [ 0 ] ) ;
111119 }
112120
113121 ngOnDestroy ( ) : void {
114- if ( this . utterance ) {
122+ if ( this . utterances . length ) {
115123 speechSynthesis . cancel ( ) ;
116124 }
117125 this . _window . nativeWindow . removeEventListener ( 'scroll' , this . boundCheckPosition ) ;
0 commit comments