From 7c22e2593e5616605d96fedf96d7517bdd53a342 Mon Sep 17 00:00:00 2001 From: Alexandre <44178713+alexbelgium@users.noreply.github.com> Date: Sat, 12 Apr 2025 10:09:03 +0200 Subject: [PATCH] New feat : Redesigned audio player (#279) * New audio player * New style * Readd vertical bar * Improve appearance safari * Improve layout * Improve alignement of bottom elements * Align --- homepage/static/custom-audio-player.js | 726 +++++++++++++++++++++++++ homepage/views.php | 22 +- scripts/overview.php | 33 +- scripts/play.php | 45 +- scripts/todays_detections.php | 6 +- 5 files changed, 787 insertions(+), 45 deletions(-) create mode 100644 homepage/static/custom-audio-player.js diff --git a/homepage/static/custom-audio-player.js b/homepage/static/custom-audio-player.js new file mode 100644 index 0000000..7a44655 --- /dev/null +++ b/homepage/static/custom-audio-player.js @@ -0,0 +1,726 @@ +function initCustomAudioPlayers() { + // =================== Config & Helpers =================== + const CONFIG = { + LEFT_MARGIN_PERCENT: 6, + RIGHT_MARGIN_PERCENT: 9, + PROGRESS_BAR_UPDATE_INTERVAL: 20, + BUFFER_TIME: 0.1, + }; + + const debounce = (func, wait) => { + let timeout; + return (...args) => { + clearTimeout(timeout); + timeout = setTimeout(() => func.apply(this, args), wait); + }; + }; + + const icons = { + play: ` + + `, + pause: ` + + `, + dots: ` + + `, + spinner: `
+ +
`, + error: ` + + `, + }; + + // For user preferences (gain, filters, etc.) + const safeGet = (k, fb) => { + try { + return localStorage.getItem(k) || fb; + } catch { + return fb; + } + }; + const safeSet = (k, v) => { + try { + localStorage.setItem(k, v); + } catch {} + }; + + // Retrieve saved user preferences + const savedGain = safeGet("customAudioPlayerGain", "Off"); + const savedHighpass = safeGet("customAudioPlayerFilterHigh", "Off"); + const savedLowpass = safeGet("customAudioPlayerFilterLow", "Off"); + + // Helper to apply multiple style properties + const applyStyles = (elem, styles) => Object.assign(elem.style, styles); + + // Basic styling for small control buttons + const styleButton = (btn, styles = {}) => { + applyStyles(btn, styles); + // Subtle hover highlight + btn.addEventListener("mouseover", () => (btn.style.background = "rgba(255,255,255,0.1)")); + btn.addEventListener("mouseout", () => (btn.style.background = "transparent")); + }; + + // Helper to create a button + const createButton = ( + parent, + { text = "", html = "", styles = {}, data = {}, onClick = null } = {} + ) => { + const btn = document.createElement("button"); + btn.type = "button"; + if (text) btn.textContent = text; + if (html) btn.innerHTML = html; + Object.entries(data).forEach(([k, v]) => (btn.dataset[k] = v)); + styleButton(btn, styles); + if (onClick) btn.addEventListener("click", onClick); + parent.appendChild(btn); + return btn; + }; + + // Common small‐button styling + const iconBtnStyle = { + background: "transparent", + border: "none", + cursor: "pointer", + width: "36px", + height: "36px", + display: "flex", + alignItems: "center", + justifyContent: "center", + marginRight: "0.6rem", + padding: "0", + borderRadius: "50%", + }; + const textBtnStyle = { + background: "none", + border: "none", + cursor: "pointer", + color: "white", + fontSize: "14px", + textAlign: "right", + width: "100%", + padding: "6px 12px", + margin: "2px 0", + borderRadius: "4px", + }; + const optionBtnStyle = { + background: "none", + border: "none", + cursor: "pointer", + color: "white", + fontSize: "14px", + textAlign: "center", + width: "auto", + padding: "6px 8px", + margin: "2px 4px", + borderRadius: "4px", + }; + + // =================== Main Loop over all .custom-audio-player =================== + document.querySelectorAll(".custom-audio-player").forEach((player) => { + let hasLoaded = false; // set to true once metadata is available + + // Audio/player data + const audioSrc = player.dataset.audioSrc; + const imageSrc = player.dataset.imageSrc; + + //