Skip to content

Commit a147819

Browse files
author
Andrea Barbasso
committed
[UXP-126] fix utterance canceling itself on long texts using chrome
1 parent 6c27fd5 commit a147819

2 files changed

Lines changed: 21 additions & 13 deletions

File tree

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<div class="p-2 text-white">
22
<div class="tts-controls" *ngIf="showTTSControls">
3-
<i *ngIf="!this.utterance" class="button fa fa-volume-high" (click)="textToSpeech()"></i>
4-
<i *ngIf="this.utterance && !isPaused" class="button fa fa-pause" (click)="pauseTextToSpeech()"></i>
5-
<i *ngIf="this.utterance && isPaused" class="button fa fa-play" (click)="resumeTextToSpeech()"></i>
3+
<i *ngIf="!this.utterances.length" class="button fa fa-volume-high" (click)="textToSpeech()"></i>
4+
<i *ngIf="this.utterances.length && !isPaused" class="button fa fa-pause" (click)="pauseTextToSpeech()"></i>
5+
<i *ngIf="this.utterances.length && isPaused" class="button fa fa-play" (click)="resumeTextToSpeech()"></i>
66
</div>
77
</div>
88
<div class="tooltip-arrow">&nbsp;</div>

src/app/directives/text-select/text-selection-tooltip/text-selection-tooltip.component.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)