Fix UIRenderer constructor to properly accept and assign 'player' instance

Resolved TypeError where 'this.player' was undefined in UIRenderer, preventing 'isCurrentTrack' check from working correctly. Updated constructor to accept 'player' argument passed from app.js.
This commit is contained in:
Julien Maille 2025-12-26 12:16:04 +01:00
parent 2ae6b620f2
commit 45380ea148
2 changed files with 48 additions and 48 deletions

View file

@ -175,12 +175,12 @@ function hideOfflineNotification() {
document.addEventListener('DOMContentLoaded', async () => { document.addEventListener('DOMContentLoaded', async () => {
const api = new LosslessAPI(apiSettings); const api = new LosslessAPI(apiSettings);
const ui = new UIRenderer(api);
const audioPlayer = document.getElementById('audio-player'); const audioPlayer = document.getElementById('audio-player');
const currentQuality = localStorage.getItem('playback-quality') || 'LOSSLESS'; const currentQuality = localStorage.getItem('playback-quality') || 'LOSSLESS';
const player = new Player(audioPlayer, api, currentQuality); const player = new Player(audioPlayer, api, currentQuality);
const ui = new UIRenderer(api, player);
const scrobbler = new LastFMScrobbler(); const scrobbler = new LastFMScrobbler();
const lyricsManager = new LyricsManager(api); const lyricsManager = new LyricsManager(api);
const lyricsPanel = createLyricsPanel(); const lyricsPanel = createLyricsPanel();

View file

@ -3,8 +3,9 @@ import { SVG_PLAY, SVG_DOWNLOAD, SVG_MENU, formatTime, createPlaceholder, trackD
import { recentActivityManager, backgroundSettings, trackListSettings } from './storage.js'; import { recentActivityManager, backgroundSettings, trackListSettings } from './storage.js';
export class UIRenderer { export class UIRenderer {
constructor(api) { constructor(api, player) {
this.api = api; this.api = api;
this.player = player;
this.currentTrack = null; this.currentTrack = null;
this.searchAbortController = null; this.searchAbortController = null;
} }
@ -72,6 +73,7 @@ export class UIRenderer {
const explicitBadge = hasExplicitContent(track) ? this.createExplicitBadge() : ''; const explicitBadge = hasExplicitContent(track) ? this.createExplicitBadge() : '';
const trackArtists = getTrackArtists(track); const trackArtists = getTrackArtists(track);
const trackTitle = getTrackTitle(track); const trackTitle = getTrackTitle(track);
const isCurrentTrack = this.player?.currentTrack?.id === track.id;
let yearDisplay = ''; let yearDisplay = '';
const releaseDate = track.album?.releaseDate || track.streamStartDate; const releaseDate = track.album?.releaseDate || track.streamStartDate;
@ -112,7 +114,7 @@ export class UIRenderer {
`; `;
return ` return `
<div class="track-item" data-track-id="${track.id}"> <div class="track-item ${isCurrentTrack ? 'playing' : ''}" data-track-id="${track.id}">
${trackNumberHTML} ${trackNumberHTML}
<div class="track-item-info"> <div class="track-item-info">
<div class="track-item-details"> <div class="track-item-details">
@ -627,67 +629,65 @@ export class UIRenderer {
} }
} }
async renderPlaylistPage(playlistId) { async renderPlaylistPage(playlistId) {
this.showPage('playlist'); this.showPage('playlist');
const imageEl = document.getElementById('playlist-detail-image'); const imageEl = document.getElementById('playlist-detail-image');
const titleEl = document.getElementById('playlist-detail-title'); const titleEl = document.getElementById('playlist-detail-title');
const metaEl = document.getElementById('playlist-detail-meta'); const metaEl = document.getElementById('playlist-detail-meta');
const descEl = document.getElementById('playlist-detail-description'); const descEl = document.getElementById('playlist-detail-description');
const tracklistContainer = document.getElementById('playlist-detail-tracklist'); const tracklistContainer = document.getElementById('playlist-detail-tracklist');
const playBtn = document.getElementById('play-playlist-btn'); const playBtn = document.getElementById('play-playlist-btn');
if (playBtn) playBtn.innerHTML = `${SVG_PLAY}<span>Play</span>`; if (playBtn) playBtn.innerHTML = `${SVG_PLAY}<span>Play</span>`;
const dlBtn = document.getElementById('download-playlist-btn'); const dlBtn = document.getElementById('download-playlist-btn');
if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD}<span>Download</span>`; if (dlBtn) dlBtn.innerHTML = `${SVG_DOWNLOAD}<span>Download</span>`;
imageEl.src = ''; imageEl.src = '';
imageEl.style.backgroundColor = 'var(--muted)'; imageEl.style.backgroundColor = 'var(--muted)';
titleEl.innerHTML = '<div class="skeleton" style="height: 48px; width: 300px; max-width: 90%;"></div>'; titleEl.innerHTML = '<div class="skeleton" style="height: 48px; width: 300px; max-width: 90%;"></div>';
metaEl.innerHTML = '<div class="skeleton" style="height: 16px; width: 200px; max-width: 80%;"></div>'; metaEl.innerHTML = '<div class="skeleton" style="height: 16px; width: 200px; max-width: 80%;"></div>';
descEl.innerHTML = '<div class="skeleton" style="height: 16px; width: 100%;"></div>'; descEl.innerHTML = '<div class="skeleton" style="height: 16px; width: 100%;"></div>';
tracklistContainer.innerHTML = `
<div class="track-list-header">
<span style="width: 40px; text-align: center;">#</span>
<span>Title</span>
<span class="duration-header">Duration</span>
</div>
${this.createSkeletonTracks(10, true)}
`;
try {
const { playlist, tracks } = await this.api.getPlaylist(playlistId);
const imageId = playlist.squareImage || playlist.image;
imageEl.src = this.api.getCoverUrl(imageId, '1080');
imageEl.style.backgroundColor = '';
titleEl.textContent = playlist.title;
this.adjustTitleFontSize(titleEl, playlist.title);
const totalDuration = calculateTotalDuration(tracks);
metaEl.textContent = `${playlist.numberOfTracks} tracks • ${formatDuration(totalDuration)}`;
descEl.textContent = playlist.description || '';
tracklistContainer.innerHTML = ` tracklistContainer.innerHTML = `
<div class="track-list-header"> <div class="track-list-header">
<span style="width: 40px; text-align: center;">#</span> <span style="width: 40px; text-align: center;">#</span>
<span>Title</span> <span>Title</span>
<span class="duration-header">Duration</span> <span class="duration-header">Duration</span>
</div> </div>
${this.createSkeletonTracks(10, true)}
`; `;
this.renderListWithTracks(tracklistContainer, tracks, true); try {
const { playlist, tracks } = await this.api.getPlaylist(playlistId);
recentActivityManager.addPlaylist(playlist);
const imageId = playlist.squareImage || playlist.image;
document.title = `${playlist.title || 'Artist Mix'} - Monochrome`; } catch (error) { imageEl.src = this.api.getCoverUrl(imageId, '1080');
console.error("Failed to load playlist:", error); imageEl.style.backgroundColor = '';
tracklistContainer.innerHTML = createPlaceholder(`Could not load playlist details. ${error.message}`);
titleEl.textContent = playlist.title;
this.adjustTitleFontSize(titleEl, playlist.title);
const totalDuration = calculateTotalDuration(tracks);
metaEl.textContent = `${playlist.numberOfTracks} tracks • ${formatDuration(totalDuration)}`;
descEl.textContent = playlist.description || '';
tracklistContainer.innerHTML = `
<div class="track-list-header">
<span style="width: 40px; text-align: center;">#</span>
<span>Title</span>
<span class="duration-header">Duration</span>
</div>
`;
this.renderListWithTracks(tracklistContainer, tracks, true);
recentActivityManager.addPlaylist(playlist);
document.title = `${playlist.title || 'Artist Mix'} - Monochrome`;
} catch (error) {
console.error("Failed to load playlist:", error);
tracklistContainer.innerHTML = createPlaceholder(`Could not load playlist details. ${error.message}`);
}
} }
}
async renderArtistPage(artistId) { async renderArtistPage(artistId) {
this.showPage('artist'); this.showPage('artist');