chore: fixes

This commit is contained in:
MattTheTekie 2026-05-04 20:07:59 -04:00
commit 49c2009a74

View file

@ -1,12 +1,12 @@
// ============================
// Volume normalization
// Volume control
// ============================
document.querySelectorAll("audio").forEach((audio) => {
audio.volume = 0.5;
});
// ============================
// Fisher-Yates Shuffle
// Shuffle (safe)
// ============================
function fisherYatesShuffle(arr) {
if (!Array.isArray(arr)) return [];
@ -15,66 +15,81 @@ function fisherYatesShuffle(arr) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
return arr;
}
// ============================
// Fetch music data (SAFE)
// SAFE FETCH (fixes JSON crash)
// ============================
async function loadMusicData(category = "frutigerAeroBliss") {
async function safeFetchJSON(url) {
try {
const response = await fetch("https://api.veltron.net");
const res = await fetch(url);
if (!response.ok) {
console.error("HTTP error:", response.status);
return [];
if (!res.ok) {
console.error("HTTP error:", res.status);
return null;
}
const data = await response.json();
const text = await res.text();
if (!data?.ols || !Array.isArray(data.ols)) {
console.error("Invalid API structure:", data);
return [];
// Reject non-JSON responses (HTML, error pages, etc.)
const trimmed = text.trim();
if (!trimmed || (trimmed[0] !== "{" && trimmed[0] !== "[")) {
console.error("Non-JSON response detected:", trimmed.slice(0, 120));
return null;
}
const section =
data.ols.find((item) => item?.["@id"] === category) || data.ols[0];
if (!section?.li || !Array.isArray(section.li)) {
console.error("Missing playlist section:", category);
return [];
}
const baseUrl = "https://cdn.veltron.net/aero";
const playlist = section.li
.map((item) => {
const a = item?.a;
const mp3 = a?.["@data-src-mp3"];
const title = a?.title;
if (!mp3 || !title) return null;
return {
title,
url: baseUrl + mp3.split("/").pop(),
background: a["@data-background"] || "",
artist: a["@data-artist"] || "",
youtubeLink: a["@data-youtube"] || ""
};
})
.filter(Boolean);
return fisherYatesShuffle(playlist);
return JSON.parse(text);
} catch (err) {
console.error("Failed to load music:", err);
return [];
console.error("Fetch failed:", err);
return null;
}
}
// ============================
// DOM Elements
// Load music data
// ============================
async function loadMusicData(category = "frutigerAeroBliss") {
const data = await safeFetchJSON("https://api.veltron.net");
if (!data?.ols || !Array.isArray(data.ols)) {
console.error("Invalid API structure");
return [];
}
const section =
data.ols.find((x) => x?.["@id"] === category) || data.ols[0];
if (!section?.li || !Array.isArray(section.li)) {
console.error("Missing playlist section");
return [];
}
const baseUrl = "https://cdn.veltron.net/aero";
const playlist = section.li
.map((item) => {
const a = item?.a;
const mp3 = a?.["@data-src-mp3"];
const title = a?.title;
if (!mp3 || !title) return null;
return {
title,
url: baseUrl + mp3.split("/").pop(),
background: a["@data-background"] || "",
artist: a["@data-artist"] || "",
youtube: a["@data-youtube"] || ""
};
})
.filter(Boolean);
return fisherYatesShuffle(playlist);
}
// ============================
// DOM
// ============================
const NAV_MUSIC = document.getElementById("navMusic");
const BUTTON_PLAY = document.getElementById("navMusicPlay");
@ -91,7 +106,7 @@ let currentIndex = 0;
let isPlaying = false;
// ============================
// Session persistence
// Save / Load state
// ============================
function saveState() {
sessionStorage.setItem("isPlaying", JSON.stringify(isPlaying));
@ -99,9 +114,7 @@ function saveState() {
function loadState() {
const saved = sessionStorage.getItem("isPlaying");
if (saved !== null) {
isPlaying = JSON.parse(saved);
}
if (saved !== null) isPlaying = JSON.parse(saved);
}
// ============================
@ -109,25 +122,20 @@ function loadState() {
// ============================
function loadSong(index) {
if (!Array.isArray(songs) || songs.length === 0) return;
if (index < 0 || index >= songs.length) return;
const song = songs[index];
if (!song?.url) {
console.warn("Skipping invalid song at index:", index);
return;
}
if (!song?.url) return;
NAV_MUSIC.src = song.url;
CURRENT_SONG_INFO.innerText = `Featured song: ${song.title}`;
CURRENT_SONG_INFO.innerText = `Now playing: ${song.title}`;
NAV_MUSIC.load();
}
// ============================
// UI state sync
// UI state
// ============================
function updateButtonStates() {
function updateUI() {
BUTTON_PLAY.classList.toggle("active", isPlaying);
BUTTON_PAUSE.classList.toggle("active", !isPlaying);
}
@ -140,14 +148,14 @@ BUTTON_PLAY.addEventListener("click", () => {
isPlaying = true;
NAV_MUSIC.play().catch(() => {});
updateButtonStates();
updateUI();
saveState();
});
BUTTON_PAUSE.addEventListener("click", () => {
isPlaying = false;
NAV_MUSIC.pause();
updateButtonStates();
updateUI();
saveState();
});
@ -172,7 +180,7 @@ BUTTON_NEXT.addEventListener("click", () => {
});
// ============================
// Auto next track
// Auto next
// ============================
NAV_MUSIC.addEventListener("ended", () => {
if (!songs.length) return;
@ -192,18 +200,17 @@ window.addEventListener("load", async () => {
if (!songs.length) {
CURRENT_SONG_INFO.innerText = "No music available";
console.error("Playlist empty or failed to load");
console.error("Playlist failed to load");
return;
}
loadState();
loadSong(currentIndex);
updateUI();
if (isPlaying) {
NAV_MUSIC.play().catch(() => {});
}
updateButtonStates();
});
// ============================