Website overhaul: nav, accessibility, shared components, SEO, Reaper silence detection
Website: - Add persistent top nav across all pages - Add skip-to-content links, focus-visible styles, ARIA on audio player - Fix text contrast for WCAG AA compliance - Add 600px breakpoint, mobile typography scaling - Extract shared footer.js, player.js, episode.js components - Episode pagination (10 + Load More), featured clip dedup - Worker meta injection for social crawler OG tags - Unify Plausible analytics proxy across all pages - Sanitize innerHTML for XSS safety - Custom 404 page, enhanced llms.txt, fix sitemap - Bump cache versions to v=4 Reaper: - Add dual silence threshold: 2.5s for speaker transitions, 6s for same-speaker gaps Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
const audio = document.getElementById('audio-element');
|
||||
const stickyPlayer = document.getElementById('sticky-player');
|
||||
const playerPlayBtn = document.getElementById('player-play-btn');
|
||||
const playerTitle = document.getElementById('player-title');
|
||||
const playerProgress = document.getElementById('player-progress');
|
||||
const playerProgressFill = document.getElementById('player-progress-fill');
|
||||
const playerTime = document.getElementById('player-time');
|
||||
|
||||
function formatTime(seconds) {
|
||||
if (!seconds || isNaN(seconds)) return '0:00';
|
||||
const s = Math.floor(seconds);
|
||||
const h = Math.floor(s / 3600);
|
||||
const m = Math.floor((s % 3600) / 60);
|
||||
const sec = s % 60;
|
||||
if (h > 0) return `${h}:${String(m).padStart(2, '0')}:${String(sec).padStart(2, '0')}`;
|
||||
return `${m}:${String(sec).padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
function updatePlayIcons(playing) {
|
||||
const iconPlay = playerPlayBtn.querySelector('.icon-play');
|
||||
const iconPause = playerPlayBtn.querySelector('.icon-pause');
|
||||
if (iconPlay) iconPlay.style.display = playing ? 'none' : 'block';
|
||||
if (iconPause) iconPause.style.display = playing ? 'block' : 'none';
|
||||
}
|
||||
|
||||
audio.addEventListener('play', () => updatePlayIcons(true));
|
||||
audio.addEventListener('pause', () => updatePlayIcons(false));
|
||||
audio.addEventListener('ended', () => updatePlayIcons(false));
|
||||
audio.addEventListener('timeupdate', () => {
|
||||
if (audio.duration) {
|
||||
playerProgressFill.style.width = (audio.currentTime / audio.duration * 100) + '%';
|
||||
playerTime.textContent = `${formatTime(audio.currentTime)} / ${formatTime(audio.duration)}`;
|
||||
}
|
||||
});
|
||||
|
||||
playerPlayBtn.addEventListener('click', () => {
|
||||
if (audio.src) { audio.paused ? audio.play() : audio.pause(); }
|
||||
});
|
||||
|
||||
playerProgress.addEventListener('click', (e) => {
|
||||
if (audio.duration) {
|
||||
const rect = playerProgress.getBoundingClientRect();
|
||||
audio.currentTime = ((e.clientX - rect.left) / rect.width) * audio.duration;
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user