feat(playlists): track custom order in separate 'order' array; reading API honors 'order' while preserving 'tracks'

This commit is contained in:
Geert Rademakes 2025-08-08 14:25:50 +02:00
parent 5a396d774e
commit 61d4ca16de
3 changed files with 13 additions and 9 deletions

View File

@ -9,6 +9,8 @@ const playlistSchema = new mongoose.Schema({
required: true
},
tracks: [String],
// Optional custom order of track IDs (display-only, not exported)
order: [String],
children: [{
type: mongoose.Schema.Types.Mixed
}]

View File

@ -80,7 +80,7 @@ router.post('/batch', async (req, res) => {
}
});
// Reorder tracks inside a playlist (by name)
// Reorder tracks inside a playlist (by name). Stores order separately in `order` to avoid interfering with original `tracks`.
router.post('/reorder', async (req: Request, res: Response) => {
try {
const { playlistName, orderedIds } = req.body as { playlistName: string; orderedIds: string[] };
@ -94,13 +94,9 @@ router.post('/reorder', async (req: Request, res: Response) => {
const reorderNode = (node: any): any => {
if (!node) return node;
if (node.type === 'playlist' && node.name === playlistName) {
// Ensure unique order and only include known IDs
// Store order separately; do not mutate tracks
const unique = Array.from(new Set(orderedIds));
// If tracks exist, keep only ids present in unique, and append any tracks not included to preserve membership
const current: string[] = Array.isArray(node.tracks) ? node.tracks : [];
const orderedKnown = unique.filter(id => current.includes(id));
const missing = current.filter(id => !unique.includes(id));
node.tracks = [...orderedKnown, ...missing];
node.order = unique;
updated = true;
return node;
}

View File

@ -110,8 +110,14 @@ router.get('/playlist/*', async (req: Request, res: Response) => {
// Get all track IDs from the playlist (including nested playlists)
const getAllTrackIds = (node: any): string[] => {
if (node.type === 'playlist' && node.tracks) {
return node.tracks;
if (node.type === 'playlist') {
const base = Array.isArray(node.tracks) ? node.tracks : [];
const order = Array.isArray(node.order) ? node.order : [];
if (order.length === 0) return base;
const setBase = new Set(base);
const orderedKnown = order.filter((id: string) => setBase.has(id));
const missing = base.filter((id: string) => !order.includes(id));
return [...orderedKnown, ...missing];
}
if (node.type === 'folder' && node.children) {
return node.children.flatMap((child: any) => getAllTrackIds(child));