diff --git a/source/client/components/CVAudioManager.ts b/source/client/components/CVAudioManager.ts index cba5096d..476943dc 100644 --- a/source/client/components/CVAudioManager.ts +++ b/source/client/components/CVAudioManager.ts @@ -75,9 +75,6 @@ export default class CVAudioManager extends Component { super.create(); this.graph.components.on(CVMeta, this.onMetaComponent, this); - - this.audioPlayer = document.createElement('audio'); - this.audioPlayer.onended = this.onEnd; } dispose() @@ -91,11 +88,13 @@ export default class CVAudioManager extends Component const { ins, outs } = this; if (ins.playNarration.changed) { - if(!this.isPlaying) { - this.play(this._narrationId); - } - else { - this.stop(); + if(this.audioPlayer) { + if(!this.isPlaying) { + this.play(this._narrationId); + } + else { + this.stop(); + } } } @@ -171,12 +170,13 @@ export default class CVAudioManager extends Component this.isPlaying = true; outs.narrationPlaying.setValue(id === this._narrationId); }) - .catch(error => Notification.show(`Failed to play audio at '${uri}'`, "warning")); + .catch(error => Notification.show(`Failed to play audio at '${this.audioPlayer.getAttribute("src")}':${error}`, "warning")); } stop() { this.audioPlayer.pause(); + this.audioPlayer.currentTime = 0; this.onEnd(); } @@ -186,4 +186,16 @@ export default class CVAudioManager extends Component this.isPlaying = false; outs.narrationPlaying.setValue(false); } + + // setup function required for Safari compatibility so audio element is setup immediately on user interaction. + setupAudio() + { + if(this.audioPlayer === null) { + this.audioPlayer = document.createElement('audio'); + this.audioPlayer.onended = this.onEnd; + //this.audioPlayer.src = "data:audio/mpeg;base64,SUQzBAAAAAABEVRYWFgAAAAtAAADY29tbWVudABCaWdTb3VuZEJhbmsuY29tIC8gTGFTb25vdGhlcXVlLm9yZwBURU5DAAAAHQAAA1N3aXRjaCBQbHVzIMKpIE5DSCBTb2Z0d2FyZQBUSVQyAAAABgAAAzIyMzUAVFNTRQAAAA8AAANMYXZmNTcuODMuMTAwAAAAAAAAAAAAAAD/80DEAAAAA0gAAAAATEFNRTMuMTAwVVVVVVVVVVVVVUxBTUUzLjEwMFVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQsRbAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/zQMSkAAADSAAAAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV"; + + this.ins.playNarration.set(); + } + } } \ No newline at end of file diff --git a/source/client/ui/explorer/ARMenu.ts b/source/client/ui/explorer/ARMenu.ts index 4292fe57..615c9446 100644 --- a/source/client/ui/explorer/ARMenu.ts +++ b/source/client/ui/explorer/ARMenu.ts @@ -90,8 +90,9 @@ export default class ARMenu extends DocumentView protected onToggleNarration() { - const audioIns = this.activeDocument.setup.audio.ins; - audioIns.playNarration.set(); + const audio = this.activeDocument.setup.audio; + audio.setupAudio(); // required for Safari compatibility + audio.ins.playNarration.set(); } protected onToggleAnnotations() diff --git a/source/client/ui/explorer/MainMenu.ts b/source/client/ui/explorer/MainMenu.ts index 38194f34..17091a3d 100644 --- a/source/client/ui/explorer/MainMenu.ts +++ b/source/client/ui/explorer/MainMenu.ts @@ -226,8 +226,9 @@ export default class MainMenu extends DocumentView protected onToggleNarration() { - const audioIns = this.activeDocument.setup.audio.ins; - audioIns.playNarration.set(); + const audio = this.activeDocument.setup.audio; + audio.setupAudio(); // required for Safari compatibility + audio.ins.playNarration.set(); } // TODO: More elegant way to handle focus diff --git a/source/client/ui/explorer/TourNavigator.ts b/source/client/ui/explorer/TourNavigator.ts index bd9cc3d5..56b5fec5 100644 --- a/source/client/ui/explorer/TourNavigator.ts +++ b/source/client/ui/explorer/TourNavigator.ts @@ -34,6 +34,7 @@ export default class TourNavigator extends DocumentView protected needsFocus: boolean = false; protected firstRender: boolean = true; + protected stepTitle: string = ""; protected firstConnected() { @@ -62,6 +63,7 @@ export default class TourNavigator extends DocumentView title = language.getLocalizedString("No tour selected"); info = "---"; } + this.stepTitle = title; return html`
this.onKeyDown(e)}>
@@ -85,10 +87,14 @@ export default class TourNavigator extends DocumentView } // Hack so that initial nav title display is detected by screen readers. - if(this.firstRender) { - const titleDiv = this.getElementsByClassName("sv-title").item(0) as HTMLElement; - setTimeout(() => {titleDiv.innerHTML = `
${titleDiv.innerText}
`;}, 100); - this.firstRender = false; + const titleDiv = this.getElementsByClassName("sv-title").item(0) as HTMLElement; + if(titleDiv) + { + titleDiv.innerHTML = this.stepTitle; + if(this.firstRender) { + setTimeout(() => {titleDiv.innerHTML = `
${this.stepTitle}
`;}, 100); + this.firstRender = false; + } } } diff --git a/source/client/ui/explorer/styles.scss b/source/client/ui/explorer/styles.scss index 38eac732..f525dcb6 100644 --- a/source/client/ui/explorer/styles.scss +++ b/source/client/ui/explorer/styles.scss @@ -526,6 +526,7 @@ $pad: $canvas-border-width + $main-menu-button-size + 8px; & > .ff-button { box-sizing: border-box; + -webkit-tap-highlight-color: transparent; width: $main-menu-button-size; height: $main-menu-button-size; margin: 2px 0; diff --git a/source/client/ui/styles.scss b/source/client/ui/styles.scss index ef8706ce..647757f4 100644 --- a/source/client/ui/styles.scss +++ b/source/client/ui/styles.scss @@ -136,6 +136,10 @@ } +.ff-flex-spacer { + @include noselect; +} + // Screen reader only elements .sr-only { position: absolute;