From 197c4b56f7d47ee324ff51241ee1293df7d89c2e Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Wed, 1 Apr 2026 08:23:33 +0000 Subject: [PATCH] update display --- assets/js/main.js | 141 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 119 insertions(+), 22 deletions(-) diff --git a/assets/js/main.js b/assets/js/main.js index 03c2439..66835ff 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -84,6 +84,21 @@ document.addEventListener('DOMContentLoaded', () => { fullscreenButton.hidden = true; } + let audioCtx = null; + const initAudio = () => { + try { + const AudioContext = window.AudioContext || window.webkitAudioContext; + if (!audioCtx && AudioContext) { + audioCtx = new AudioContext(); + } + if (audioCtx && audioCtx.state === 'suspended') { + audioCtx.resume(); + } + } catch (e) { + console.warn('AudioContext init failed', e); + } + }; + const audioBtn = document.querySelector('.js-audio-toggle'); if (audioBtn) { const updateAudioBtnState = () => { @@ -109,38 +124,120 @@ document.addEventListener('DOMContentLoaded', () => { window.localStorage.setItem('hospitalQueue:audioEnabled', nextState.toString()); updateAudioBtnState(); - if (nextState && 'speechSynthesis' in window) { - const primeUtterance = new SpeechSynthesisUtterance(''); - window.speechSynthesis.speak(primeUtterance); + if (nextState) { + initAudio(); + if ('speechSynthesis' in window) { + const primeUtterance = new SpeechSynthesisUtterance(''); + window.speechSynthesis.speak(primeUtterance); + } } }); } - const cards = Array.from(document.querySelectorAll('.announcement-card')); - const latest = cards[0]; - const audioEnabled = window.localStorage.getItem('hospitalQueue:audioEnabled') === 'true'; - if (latest && 'speechSynthesis' in window && audioEnabled) { - const announcementKey = latest.dataset.announcementKey || ''; - const storageKey = `hospitalQueue:lastAnnouncement:${locale}`; - const storedKey = window.localStorage.getItem(storageKey) || ''; - if (announcementKey && announcementKey !== storedKey) { - const text = locale === 'ar' ? (latest.dataset.announcementAr || '') : (latest.dataset.announcementEn || ''); - const utterance = new SpeechSynthesisUtterance(text); - utterance.lang = locale === 'ar' ? 'ar-SA' : 'en-US'; - const voices = window.speechSynthesis.getVoices(); - const preferredVoice = voices.find((voice) => voice.lang.toLowerCase().startsWith(locale === 'ar' ? 'ar' : 'en')); - if (preferredVoice) utterance.voice = preferredVoice; - window.speechSynthesis.cancel(); - if (text) { - window.speechSynthesis.speak(utterance); + const playChime = () => { + try { + if (!audioCtx) initAudio(); + if (!audioCtx) return; + if (audioCtx.state === 'suspended') audioCtx.resume(); + + const playTone = (freq, startTime, duration) => { + const osc = audioCtx.createOscillator(); + const gain = audioCtx.createGain(); + osc.connect(gain); + gain.connect(audioCtx.destination); + osc.type = 'sine'; + osc.frequency.setValueAtTime(freq, audioCtx.currentTime + startTime); + gain.gain.setValueAtTime(0, audioCtx.currentTime + startTime); + gain.gain.linearRampToValueAtTime(0.5, audioCtx.currentTime + startTime + 0.05); + gain.gain.exponentialRampToValueAtTime(0.01, audioCtx.currentTime + startTime + duration); + osc.start(audioCtx.currentTime + startTime); + osc.stop(audioCtx.currentTime + startTime + duration); + }; + playTone(523.25, 0, 0.4); // C5 + playTone(659.25, 0.3, 0.6); // E5 + } catch (e) { + console.warn('AudioContext failed', e); + } + }; + + const checkAnnouncements = () => { + const cards = Array.from(document.querySelectorAll('.announcement-card')); + const latest = cards[0]; + const audioEnabled = window.localStorage.getItem('hospitalQueue:audioEnabled') === 'true'; + + if (latest) { + const announcementKey = latest.dataset.announcementKey || ''; + const storageKey = `hospitalQueue:lastAnnouncement:${locale}`; + const storedKey = window.localStorage.getItem(storageKey) || ''; + + if (announcementKey && announcementKey !== storedKey) { window.localStorage.setItem(storageKey, announcementKey); + + if (audioEnabled) { + const videoPlayer = document.getElementById('adsVideoPlayer'); + if (videoPlayer) videoPlayer.volume = 0.1; + + playChime(); + + if ('speechSynthesis' in window) { + setTimeout(() => { + const text = locale === 'ar' ? (latest.dataset.announcementAr || '') : (latest.dataset.announcementEn || ''); + if (text) { + window.speechSynthesis.cancel(); + const utterance = new SpeechSynthesisUtterance(text); + utterance.lang = locale === 'ar' ? 'ar-SA' : 'en-US'; + const voices = window.speechSynthesis.getVoices(); + const preferredVoice = voices.find((voice) => voice.lang.toLowerCase().startsWith(locale === 'ar' ? 'ar' : 'en')); + if (preferredVoice) utterance.voice = preferredVoice; + + utterance.onend = () => { if (videoPlayer) videoPlayer.volume = 1.0; }; + utterance.onerror = () => { if (videoPlayer) videoPlayer.volume = 1.0; }; + + window.speechSynthesis.speak(utterance); + } else { + if (videoPlayer) videoPlayer.volume = 1.0; + } + }, 1200); // play voice after chime finishes + } else { + setTimeout(() => { if (videoPlayer) videoPlayer.volume = 1.0; }, 2000); + } + } } } - } + }; + + checkAnnouncements(); const autoRefreshSeconds = parseInt(document.querySelector('[data-auto-refresh]')?.dataset.autoRefresh || '0', 10); if (autoRefreshSeconds > 0) { - window.setTimeout(() => window.location.reload(), autoRefreshSeconds * 1000); + window.setInterval(async () => { + try { + const response = await fetch(window.location.href, { + headers: { 'X-Requested-With': 'XMLHttpRequest' } + }); + if (response.ok) { + const html = await response.text(); + const parser = new DOMParser(); + const doc = parser.parseFromString(html, 'text/html'); + + const newSections = doc.querySelector('#queueSections'); + const currentSections = document.querySelector('#queueSections'); + if (newSections && currentSections) { + currentSections.innerHTML = newSections.innerHTML; + } + + const oldTicker = document.querySelector('.news-ticker-container'); + const newTicker = doc.querySelector('.news-ticker-container'); + if (oldTicker && newTicker) { + oldTicker.innerHTML = newTicker.innerHTML; + } + + checkAnnouncements(); + } + } catch (e) { + console.error('Auto-refresh failed', e); + } + }, autoRefreshSeconds * 1000); } } });