fix: prevent home page double refresh and improve artist name extraction in album cards

This commit is contained in:
Julien Maille 2026-02-21 14:16:30 +01:00
parent b62f4144ac
commit acf64cbc17
2 changed files with 92 additions and 62 deletions

View file

@ -330,6 +330,17 @@ export class QobuzAPI {
} }
} }
// Similar/recommendation methods
async getSimilarArtists(artistId) {
// Qobuz doesn't have a direct similar artists endpoint in this simplified API
return [];
}
async getSimilarAlbums(albumId) {
// Qobuz doesn't have a direct similar albums endpoint in this simplified API
return [];
}
// Unified search - search all types at once // Unified search - search all types at once
async search(query, options = {}) { async search(query, options = {}) {
const offset = options.offset || 0; const offset = options.offset || 0;

View file

@ -91,6 +91,7 @@ export class UIRenderer {
this.searchAbortController = null; this.searchAbortController = null;
this.vibrantColorCache = new Map(); this.vibrantColorCache = new Map();
this.visualizer = null; this.visualizer = null;
this.renderLock = false;
// Listen for dynamic color reset events // Listen for dynamic color reset events
window.addEventListener('reset-dynamic-color', () => { window.addEventListener('reset-dynamic-color', () => {
@ -575,13 +576,19 @@ export class UIRenderer {
else if (album.type === 'SINGLE') typeLabel = ' • Single'; else if (album.type === 'SINGLE') typeLabel = ' • Single';
const isCompact = cardSettings.isCompactAlbum(); const isCompact = cardSettings.isCompactAlbum();
let artistName = '';
if (album.artist) {
artistName = typeof album.artist === 'string' ? album.artist : album.artist.name;
} else if (album.artists?.length) {
artistName = album.artists.map((a) => a.name).join(', ');
}
return this.createBaseCardHTML({ return this.createBaseCardHTML({
type: 'album', type: 'album',
id: album.id, id: album.id,
href: `/album/${album.id}`, href: `/album/${album.id}`,
title: `${escapeHtml(album.title)} ${explicitBadge} ${qualityBadge}`, title: `${escapeHtml(album.title)} ${explicitBadge} ${qualityBadge}`,
subtitle: `${escapeHtml(album.artist?.name ?? '')}${yearDisplay}${typeLabel}`, subtitle: `${escapeHtml(artistName)}${yearDisplay}${typeLabel}`,
imageHTML: `<img src="${this.api.getCoverUrl(album.cover)}" alt="${escapeHtml(album.title)}" class="card-image" loading="lazy">`, imageHTML: `<img src="${this.api.getCoverUrl(album.cover)}" alt="${escapeHtml(album.title)}" class="card-image" loading="lazy">`,
actionButtonsHTML: ` actionButtonsHTML: `
<button class="like-btn card-like-btn" data-action="toggle-like" data-type="album" title="Add to Liked"> <button class="like-btn card-like-btn" data-action="toggle-like" data-type="album" title="Add to Liked">
@ -1464,6 +1471,10 @@ export class UIRenderer {
} }
async renderHomePage() { async renderHomePage() {
if (this.renderLock) return;
this.renderLock = true;
try {
this.showPage('home'); this.showPage('home');
const welcomeEl = document.getElementById('home-welcome'); const welcomeEl = document.getElementById('home-welcome');
@ -1520,10 +1531,18 @@ export class UIRenderer {
} }
}; };
this.renderHomeSongs();
this.renderHomeAlbums();
this.renderHomeArtists();
this.renderHomeRecent(); this.renderHomeRecent();
// Load dynamic sections in parallel with pre-fetched seeds
const seeds = await this.getSeeds();
await Promise.all([
this.renderHomeSongs(false, seeds),
this.renderHomeAlbums(false, seeds),
this.renderHomeArtists(false, seeds),
]);
} finally {
this.renderLock = false;
}
} }
async getSeeds() { async getSeeds() {
@ -1545,7 +1564,7 @@ export class UIRenderer {
return shuffle(seeds); return shuffle(seeds);
} }
async renderHomeSongs(forceRefresh = false) { async renderHomeSongs(forceRefresh = false, providedSeeds = null) {
const songsContainer = document.getElementById('home-recommended-songs'); const songsContainer = document.getElementById('home-recommended-songs');
const section = songsContainer?.closest('.content-section'); const section = songsContainer?.closest('.content-section');
@ -1564,7 +1583,7 @@ export class UIRenderer {
} }
try { try {
const seeds = await this.getSeeds(); const seeds = providedSeeds || (await this.getSeeds());
const trackSeeds = seeds.slice(0, 5); const trackSeeds = seeds.slice(0, 5);
const recommendedTracks = await this.api.getRecommendedTracksForPlaylist(trackSeeds, 20, { const recommendedTracks = await this.api.getRecommendedTracksForPlaylist(trackSeeds, 20, {
skipCache: forceRefresh, skipCache: forceRefresh,
@ -1584,7 +1603,7 @@ export class UIRenderer {
} }
} }
async renderHomeAlbums(forceRefresh = false) { async renderHomeAlbums(forceRefresh = false, providedSeeds = null) {
const albumsContainer = document.getElementById('home-recommended-albums'); const albumsContainer = document.getElementById('home-recommended-albums');
const section = albumsContainer?.closest('.content-section'); const section = albumsContainer?.closest('.content-section');
@ -1603,7 +1622,7 @@ export class UIRenderer {
} }
try { try {
const seeds = await this.getSeeds(); const seeds = providedSeeds || (await this.getSeeds());
const albumSeed = seeds.find((t) => t.album && t.album.id); const albumSeed = seeds.find((t) => t.album && t.album.id);
if (albumSeed) { if (albumSeed) {
const similarAlbums = await this.api.getSimilarAlbums(albumSeed.album.id); const similarAlbums = await this.api.getSimilarAlbums(albumSeed.album.id);
@ -1790,7 +1809,7 @@ export class UIRenderer {
} }
} }
async renderHomeArtists(forceRefresh = false) { async renderHomeArtists(forceRefresh = false, providedSeeds = null) {
const artistsContainer = document.getElementById('home-recommended-artists'); const artistsContainer = document.getElementById('home-recommended-artists');
const section = artistsContainer?.closest('.content-section'); const section = artistsContainer?.closest('.content-section');
@ -1809,7 +1828,7 @@ export class UIRenderer {
} }
try { try {
const seeds = await this.getSeeds(); const seeds = providedSeeds || (await this.getSeeds());
const artistSeed = seeds.find((t) => (t.artist && t.artist.id) || (t.artists && t.artists.length > 0)); const artistSeed = seeds.find((t) => (t.artist && t.artist.id) || (t.artists && t.artists.length > 0));
const artistId = artistSeed ? artistSeed.artist?.id || artistSeed.artists?.[0]?.id : null; const artistId = artistSeed ? artistSeed.artist?.id || artistSeed.artists?.[0]?.id : null;