From f01802f495e8bec1f247e0bf735847e1e48b1d16 Mon Sep 17 00:00:00 2001 From: Willian Galvani Date: Thu, 3 Aug 2023 21:21:46 -0300 Subject: [PATCH] Fail nicely on browsers with no tts support --- src/components/widgets/Alerter.vue | 12 +++++----- src/stores/alert.ts | 36 ++++++++++++++++++------------ 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/components/widgets/Alerter.vue b/src/components/widgets/Alerter.vue index e639f2b09..f538799c5 100644 --- a/src/components/widgets/Alerter.vue +++ b/src/components/widgets/Alerter.vue @@ -4,9 +4,9 @@ ref="currentAlertBar" class="flex items-center justify-between p-1 overflow-hidden rounded cursor-pointer select-none whitespace-nowrap bg-slate-800/75" > -

{{ currentAlert.message }}

+

{{ currentAlert?.message }}

-

{{ formattedDate(currentAlert.time_created || new Date()) }}

+

{{ formattedDate(currentAlert?.time_created || new Date()) }}

{{ currentAlert.level.toUpperCase() }}

@@ -16,12 +16,12 @@ :class="{ 'opacity-0 invisible': !isShowingExpandedAlerts }" >
-
-

{{ alert.message }}

+
+

{{ alert?.message }}

-

{{ formattedDate(alert.time_created || new Date()) }}

+

{{ formattedDate(alert?.time_created || new Date()) }}

{{ alert.level.toUpperCase() }}

@@ -47,7 +47,7 @@ const alertPersistencyInterval = 10 // in seconds const formattedDate = (datetime: Date): string => format(datetime, 'HH:mm:ss') -const currentAlert = ref(alertStore.alerts[0]) +const currentAlert = ref(alertStore.alerts?.[0] ?? undefined) // eslint-disable-next-line no-undef let currentAlertInterval: NodeJS.Timer | undefined = undefined diff --git a/src/stores/alert.ts b/src/stores/alert.ts index 55615527d..c0c18b388 100644 --- a/src/stores/alert.ts +++ b/src/stores/alert.ts @@ -1,6 +1,6 @@ import { useStorage } from '@vueuse/core' import { defineStore } from 'pinia' -import { computed, reactive, watch } from 'vue' +import { computed, reactive, ref, watch } from 'vue' import { Alert, AlertLevel } from '../types/alert' @@ -49,29 +49,37 @@ export const useAlertStore = defineStore('alert', () => { } // Alert speech syntesis routine - const synth = window.speechSynthesis + const synth = ref(window.speechSynthesis) // We need to cache these otherwise they get garbage collected... + let availableAlertSpeechVoiceNames const utterance_cache: SpeechSynthesisUtterance[] = [] + if (synth.value !== undefined) { + synth.value.onvoiceschanged = () => { + synth.value.getVoices().forEach((voice) => { + availableAlertSpeechVoices.push(voice) + if (selectedAlertSpeechVoiceName.value === undefined && voice.default) { + selectedAlertSpeechVoiceName.value = voice.name + } + }) + } - synth.onvoiceschanged = () => { - synth.getVoices().forEach((voice) => { - availableAlertSpeechVoices.push(voice) - if (selectedAlertSpeechVoiceName.value === undefined && voice.default) { - selectedAlertSpeechVoiceName.value = voice.name - } - }) + availableAlertSpeechVoiceNames = computed(() => + availableAlertSpeechVoices.map((v) => ({ value: v.name, name: `${v.name} (${v.lang})` })) + ) + } else { + availableAlertSpeechVoiceNames = computed(() => []) } - const availableAlertSpeechVoiceNames = computed(() => - availableAlertSpeechVoices.map((v) => ({ value: v.name, name: `${v.name} (${v.lang})` })) - ) - /** * Speaks a text out loud using the browsers TTS engine * @param {string} text string */ function speak(text: string): void { + if (!synth.value) { + console.warn('No speechSynthesis available') + return + } const utterance = new SpeechSynthesisUtterance(text) const voice = availableAlertSpeechVoices.find((v) => v.name === selectedAlertSpeechVoiceName.value) if (voice) { @@ -85,7 +93,7 @@ export const useAlertStore = defineStore('alert', () => { utterance.onerror = function (event) { console.error(`SpeechSynthesisUtterance error: ${event.error}`) } - synth.speak(utterance) + synth.value.speak(utterance) } watch(alerts, () => {