v1.0.0-beta.2
Release Notes — Playlist Import & On-Demand Loading
Overview
This release improves how SpinDeck imports and displays playlists from QQ Music, Kugou, and NetEase Cloud Music. Large playlists load faster and more reliably, with platform-specific strategies: full load where APIs allow it, and pagination where they do not.
✨ New Features
On-demand playlist loading
- NetEase Cloud Music playlists now load in pages (30 songs per request) instead of fetching the entire list upfront.
- The 3D shelf renders the full playlist length immediately using placeholders, while songs and covers load incrementally as you scroll.
- Scroll-based preloading fetches upcoming songs before you reach them.
Unified playlist page API (getPlaylistPage)
- New core API with consistent response shape:
songs,offset,limit,hasMore,paginated,platformPlaylistId. isPaginatedPlaylistPlatform()identifies platforms that require pagination (NetEase only).
Metadata-only refresh
- Playlists can be refreshed with
metaOnly: trueto update title, cover, and song count without reloading already-fetched songs. - Background refresh and create-playlist flows use this to avoid unnecessary full re-imports.
🚀 Improvements
QQ Music & Kugou — full load restored
- These platforms load the full playlist in a single request (up to 300 songs), matching the original fast behavior.
- Raw response caching reduces repeated parsing overhead for QQ Music.
NetEase Cloud Music — stability & rate limiting
- Primary path now uses the v6 playlist detail API (
/api/v6/playlist/detail) with 60-second page caching. - Avoids the legacy v1 API that triggered
405(“too frequent”) errors under repeated requests. - When v6 track data is incomplete, falls back to
trackIds+/api/song/detailinstead of v1. - v1 is only used as a last resort when v6 fully fails.
- User-friendly error message when rate-limited: “网易云请求过于频繁,请稍后再试”.
Album cover fixes (NetEase)
- Fixed missing album art on the 3D shelf for NetEase songs.
/api/song/detailreturnsalbum.picUrlandartists(notal/arlike v6); parser now supports both formats.- Cover URLs are normalized to HTTPS.
- When merging v6 and song/detail data, v6 cover art is preserved as a fallback.
Image proxy
/api/imagenow selects the correctRefererheader based on CDN domain:- NetEase (
126.net,163.com) →https://music.163.com/ - QQ Music →
https://y.qq.com/
- NetEase (
3D shelf (PlaylistShelf)
- Accepts
totalSongCountfor paginated playlists (shelf length independent of loaded songs). onScrollCentercallback triggers loading as the user scrolls.- Incremental spine and cover updates when new song pages arrive.
- Placeholder books shown for not-yet-loaded tracks.
🔧 API Changes
POST /api/import
- New form fields:
offset,limit,metaOnly,platformPlaylistId. - Response includes:
paginated,hasMore,songCount,platformPlaylistId. - QQ / Kugou: single full-load response (
paginated: false). - NetEase: paginated response (
paginated: true).
📦 Changed Files (summary)
| Area | Files |
|---|---|
| Core | getPlaylistPage.ts, getNeteaseMusicList.ts, getQQMusicList.ts, getKugouMusicList.ts, playlistCache.ts |
| Web API | api.import.ts, api.image.ts |
| UI | PlaylistShelf.tsx, use-playlist-fetch.ts, shelf.$playlistId.tsx, CreatePlaylistModal.tsx, use-background-refresh.ts |
🧪 Testing Checklist
- Import a large NetEase playlist — songs load page by page; shelf scrolls smoothly
- NetEase album covers appear on book spines and in playback view
- Import a QQ Music playlist — full list loads in one request; speed comparable to before
- Import a Kugou playlist — same full-load behavior
- Scroll deep into a NetEase playlist — additional pages load without 405 errors
- Background metadata refresh updates title/cover without clearing loaded songs
⚠️ Known Notes
- NetEase remains the only paginated platform; QQ and Kugou are capped at 300 songs per import.
- ESLint warnings on
PlaylistShelfuseEffectdependencies are intentional — rebuilding the full 3D scene on every page load would hurt performance.