agahnim.dev/static/miniplayer.js
2026-05-16 22:58:29 +02:00

145 lines
3.9 KiB
JavaScript

function initMiniPlayer() {
const player = document.querySelector("mini-player");
if (!player) return;
const audio = player.querySelector("audio");
const playBtn = player.querySelector('button[data-action="play"]');
const prevBtn = player.querySelector('button[data-action="prev"]');
const nextBtn = player.querySelector('button[data-action="next"]');
const playIcon = playBtn.querySelector(".play-icon");
const pauseIcon = playBtn.querySelector(".pause-icon");
const progressInput = player.querySelector(".progress-input");
const volumeInput = player.querySelector(".volume-input");
const currentTimeEl = player.querySelector("current-time");
const durationTimeEl = player.querySelector("duration-time");
const trackTitleEl = player.querySelector("track-title");
const trackArtistEl = player.querySelector("track-artist");
let isTransitioning = false;
let currentTrackIndex = 0;
let isPlaying = false;
const sources = audio.querySelectorAll("source");
const tracks = Array.from(sources).map((s) => ({
src: s.getAttribute("src"),
title: s.getAttribute("data-title"),
artist: s.getAttribute("data-artist"),
}));
if (!tracks.length) return;
audio.src = tracks[0].src;
audio.volume = parseFloat(volumeInput.value) || 0.7;
const formatTime = (time) => {
if (isNaN(time)) return "00:00";
const m = Math.floor(time / 60);
const s = Math.floor(time % 60);
return `${m.toString().padStart(2, "0")}:${s.toString().padStart(2, "0")}`;
};
const updatePlayState = () => {
if (isPlaying) {
playIcon.style.display = "none";
pauseIcon.style.display = "";
} else {
playIcon.style.display = "";
pauseIcon.style.display = "none";
}
};
const loadTrack = (index) => {
currentTrackIndex = index;
const wasPlaying = isPlaying || isTransitioning;
isTransitioning = false;
audio.src = tracks[index].src;
audio.currentTime = 0;
progressInput.value = 0;
currentTimeEl.textContent = "00:00";
if (trackTitleEl) trackTitleEl.textContent = tracks[index].title;
if (trackArtistEl) trackArtistEl.textContent = tracks[index].artist;
if (wasPlaying) {
audio.addEventListener(
"loadeddata",
() => {
audio.play();
},
{ once: true },
);
}
};
const handlePlayPause = () => {
if (isPlaying) {
audio.pause();
} else {
audio.play();
}
isPlaying = !isPlaying;
updatePlayState();
};
const handlePrev = () => {
const newIndex =
currentTrackIndex === 0 ? tracks.length - 1 : currentTrackIndex - 1;
loadTrack(newIndex);
};
const handleNext = () => {
isTransitioning = true;
const newIndex =
currentTrackIndex === tracks.length - 1 ? 0 : currentTrackIndex + 1;
loadTrack(newIndex);
};
playBtn.addEventListener("click", handlePlayPause);
prevBtn.addEventListener("click", handlePrev);
nextBtn.addEventListener("click", handleNext);
audio.addEventListener("loadeddata", () => {
progressInput.max = audio.duration;
durationTimeEl.textContent = formatTime(audio.duration);
});
audio.addEventListener("timeupdate", () => {
progressInput.value = audio.currentTime;
currentTimeEl.textContent = formatTime(audio.currentTime);
});
audio.addEventListener("ended", handleNext);
progressInput.addEventListener("input", (e) => {
audio.currentTime = parseFloat(e.target.value);
});
volumeInput.addEventListener("input", (e) => {
audio.volume = parseFloat(e.target.value);
});
document.addEventListener("keydown", (e) => {
if (e.target.tagName === "INPUT") return;
if (e.code === "Space") {
e.preventDefault();
handlePlayPause();
}
});
audio.addEventListener("pause", () => {
if (isTransitioning) return;
isPlaying = false;
updatePlayState();
});
audio.addEventListener("play", () => {
isPlaying = true;
updatePlayState();
});
}
initMiniPlayer();