perf: optimize seek bar dragging to prevent network spam

This commit is contained in:
Julien Maille 2026-01-14 23:46:04 +01:00
parent bfbc0fa328
commit d5ef9f288b

View file

@ -299,6 +299,7 @@ export function initializePlayerEvents(player, audioPlayer, scrobbler, ui) {
function initializeSmoothSliders(audioPlayer, player) { function initializeSmoothSliders(audioPlayer, player) {
const progressBar = document.getElementById('progress-bar'); const progressBar = document.getElementById('progress-bar');
const progressFill = document.getElementById('progress-fill'); const progressFill = document.getElementById('progress-fill');
const currentTimeEl = document.getElementById('current-time');
const volumeBar = document.getElementById('volume-bar'); const volumeBar = document.getElementById('volume-bar');
const volumeFill = document.getElementById('volume-fill'); const volumeFill = document.getElementById('volume-fill');
const volumeBtn = document.getElementById('volume-btn'); const volumeBtn = document.getElementById('volume-btn');
@ -306,6 +307,7 @@ function initializeSmoothSliders(audioPlayer, player) {
let isSeeking = false; let isSeeking = false;
let wasPlaying = false; let wasPlaying = false;
let isAdjustingVolume = false; let isAdjustingVolume = false;
let lastSeekPosition = 0;
const seek = (bar, event, setter) => { const seek = (bar, event, setter) => {
const rect = bar.getBoundingClientRect(); const rect = bar.getBoundingClientRect();
@ -313,6 +315,15 @@ function initializeSmoothSliders(audioPlayer, player) {
setter(position); setter(position);
}; };
const updateSeekUI = (position) => {
if (!isNaN(audioPlayer.duration)) {
progressFill.style.width = `${position * 100}%`;
if (currentTimeEl) {
currentTimeEl.textContent = formatTime(position * audioPlayer.duration);
}
}
};
// Progress bar with smooth dragging // Progress bar with smooth dragging
progressBar.addEventListener('mousedown', (e) => { progressBar.addEventListener('mousedown', (e) => {
isSeeking = true; isSeeking = true;
@ -320,10 +331,8 @@ function initializeSmoothSliders(audioPlayer, player) {
if (wasPlaying) audioPlayer.pause(); if (wasPlaying) audioPlayer.pause();
seek(progressBar, e, (position) => { seek(progressBar, e, (position) => {
if (!isNaN(audioPlayer.duration)) { lastSeekPosition = position;
audioPlayer.currentTime = position * audioPlayer.duration; updateSeekUI(position);
progressFill.style.width = `${position * 100}%`;
}
}); });
}); });
@ -337,19 +346,16 @@ function initializeSmoothSliders(audioPlayer, player) {
const touch = e.touches[0]; const touch = e.touches[0];
const rect = progressBar.getBoundingClientRect(); const rect = progressBar.getBoundingClientRect();
const position = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width)); const position = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width));
if (!isNaN(audioPlayer.duration)) {
audioPlayer.currentTime = position * audioPlayer.duration; lastSeekPosition = position;
progressFill.style.width = `${position * 100}%`; updateSeekUI(position);
}
}); });
document.addEventListener('mousemove', (e) => { document.addEventListener('mousemove', (e) => {
if (isSeeking) { if (isSeeking) {
seek(progressBar, e, (position) => { seek(progressBar, e, (position) => {
if (!isNaN(audioPlayer.duration)) { lastSeekPosition = position;
audioPlayer.currentTime = position * audioPlayer.duration; updateSeekUI(position);
progressFill.style.width = `${position * 100}%`;
}
}); });
} }
@ -371,10 +377,9 @@ function initializeSmoothSliders(audioPlayer, player) {
const touch = e.touches[0]; const touch = e.touches[0];
const rect = progressBar.getBoundingClientRect(); const rect = progressBar.getBoundingClientRect();
const position = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width)); const position = Math.max(0, Math.min(1, (touch.clientX - rect.left) / rect.width));
if (!isNaN(audioPlayer.duration)) {
audioPlayer.currentTime = position * audioPlayer.duration; lastSeekPosition = position;
progressFill.style.width = `${position * 100}%`; updateSeekUI(position);
}
} }
if (isAdjustingVolume) { if (isAdjustingVolume) {
@ -393,13 +398,12 @@ function initializeSmoothSliders(audioPlayer, player) {
document.addEventListener('mouseup', (e) => { document.addEventListener('mouseup', (e) => {
if (isSeeking) { if (isSeeking) {
seek(progressBar, e, (position) => { // Commit the seek
if (!isNaN(audioPlayer.duration)) { if (!isNaN(audioPlayer.duration)) {
audioPlayer.currentTime = position * audioPlayer.duration; audioPlayer.currentTime = lastSeekPosition * audioPlayer.duration;
player.updateMediaSessionPositionState(); player.updateMediaSessionPositionState();
if (wasPlaying) audioPlayer.play(); if (wasPlaying) audioPlayer.play();
} }
});
isSeeking = false; isSeeking = false;
} }
@ -411,6 +415,7 @@ function initializeSmoothSliders(audioPlayer, player) {
document.addEventListener('touchend', (e) => { document.addEventListener('touchend', (e) => {
if (isSeeking) { if (isSeeking) {
if (!isNaN(audioPlayer.duration)) { if (!isNaN(audioPlayer.duration)) {
audioPlayer.currentTime = lastSeekPosition * audioPlayer.duration;
player.updateMediaSessionPositionState(); player.updateMediaSessionPositionState();
if (wasPlaying) audioPlayer.play(); if (wasPlaying) audioPlayer.play();
} }
@ -423,7 +428,7 @@ function initializeSmoothSliders(audioPlayer, player) {
}); });
progressBar.addEventListener('click', (e) => { progressBar.addEventListener('click', (e) => {
if (!isSeeking) { if (!isSeeking) { // Only handle click if not result of a drag release
seek(progressBar, e, (position) => { seek(progressBar, e, (position) => {
if (!isNaN(audioPlayer.duration) && audioPlayer.duration > 0 && audioPlayer.duration !== Infinity) { if (!isNaN(audioPlayer.duration) && audioPlayer.duration > 0 && audioPlayer.duration !== Infinity) {
audioPlayer.currentTime = position * audioPlayer.duration; audioPlayer.currentTime = position * audioPlayer.duration;