load skeleton styling
This commit is contained in:
parent
b531d31dc1
commit
762488d823
4 changed files with 22 additions and 12 deletions
10
js/api.js
10
js/api.js
|
|
@ -675,8 +675,10 @@ export class LosslessAPI {
|
||||||
|
|
||||||
async getArtist(artistId, options = {}) {
|
async getArtist(artistId, options = {}) {
|
||||||
const cacheKey = options.lightweight ? `artist_${artistId}_light` : `artist_${artistId}`;
|
const cacheKey = options.lightweight ? `artist_${artistId}_light` : `artist_${artistId}`;
|
||||||
const cached = await this.cache.get('artist', cacheKey);
|
if (!options.skipCache) {
|
||||||
if (cached) return cached;
|
const cached = await this.cache.get('artist', cacheKey);
|
||||||
|
if (cached) return cached;
|
||||||
|
}
|
||||||
|
|
||||||
const [primaryResponse, contentResponse] = await Promise.all([
|
const [primaryResponse, contentResponse] = await Promise.all([
|
||||||
this.fetchWithRetry(`/artist/?id=${artistId}`),
|
this.fetchWithRetry(`/artist/?id=${artistId}`),
|
||||||
|
|
@ -811,7 +813,7 @@ export class LosslessAPI {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecommendedTracksForPlaylist(tracks, limit = 20) {
|
async getRecommendedTracksForPlaylist(tracks, limit = 20, options = {}) {
|
||||||
const artistMap = new Map();
|
const artistMap = new Map();
|
||||||
|
|
||||||
// Check if tracks already have artist info (some might)
|
// Check if tracks already have artist info (some might)
|
||||||
|
|
@ -872,7 +874,7 @@ export class LosslessAPI {
|
||||||
const artistPromises = artistsToProcess.map(async (artist) => {
|
const artistPromises = artistsToProcess.map(async (artist) => {
|
||||||
try {
|
try {
|
||||||
console.log(`Fetching tracks for artist: ${artist.name} (ID: ${artist.id})`);
|
console.log(`Fetching tracks for artist: ${artist.name} (ID: ${artist.id})`);
|
||||||
const artistData = await this.getArtist(artist.id, { lightweight: true });
|
const artistData = await this.getArtist(artist.id, { lightweight: true, skipCache: options.skipCache });
|
||||||
if (artistData && artistData.tracks && artistData.tracks.length > 0) {
|
if (artistData && artistData.tracks && artistData.tracks.length > 0) {
|
||||||
const newTracks = artistData.tracks.filter((track) => !seenTrackIds.has(track.id)).slice(0, 4);
|
const newTracks = artistData.tracks.filter((track) => !seenTrackIds.has(track.id)).slice(0, 4);
|
||||||
return newTracks;
|
return newTracks;
|
||||||
|
|
|
||||||
|
|
@ -154,9 +154,9 @@ export class MusicAPI {
|
||||||
return api.getSimilarAlbums(cleanId);
|
return api.getSimilarAlbums(cleanId);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getRecommendedTracksForPlaylist(tracks, limit = 20) {
|
async getRecommendedTracksForPlaylist(tracks, limit = 20, options = {}) {
|
||||||
// Use Tidal for recommendations
|
// Use Tidal for recommendations
|
||||||
return this.tidalAPI.getRecommendedTracksForPlaylist(tracks, limit);
|
return this.tidalAPI.getRecommendedTracksForPlaylist(tracks, limit, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cache methods
|
// Cache methods
|
||||||
|
|
|
||||||
9
js/ui.js
9
js/ui.js
|
|
@ -624,6 +624,7 @@ export class UIRenderer {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="skeleton skeleton-track-duration"></div>
|
<div class="skeleton skeleton-track-duration"></div>
|
||||||
|
<div class="skeleton skeleton-track-actions"></div>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
@ -639,10 +640,10 @@ export class UIRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
createSkeletonTracks(count = 5, showCover = false) {
|
createSkeletonTracks(count = 5, showCover = false) {
|
||||||
return `<div class="skeleton-container">${Array(count)
|
return Array(count)
|
||||||
.fill(0)
|
.fill(0)
|
||||||
.map(() => this.createSkeletonTrack(showCover))
|
.map(() => this.createSkeletonTrack(showCover))
|
||||||
.join('')}</div>`;
|
.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
createSkeletonCards(count = 6, isArtist = false) {
|
createSkeletonCards(count = 6, isArtist = false) {
|
||||||
|
|
@ -1560,7 +1561,9 @@ export class UIRenderer {
|
||||||
try {
|
try {
|
||||||
const seeds = await this.getSeeds();
|
const seeds = 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,
|
||||||
|
});
|
||||||
|
|
||||||
const filteredTracks = await this.filterUserContent(recommendedTracks, 'track');
|
const filteredTracks = await this.filterUserContent(recommendedTracks, 'track');
|
||||||
|
|
||||||
|
|
|
||||||
11
styles.css
11
styles.css
|
|
@ -3289,11 +3289,10 @@ input:checked + .slider::before {
|
||||||
|
|
||||||
.skeleton-track {
|
.skeleton-track {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 40px 1fr 80px 48px;
|
grid-template-columns: 40px 1fr 60px 40px;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--spacing-md);
|
gap: var(--spacing-md);
|
||||||
padding: var(--spacing-sm);
|
padding: var(--spacing-sm) var(--spacing-md);
|
||||||
margin-bottom: 2px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.skeleton-track-number {
|
.skeleton-track-number {
|
||||||
|
|
@ -3341,6 +3340,12 @@ input:checked + .slider::before {
|
||||||
height: 14px;
|
height: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.skeleton-track-actions {
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
justify-self: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
.skeleton-card {
|
.skeleton-card {
|
||||||
background-color: var(--card);
|
background-color: var(--card);
|
||||||
border-radius: var(--radius);
|
border-radius: var(--radius);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue