fix "now playing" flicker; fix album art url
Hunter
Tuesday, November 4th, 2025 at 11:12 PM
99 // Update media session metadata
100 if ('mediaSession' in navigator) {
101 // Convert relative path to absolute URL for media session
- const albumArtUrl = new URL('resources/album_art.jpg', window.location.href).href;
102 + // Use document.baseURI to correctly resolve paths in subdirectories
103 + const albumArtUrl = new URL('resources/album_art.jpg', document.baseURI).href;
104 navigator.mediaSession.metadata = new MediaMetadata({
105 title: song.title,
106 artist: song.artist,
844 // Create a blob URL that will persist in memory
845 const blobUrl = URL.createObjectURL(blob);
846
- // Create audio element with the fully downloaded blob
- const preloadAudio = new Audio();
- preloadAudio.preload = 'auto';
- preloadAudio.src = blobUrl;
-
- // Wait for the audio element to fully buffer the blob
- return new Promise((resolve) => {
- const checkBuffered = () => {
- // Check if the entire duration is buffered
- if (preloadAudio.duration > 0 && preloadAudio.buffered.length > 0) {
- const bufferedEnd = preloadAudio.buffered.end(preloadAudio.buffered.length - 1);
- if (bufferedEnd >= preloadAudio.duration - 0.1) {
- // Fully buffered!
- resolve({ preloadAudio, blobUrl, blob });
- return;
- }
- }
- // Not fully buffered yet, check again soon
- setTimeout(checkBuffered, 100);
- };
-
- // Start checking once metadata is loaded
- preloadAudio.addEventListener('loadedmetadata', () => {
- checkBuffered();
- }, { once: true });
-
- // Trigger the loading
- preloadAudio.load();
- });
- })
- .then(({ preloadAudio, blobUrl, blob }) => {
- // Store both the audio element and blob URL
847 preloadedAudio[filename] = {
- audio: preloadAudio,
848 blobUrl: blobUrl,
849 blob: blob
850 };
935 // Create a blob URL that will persist in memory
936 const blobUrl = URL.createObjectURL(blob);
937
- // Create audio element with the cached blob
- const preloadAudio = new Audio();
- preloadAudio.preload = 'auto';
- preloadAudio.src = blobUrl;
-
- // Wait for the audio element to fully buffer the blob
- return new Promise((resolve) => {
- const checkBuffered = () => {
- // Check if the entire duration is buffered
- if (preloadAudio.duration > 0 && preloadAudio.buffered.length > 0) {
- const bufferedEnd = preloadAudio.buffered.end(preloadAudio.buffered.length - 1);
- if (bufferedEnd >= preloadAudio.duration - 0.1) {
- // Fully buffered!
- preloadedAudio[filename] = {
- audio: preloadAudio,
- blobUrl: blobUrl,
- blob: blob
- };
- console.log(`✓ Loaded from cache: ${filename}`);
- resolve();
- return;
- }
- }
- // Not fully buffered yet, check again soon
- setTimeout(checkBuffered, 100);
- };
-
- // Start checking once metadata is loaded
- preloadAudio.addEventListener('loadedmetadata', () => {
- checkBuffered();
- }, { once: true });
-
- // Trigger the loading
- preloadAudio.load();
- });
938 + preloadedAudio[filename] = {
939 + blobUrl: blobUrl,
940 + blob: blob
941 + };
942 + console.log(`✓ Loaded from cache: ${filename}`);
943 } catch (error) {
944 console.error(`Failed to load from cache: ${filename}`, error);
945 throw error;
1047 // Create a blob URL that will persist in memory
1048 const blobUrl = URL.createObjectURL(blob);
1049
- // Create audio element with the fully downloaded blob
- const preloadAudio = new Audio();
- preloadAudio.preload = 'auto';
- preloadAudio.src = blobUrl;
-
- // Wait for the audio element to fully buffer the blob
- return new Promise((resolve) => {
- const checkBuffered = () => {
- // Check if the entire duration is buffered
- if (preloadAudio.duration > 0 && preloadAudio.buffered.length > 0) {
- const bufferedEnd = preloadAudio.buffered.end(preloadAudio.buffered.length - 1);
- if (bufferedEnd >= preloadAudio.duration - 0.1) {
- // Fully buffered!
- resolve({ preloadAudio, blobUrl, blob });
- return;
- }
- }
- // Not fully buffered yet, check again soon
- setTimeout(checkBuffered, 100);
- };
-
- // Start checking once metadata is loaded
- preloadAudio.addEventListener('loadedmetadata', () => {
- checkBuffered();
- }, { once: true });
-
- // Trigger the loading
- preloadAudio.load();
- });
- })
- .then(({ preloadAudio, blobUrl, blob }) => {
- // Store both the audio element and blob URL
1050 preloadedAudio[filename] = {
- audio: preloadAudio,
1051 blobUrl: blobUrl,
1052 blob: blob
1053 };
1054
- // Switch to the preloaded version if this is the current song
- if (songs[currentSongIndex].filename === filename && audio.src !== blobUrl) {
- const currentTime = audio.currentTime;
- const wasPlaying = !audio.paused;
- audio.src = blobUrl;
- audio.currentTime = currentTime;
- if (wasPlaying) {
- audio.play().catch(err => {
- // Ignore play interruption errors (expected during source switching)
- if (err.name !== 'AbortError') {
- console.error('Error resuming playback:', err);
- }
- });
- }
- }
1055 + // Next time this song plays, it will use the cached version
1056 + console.log(`✓ Priority preloaded: ${song.artist} – ${song.title}`);
1057
1058 // Store in Cache API for offline access
1059 return storeBlobInCache(filename, blob).then(() => {