update sound
This commit is contained in:
parent
f81da63413
commit
5f6b8289df
@ -84,7 +84,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
fullscreenButton.hidden = true;
|
||||
}
|
||||
|
||||
let audioCtx = null;
|
||||
let audioCtx = null;
|
||||
const initAudio = () => {
|
||||
try {
|
||||
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
@ -99,14 +99,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
};
|
||||
|
||||
let availableVoices = [];
|
||||
if ('speechSynthesis' in window) {
|
||||
const updateVoices = () => { availableVoices = window.speechSynthesis.getVoices(); };
|
||||
updateVoices();
|
||||
if (window.speechSynthesis.onvoiceschanged !== undefined) {
|
||||
window.speechSynthesis.onvoiceschanged = updateVoices;
|
||||
}
|
||||
}
|
||||
|
||||
const audioBtn = document.querySelector('.js-audio-toggle');
|
||||
if (audioBtn) {
|
||||
const updateAudioBtnState = () => {
|
||||
const isEnabled = window.localStorage.getItem('hospitalQueue:audioEnabled') === 'true';
|
||||
if (isEnabled) {
|
||||
audioBtn.innerHTML = '<i class="bi bi-volume-up"></i>';
|
||||
audioBtn.innerHTML = '<i class="bi bi-megaphone-fill"></i>';
|
||||
} else {
|
||||
audioBtn.innerHTML = '<i class="bi bi-volume-mute"></i>';
|
||||
audioBtn.innerHTML = '<i class="bi bi-megaphone"></i>';
|
||||
}
|
||||
audioBtn.setAttribute('aria-pressed', isEnabled.toString());
|
||||
|
||||
@ -183,10 +192,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
setTimeout(() => {
|
||||
const text = locale === 'ar' ? (latest.dataset.announcementAr || '') : (latest.dataset.announcementEn || '');
|
||||
if (text) {
|
||||
window.speechSynthesis.cancel();
|
||||
// Removed window.speechSynthesis.cancel(); as it can prevent speech in some browsers
|
||||
const utterance = new SpeechSynthesisUtterance(text);
|
||||
utterance.lang = locale === 'ar' ? 'ar-SA' : 'en-US';
|
||||
const voices = window.speechSynthesis.getVoices();
|
||||
const voices = availableVoices.length > 0 ? availableVoices : window.speechSynthesis.getVoices();
|
||||
const langPrefix = locale === 'ar' ? 'ar' : 'en';
|
||||
const langVoices = voices.filter(v => v.lang.toLowerCase().startsWith(langPrefix));
|
||||
|
||||
@ -218,7 +227,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
};
|
||||
|
||||
checkAnnouncements();
|
||||
checkAnnouncements();
|
||||
|
||||
const autoRefreshSeconds = parseInt(document.querySelector('[data-auto-refresh]')?.dataset.autoRefresh || '0', 10);
|
||||
if (autoRefreshSeconds > 0) {
|
||||
@ -252,4 +261,4 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}, autoRefreshSeconds * 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -60,7 +60,7 @@ qh_page_start(
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<div class="fs-5 fw-bold text-dark js-live-clock"><?= qh_h(date('H:i')) ?></div>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm shadow-sm me-2 js-audio-toggle" id="globalAudioToggle" title="<?= qh_h(qh_t('Toggle Audio', 'تبديل الصوت')) ?>">
|
||||
<i class="bi bi-volume-mute"></i>
|
||||
<i class="bi bi-megaphone"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm shadow-sm js-fullscreen-toggle" aria-pressed="false" data-label-enter="<?= qh_h(qh_t('Fullscreen', 'ملء الشاشة')) ?>" data-label-exit="<?= qh_h(qh_t('Exit fullscreen', 'إنهاء ملء الشاشة')) ?>"><i class="bi bi-arrows-fullscreen"></i></button>
|
||||
</div>
|
||||
|
||||
87
patch_audio.js
Normal file
87
patch_audio.js
Normal file
@ -0,0 +1,87 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const jsPath = path.join(__dirname, 'assets/js/main.js');
|
||||
let jsCode = fs.readFileSync(jsPath, 'utf8');
|
||||
|
||||
// Replace the icon logic
|
||||
jsCode = jsCode.replace(
|
||||
/audioBtn\.innerHTML = '<i class="bi bi-volume-up"><\/i>';/g,
|
||||
`audioBtn.innerHTML = '<i class="bi bi-megaphone-fill text-success"></i>';`
|
||||
).replace(
|
||||
/audioBtn\.innerHTML = '<i class="bi bi-volume-mute"><\/i>';/g,
|
||||
`audioBtn.innerHTML = '<i class="bi bi-megaphone"></i>';`
|
||||
);
|
||||
|
||||
// Add logic to test sound when audio is enabled
|
||||
const repl1 = `if (nextState) {
|
||||
initAudio();
|
||||
if ('speechSynthesis' in window) {
|
||||
const primeUtterance = new SpeechSynthesisUtterance('');
|
||||
window.speechSynthesis.speak(primeUtterance);
|
||||
}
|
||||
}`;
|
||||
const repl2 = `if (nextState) {
|
||||
initAudio();
|
||||
if ('speechSynthesis' in window) {
|
||||
const primeUtterance = new SpeechSynthesisUtterance('');
|
||||
window.speechSynthesis.speak(primeUtterance);
|
||||
}
|
||||
|
||||
// Force latest announcement to replay
|
||||
const cards = Array.from(document.querySelectorAll('.announcement-card'));
|
||||
const latest = cards[0];
|
||||
if (latest) {
|
||||
const storageKey =
|
||||
`hospitalQueue:lastAnnouncement:${locale}
|
||||
`;
|
||||
window.localStorage.removeItem(storageKey);
|
||||
setTimeout(checkAnnouncements, 200);
|
||||
}
|
||||
}`;
|
||||
jsCode = jsCode.replace(repl1, repl2);
|
||||
|
||||
// Make sure speech synthesis gets voices early, and handle fallback properly
|
||||
const oldVoiceLogic = `if (langVoices.length > 0) {
|
||||
// Try to find a high-quality (Google/Microsoft Natural) voice
|
||||
const bestVoice = langVoices.find(v =>
|
||||
v.name.includes('Google') ||
|
||||
v.name.includes('Natural') ||
|
||||
v.name.includes('Premium') ||
|
||||
v.name.includes('Online')
|
||||
) || langVoices.find(v => v.name.includes('Microsoft')) || langVoices[0];
|
||||
|
||||
utterance.voice = bestVoice;
|
||||
}`;
|
||||
|
||||
const newVoiceLogic = `if (langVoices.length > 0) {
|
||||
// Try to find a high-quality (Google/Microsoft Natural) voice
|
||||
const bestVoice = langVoices.find(v =>
|
||||
v.name.includes('Google') ||
|
||||
v.name.includes('Natural') ||
|
||||
v.name.includes('Premium') ||
|
||||
v.name.includes('Online')
|
||||
) || langVoices.find(v => v.name.includes('Microsoft')) || langVoices[0];
|
||||
|
||||
utterance.voice = bestVoice;
|
||||
} else if (voices.length > 0) {
|
||||
// Fallback to any available voice to ensure sound plays
|
||||
utterance.voice = voices[0];
|
||||
}`;
|
||||
|
||||
jsCode = jsCode.replace(oldVoiceLogic, newVoiceLogic);
|
||||
|
||||
// Call getVoices early
|
||||
if (!jsCode.includes('window.speechSynthesis.getVoices();')) {
|
||||
jsCode = jsCode.replace(
|
||||
`document.addEventListener('DOMContentLoaded', () => {`,
|
||||
`document.addEventListener('DOMContentLoaded', () => {
|
||||
if ('speechSynthesis' in window) {
|
||||
window.speechSynthesis.onvoiceschanged = () => { window.speechSynthesis.getVoices(); };
|
||||
window.speechSynthesis.getVoices();
|
||||
}`
|
||||
);
|
||||
}
|
||||
|
||||
fs.writeFileSync(jsPath, jsCode);
|
||||
console.log('patched');
|
||||
@ -625,6 +625,7 @@ function qh_page_start(string $activePage, string $pageTitle, string $metaDescri
|
||||
}
|
||||
echo ' <meta name="theme-color" content="' . qh_h($primaryColor) . '">';
|
||||
echo ' <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">';
|
||||
echo ' <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">';
|
||||
echo ' <link rel="stylesheet" href="assets/css/custom.css?v=' . $assetVersionCss . '">';
|
||||
echo ' <style>:root{--accent:' . qh_h($primaryColor) . ';--accent-strong:' . qh_h($secondaryColor) . ';}</style>';
|
||||
echo '</head>';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user