Add persistent caller voices, Discord, REC/on-air linking, SEO fixes, ep9
- Returning callers now keep their voice across sessions (stored in regulars.json) - Backfilled voice assignments for all 11 existing regulars - Discord button on homepage + link in all page footers - REC and On-Air buttons now toggle together (both directions) - Fixed host mic double-stream bug (stem_mic vs host_stream conflict) - SEO: JSON-LD structured data on episode + how-it-works pages - SEO: noscript fallbacks, RSS links, twitter meta tags - Episode 9 transcript and sitemap update Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -67,11 +67,23 @@ function initEventListeners() {
|
||||
// New Session
|
||||
document.getElementById('new-session-btn')?.addEventListener('click', newSession);
|
||||
|
||||
// On-Air toggle
|
||||
// On-Air + Recording (linked — toggling one toggles both)
|
||||
const onAirBtn = document.getElementById('on-air-btn');
|
||||
const recBtn = document.getElementById('rec-btn');
|
||||
let stemRecording = false;
|
||||
|
||||
function updateRecBtn(recording) {
|
||||
stemRecording = recording;
|
||||
if (recBtn) {
|
||||
recBtn.classList.toggle('recording', recording);
|
||||
recBtn.textContent = recording ? '⏺ REC' : 'REC';
|
||||
}
|
||||
}
|
||||
|
||||
if (onAirBtn) {
|
||||
fetch('/api/on-air').then(r => r.json()).then(data => {
|
||||
updateOnAirBtn(onAirBtn, data.on_air);
|
||||
updateRecBtn(data.recording);
|
||||
});
|
||||
onAirBtn.addEventListener('click', async () => {
|
||||
const isOn = onAirBtn.classList.contains('on');
|
||||
@@ -81,28 +93,24 @@ function initEventListeners() {
|
||||
body: JSON.stringify({ on_air: !isOn }),
|
||||
});
|
||||
updateOnAirBtn(onAirBtn, res.on_air);
|
||||
log(res.on_air ? 'Show is ON AIR — accepting calls' : 'Show is OFF AIR — calls get off-air message');
|
||||
updateRecBtn(res.recording);
|
||||
log(res.on_air ? 'Show is ON AIR + Recording' : 'Show is OFF AIR + Recording stopped');
|
||||
});
|
||||
}
|
||||
|
||||
// Stem recording toggle
|
||||
const recBtn = document.getElementById('rec-btn');
|
||||
if (recBtn) {
|
||||
let stemRecording = false;
|
||||
recBtn.addEventListener('click', async () => {
|
||||
try {
|
||||
if (!stemRecording) {
|
||||
const res = await safeFetch('/api/recording/start', { method: 'POST' });
|
||||
stemRecording = true;
|
||||
recBtn.classList.add('recording');
|
||||
recBtn.textContent = '⏺ REC';
|
||||
log('Stem recording started: ' + res.dir);
|
||||
updateRecBtn(true);
|
||||
if (onAirBtn) updateOnAirBtn(onAirBtn, res.on_air);
|
||||
log('Recording started + ON AIR: ' + res.dir);
|
||||
} else {
|
||||
const res = await safeFetch('/api/recording/stop', { method: 'POST' });
|
||||
stemRecording = false;
|
||||
recBtn.classList.remove('recording');
|
||||
recBtn.textContent = 'REC';
|
||||
log('Stem recording stopped');
|
||||
updateRecBtn(false);
|
||||
if (onAirBtn) updateOnAirBtn(onAirBtn, res.on_air);
|
||||
log('Recording stopped + OFF AIR');
|
||||
}
|
||||
} catch (err) {
|
||||
log('Recording error: ' + err.message);
|
||||
|
||||
Reference in New Issue
Block a user