web-player: use playlist totals from the API, cache genres and parallelize explore requests
This commit is contained in:
Vendored
+4
@@ -942,6 +942,10 @@ export interface components {
|
||||
largeImageKeyName: null | string;
|
||||
ownerUserId: string;
|
||||
visibility: components["schemas"]["PlaylistVisibility"];
|
||||
/** Format: int32 */
|
||||
trackCount: number | string;
|
||||
/** Format: double */
|
||||
durationSeconds: number | string;
|
||||
/** Format: date-time */
|
||||
createdAt: string;
|
||||
/** Format: date-time */
|
||||
|
||||
@@ -9,9 +9,7 @@ export const PLAYLIST_TRACKS_PAGE_SIZE = 200;
|
||||
export const LIBRARY_PICKER_PAGE_SIZE = 50;
|
||||
export const LIBRARY_PAGE_SIZE = 50;
|
||||
export const PLAYLISTS_PAGE_SIZE = 50;
|
||||
export const PLAYLIST_SUMMARY_TRACKS_PAGE_SIZE = 500;
|
||||
export const PROFILE_PLAYLISTS_PAGE_SIZE = 50;
|
||||
export const COUNT_ONLY_PAGE_SIZE = 1;
|
||||
export const EXPLORE_ALBUMS_PAGE_SIZE = 10;
|
||||
export const EXPLORE_ALBUMS_LIMIT = 18;
|
||||
export const HOME_MIXES_LIMIT = 6;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import type { ApiClient } from '$lib/server/api';
|
||||
import type { components } from '$lib/api/schema';
|
||||
|
||||
type GenreInfo = components['schemas']['GenreResponse'];
|
||||
|
||||
const CACHE_TTL_MS = 5 * 60_000;
|
||||
|
||||
let cached: { genres: GenreInfo[]; expiresAt: number } | null = null;
|
||||
|
||||
export async function getGenres(api: ApiClient): Promise<GenreInfo[]> {
|
||||
if (cached && cached.expiresAt > Date.now()) return cached.genres;
|
||||
|
||||
const { data } = await api.GET('/genres');
|
||||
if (!data) return cached?.genres ?? [];
|
||||
|
||||
cached = { genres: data, expiresAt: Date.now() + CACHE_TTL_MS };
|
||||
return data;
|
||||
}
|
||||
@@ -1,15 +1,6 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { components } from '$lib/api/schema';
|
||||
import {
|
||||
toAlbum,
|
||||
toDatedTrack,
|
||||
toLikedTrack,
|
||||
toMix,
|
||||
toPage,
|
||||
toPlaylist,
|
||||
toPlaylistSummary,
|
||||
toTrack
|
||||
} from './mappers';
|
||||
import { toAlbum, toDatedTrack, toLikedTrack, toMix, toPage, toPlaylist, toTrack } from './mappers';
|
||||
|
||||
const trackDto: components['schemas']['TrackApplicationResponse'] = {
|
||||
id: 't1',
|
||||
@@ -107,24 +98,25 @@ describe('toPlaylist', () => {
|
||||
largeImageKeyName: null,
|
||||
ownerUserId: '42',
|
||||
visibility: 'Public',
|
||||
trackCount: '7',
|
||||
durationSeconds: '90.5',
|
||||
createdAt: '',
|
||||
updatedAt: 'u',
|
||||
coverTrackIds: []
|
||||
};
|
||||
it('drops storage keys', () => {
|
||||
it('drops storage keys and normalizes totals', () => {
|
||||
expect(toPlaylist(dto)).toEqual({
|
||||
id: 'p1',
|
||||
name: 'List',
|
||||
description: 'd',
|
||||
visibility: 'Public',
|
||||
ownerUserId: '42',
|
||||
trackCount: 7,
|
||||
durationSeconds: 90.5,
|
||||
coverTrackIds: [],
|
||||
updatedAt: 'u'
|
||||
});
|
||||
});
|
||||
it('adds the track count in summaries', () => {
|
||||
expect(toPlaylistSummary(dto, 7).trackCount).toBe(7);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toPage', () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { components } from '$lib/api/schema';
|
||||
import type { Album, LikedTrack, Mix, Paged, Playlist, PlaylistSummary, Track } from '$lib/types';
|
||||
import type { Album, LikedTrack, Mix, Paged, Playlist, Track } from '$lib/types';
|
||||
|
||||
type TrackDto = components['schemas']['TrackApplicationResponse'];
|
||||
type AlbumDto = components['schemas']['AlbumApplicationResponse'];
|
||||
@@ -75,15 +75,13 @@ export function toPlaylist(dto: PlaylistDto): Playlist {
|
||||
description: dto.description,
|
||||
visibility: dto.visibility,
|
||||
ownerUserId: dto.ownerUserId,
|
||||
trackCount: Number(dto.trackCount) || 0,
|
||||
durationSeconds: Number(dto.durationSeconds) || 0,
|
||||
coverTrackIds: dto.coverTrackIds,
|
||||
updatedAt: dto.updatedAt
|
||||
};
|
||||
}
|
||||
|
||||
export function toPlaylistSummary(dto: PlaylistDto, trackCount: number): PlaylistSummary {
|
||||
return { ...toPlaylist(dto), trackCount };
|
||||
}
|
||||
|
||||
export function toPage<D, T>(dto: PageDto<D>, map: (item: D) => T): Paged<T> {
|
||||
return {
|
||||
items: dto.items.map(map),
|
||||
|
||||
@@ -38,14 +38,12 @@ export interface Playlist {
|
||||
description: string | null;
|
||||
visibility: 'Public' | 'Private';
|
||||
ownerUserId: string;
|
||||
trackCount: number;
|
||||
durationSeconds: number;
|
||||
coverTrackIds: string[];
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface PlaylistSummary extends Playlist {
|
||||
trackCount: number;
|
||||
}
|
||||
|
||||
export interface Mix {
|
||||
id: string;
|
||||
title: string;
|
||||
|
||||
Reference in New Issue
Block a user