Merge pull request #6 from dazlygonsalves/fix/player-remix-title-display
fix(player): track version display
This commit is contained in:
commit
c3ea9eb7dc
4 changed files with 33 additions and 18 deletions
13
js/app.js
13
js/app.js
|
|
@ -7,7 +7,8 @@ import {
|
|||
REPEAT_MODE, SVG_PLAY, SVG_PAUSE,
|
||||
SVG_VOLUME, SVG_MUTE, formatTime, trackDataStore,
|
||||
buildTrackFilename, RATE_LIMIT_ERROR_MESSAGE, debounce,
|
||||
sanitizeForFilename
|
||||
sanitizeForFilename,
|
||||
getTrackTitle
|
||||
} from './utils.js';
|
||||
|
||||
const downloadTasks = new Map();
|
||||
|
|
@ -38,13 +39,15 @@ function addDownloadTask(trackId, track, filename, api) {
|
|||
const taskEl = document.createElement('div');
|
||||
taskEl.className = 'download-task';
|
||||
taskEl.dataset.trackId = trackId;
|
||||
|
||||
const trackTitle = getTrackTitle(track);
|
||||
|
||||
taskEl.innerHTML = `
|
||||
<div style="display: flex; align-items: start; gap: 0.75rem;">
|
||||
<img src="${api.getCoverUrl(track.album?.cover, '80')}"
|
||||
style="width: 40px; height: 40px; border-radius: 4px; flex-shrink: 0;">
|
||||
<div style="flex: 1; min-width: 0;">
|
||||
<div style="font-weight: 500; font-size: 0.9rem; margin-bottom: 0.25rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">${track.title}</div>
|
||||
<div style="font-weight: 500; font-size: 0.9rem; margin-bottom: 0.25rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">${trackTitle}</div>
|
||||
<div style="font-size: 0.8rem; color: var(--muted-foreground); margin-bottom: 0.5rem;">${track.artist?.name || 'Unknown'}</div>
|
||||
<div class="download-progress-bar" style="height: 4px; background: var(--secondary); border-radius: 2px; overflow: hidden;">
|
||||
<div class="download-progress-fill" style="width: 0%; height: 100%; background: var(--highlight); transition: width 0.2s;"></div>
|
||||
|
|
@ -184,8 +187,9 @@ async function downloadAlbumAsZip(album, tracks, api, quality) {
|
|||
for (let i = 0; i < tracks.length; i++) {
|
||||
const track = tracks[i];
|
||||
const filename = buildTrackFilename(track, quality);
|
||||
const trackTitle = getTrackTitle(track);
|
||||
|
||||
updateBulkDownloadProgress(notification, i, tracks.length, track.title);
|
||||
updateBulkDownloadProgress(notification, i, tracks.length, trackTitle);
|
||||
|
||||
const blob = await downloadTrackBlob(track, quality, api);
|
||||
zip.file(`${folderName}/${filename}`, blob);
|
||||
|
|
@ -777,6 +781,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
|
||||
const html = currentQueue.map((track, index) => {
|
||||
const isPlaying = index === player.currentQueueIndex;
|
||||
const trackTitle = getTrackTitle(track);
|
||||
|
||||
return `
|
||||
<div class="queue-track-item ${isPlaying ? 'playing' : ''}" data-queue-index="${index}" data-track-id="${track.id}" draggable="true">
|
||||
|
|
@ -790,7 +795,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
|||
<img src="${api.getCoverUrl(track.album?.cover, '80')}"
|
||||
class="track-item-cover" loading="lazy">
|
||||
<div class="track-item-details">
|
||||
<div class="title">${track.title}</div>
|
||||
<div class="title">${trackTitle}</div>
|
||||
<div class="artist">${track.artist?.name || 'Unknown'}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
18
js/player.js
18
js/player.js
|
|
@ -1,5 +1,5 @@
|
|||
//player.js
|
||||
import { REPEAT_MODE, formatTime } from './utils.js';
|
||||
import { REPEAT_MODE, formatTime, getTrackTitle } from './utils.js';
|
||||
|
||||
export class Player {
|
||||
constructor(audioElement, api, quality = 'LOSSLESS') {
|
||||
|
|
@ -99,6 +99,7 @@ export class Player {
|
|||
|
||||
for (const { track, index } of tracksToPreload) {
|
||||
if (this.preloadCache.has(track.id)) continue;
|
||||
const trackTitle = getTrackTitle(track);
|
||||
|
||||
try {
|
||||
const streamUrl = await this.api.getStreamUrl(track.id, this.quality);
|
||||
|
|
@ -113,7 +114,7 @@ export class Player {
|
|||
|
||||
} catch (error) {
|
||||
if (error.name !== 'AbortError') {
|
||||
console.debug('Failed to get stream URL for preload:', track.title);
|
||||
console.debug('Failed to get stream URL for preload:', trackTitle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -127,12 +128,14 @@ async playTrackFromQueue() {
|
|||
|
||||
const track = currentQueue[this.currentQueueIndex];
|
||||
this.currentTrack = track;
|
||||
|
||||
const trackTitle = getTrackTitle(track);
|
||||
|
||||
document.querySelector('.now-playing-bar .cover').src =
|
||||
this.api.getCoverUrl(track.album?.cover, '1280');
|
||||
document.querySelector('.now-playing-bar .title').textContent = track.title;
|
||||
document.querySelector('.now-playing-bar .title').textContent = trackTitle;
|
||||
document.querySelector('.now-playing-bar .artist').textContent = track.artist?.name || 'Unknown Artist';
|
||||
document.title = `${track.title} • ${track.artist?.name || 'Unknown'}`;
|
||||
document.title = `${trackTitle} • ${track.artist?.name || 'Unknown'}`;
|
||||
|
||||
this.updatePlayingTrackIndicator();
|
||||
this.updateMediaSession(track);
|
||||
|
|
@ -181,8 +184,8 @@ async playTrackFromQueue() {
|
|||
this.setupCrossfadeListener();
|
||||
|
||||
} catch (error) {
|
||||
console.error(`Could not play track: ${track.title}`, error);
|
||||
document.querySelector('.now-playing-bar .title').textContent = `Error: ${track.title}`;
|
||||
console.error(`Could not play track: ${trackTitle}`, error);
|
||||
document.querySelector('.now-playing-bar .title').textContent = `Error: ${trackTitle}`;
|
||||
document.querySelector('.now-playing-bar .artist').textContent = error.message || 'Could not load track';
|
||||
}
|
||||
}
|
||||
|
|
@ -410,6 +413,7 @@ async playTrackFromQueue() {
|
|||
const artwork = [];
|
||||
const sizes = ['1280'];
|
||||
const coverId = track.album?.cover;
|
||||
const trackTitle = getTrackTitle(track);
|
||||
|
||||
if (coverId) {
|
||||
sizes.forEach(size => {
|
||||
|
|
@ -422,7 +426,7 @@ async playTrackFromQueue() {
|
|||
}
|
||||
|
||||
navigator.mediaSession.metadata = new MediaMetadata({
|
||||
title: track.title || 'Unknown Title',
|
||||
title: trackTitle,
|
||||
artist: track.artist?.name || 'Unknown Artist',
|
||||
album: track.album?.title || 'Unknown Album',
|
||||
artwork: artwork.length > 0 ? artwork : undefined
|
||||
|
|
|
|||
11
js/ui.js
11
js/ui.js
|
|
@ -1,5 +1,5 @@
|
|||
//ui.js
|
||||
import { formatTime, createPlaceholder, trackDataStore, hasExplicitContent } from './utils.js';
|
||||
import { formatTime, createPlaceholder, trackDataStore, hasExplicitContent, getTrackTitle } from './utils.js';
|
||||
import { recentActivityManager } from './storage.js';
|
||||
|
||||
export class UIRenderer {
|
||||
|
|
@ -25,7 +25,8 @@ export class UIRenderer {
|
|||
createTrackItemHTML(track, index, showCover = false) {
|
||||
const playIconSmall = '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>';
|
||||
const trackNumberHTML = `<div class="track-number">${showCover ? playIconSmall : index + 1}</div>`;
|
||||
const explicitBadge = hasExplicitContent(track) ? this.createExplicitBadge() : '';
|
||||
const explicitBadge = !hasExplicitContent(track) ? this.createExplicitBadge() : '';
|
||||
const trackTitle = getTrackTitle(track);
|
||||
|
||||
return `
|
||||
<div class="track-item" data-track-id="${track.id}">
|
||||
|
|
@ -34,7 +35,7 @@ export class UIRenderer {
|
|||
${showCover ? `<img src="${this.api.getCoverUrl(track.album?.cover, '80')}" alt="Track Cover" class="track-item-cover" loading="lazy">` : ''}
|
||||
<div class="track-item-details">
|
||||
<div class="title">
|
||||
${track.title}
|
||||
${trackTitle}
|
||||
${explicitBadge}
|
||||
</div>
|
||||
<div class="artist">${track.artist?.name ?? 'Unknown Artist'}</div>
|
||||
|
|
@ -114,7 +115,7 @@ export class UIRenderer {
|
|||
renderListWithTracks(container, tracks, showCover) {
|
||||
const fragment = document.createDocumentFragment();
|
||||
const tempDiv = document.createElement('div');
|
||||
|
||||
|
||||
tempDiv.innerHTML = tracks.map((track, i) =>
|
||||
this.createTrackItemHTML(track, i, showCover)
|
||||
).join('');
|
||||
|
|
@ -418,4 +419,4 @@ async renderHomePage() {
|
|||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export const buildTrackFilename = (track, quality) => {
|
|||
|
||||
const artistName = sanitizeForFilename(track.artist?.name);
|
||||
const albumTitle = sanitizeForFilename(track.album?.title);
|
||||
const trackTitle = sanitizeForFilename(track.title);
|
||||
const trackTitle = sanitizeForFilename(getTrackTitle(track));
|
||||
|
||||
return `${artistName} - ${albumTitle} - ${padded} ${trackTitle}.${extension}`;
|
||||
};
|
||||
|
|
@ -155,4 +155,9 @@ export const debounce = (func, wait) => {
|
|||
clearTimeout(timeout);
|
||||
timeout = setTimeout(later, wait);
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export const getTrackTitle = (track, { fallback = 'Unknown Title' } = {}) => {
|
||||
if (!track?.title) return fallback;
|
||||
return track?.version ? `${track.title} (${track.version})` : track.title;
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue