diff --git a/functions/userplaylist/[id].js b/functions/userplaylist/[id].js index 51a5fa1..c291584 100644 --- a/functions/userplaylist/[id].js +++ b/functions/userplaylist/[id].js @@ -12,23 +12,31 @@ export async function onRequest(context) { if (isBot && playlistId) { try { - let pbUrl = `https://monodb.samidy.com/api/collections/user_playlists/records/${playlistId}`; + // Try public_playlists collection first (for shared playlists) + let pbUrl = `https://monodb.samidy.com/api/collections/public_playlists/records?filter=(uuid='${playlistId}')`; let response = await fetch(pbUrl); + // Fall back to user_playlists for private/owned playlists if (!response.ok) { - pbUrl = `https://monodb.samidy.com/api/collections/public_playlists/records?filter=(uuid='${playlistId}')`; + pbUrl = `https://monodb.samidy.com/api/collections/user_playlists/records/${playlistId}`; response = await fetch(pbUrl); } if (response.ok) { let playlist = await response.json(); - if (playlist.items && Array.isArray(playlist.items) && playlist.items.length > 0) { - playlist = playlist.items[0]; + + // Handle public_playlists response (returns { items: [...] }) + if (playlist.items && Array.isArray(playlist.items)) { + if (playlist.items.length > 0) { + playlist = playlist.items[0]; + } else { + throw new Error('Playlist not found'); + } } if (!playlist) throw new Error('Playlist not found'); - const title = playlist.name || playlist.title || 'User Playlist'; + const title = playlist.name || playlist.title || playlist.playlist_name || 'User Playlist'; let tracks = []; try { tracks = Array.isArray(playlist.tracks) @@ -41,14 +49,18 @@ export async function onRequest(context) { } const trackCount = tracks.length; - const description = `User Playlist • ${trackCount} Tracks\nListen on Monochrome`; + const playlistDescription = playlist.description || ''; + const description = playlistDescription + ? `${playlistDescription}\n${trackCount} Tracks • Listen on Monochrome` + : `User Playlist • ${trackCount} Tracks\nListen on Monochrome`; let imageUrl = 'https://monochrome.samidy.com/assets/appicon.png'; - if (playlist.cover) { - if (playlist.cover.startsWith('http')) { - imageUrl = playlist.cover; + const coverUrl = playlist.cover || playlist.image || playlist.playlist_cover || ''; + if (coverUrl) { + if (coverUrl.startsWith('http')) { + imageUrl = coverUrl; } else { - imageUrl = `https://monodb.samidy.com/api/files/${playlist.collectionId}/${playlist.id}/${playlist.cover}`; + imageUrl = `https://monodb.samidy.com/api/files/${playlist.collectionId}/${playlist.id}/${coverUrl}`; } } else if ( tracks.length > 0 && diff --git a/index.html b/index.html index 70e9857..38a1f7c 100644 --- a/index.html +++ b/index.html @@ -352,6 +352,12 @@ here. (or any other service that allows directly linking to a file, but we recommend catbox due to their long-term storage of your files)

+
{ document.getElementById('playlist-modal-title').textContent = 'Create Playlist'; document.getElementById('playlist-name-input').value = ''; document.getElementById('playlist-cover-input').value = ''; + document.getElementById('playlist-description-input').value = ''; modal.dataset.editingId = ''; document.getElementById('csv-import-section').style.display = 'block'; document.getElementById('csv-file-input').value = ''; @@ -696,6 +697,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (e.target.closest('#playlist-modal-save')) { const name = document.getElementById('playlist-name-input').value.trim(); + const description = document.getElementById('playlist-description-input').value.trim(); const isPublic = document.getElementById('playlist-public-toggle')?.checked; if (name) { @@ -728,6 +730,7 @@ document.addEventListener('DOMContentLoaded', async () => { if (playlist) { playlist.name = name; playlist.cover = cover; + playlist.description = description; await handlePublicStatus(playlist); await db.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist)); syncManager.syncUserPlaylist(playlist, 'update'); @@ -817,7 +820,7 @@ document.addEventListener('DOMContentLoaded', async () => { console.log(`Added ${tracks.length} tracks (including pending)`); } - db.createPlaylist(name, tracks, cover).then(async (playlist) => { + db.createPlaylist(name, tracks, cover, description).then(async (playlist) => { await handlePublicStatus(playlist); // Update DB again with isPublic flag await db.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist)); @@ -842,6 +845,7 @@ document.addEventListener('DOMContentLoaded', async () => { document.getElementById('playlist-modal-title').textContent = 'Edit Playlist'; document.getElementById('playlist-name-input').value = playlist.name; document.getElementById('playlist-cover-input').value = playlist.cover || ''; + document.getElementById('playlist-description-input').value = playlist.description || ''; // Set Public Toggle const publicToggle = document.getElementById('playlist-public-toggle'); @@ -886,6 +890,7 @@ document.addEventListener('DOMContentLoaded', async () => { document.getElementById('playlist-modal-title').textContent = 'Edit Playlist'; document.getElementById('playlist-name-input').value = playlist.name; document.getElementById('playlist-cover-input').value = playlist.cover || ''; + document.getElementById('playlist-description-input').value = playlist.description || ''; const publicToggle = document.getElementById('playlist-public-toggle'); const shareBtn = document.getElementById('playlist-share-btn'); diff --git a/js/db.js b/js/db.js index 50d55d4..79466d7 100644 --- a/js/db.js +++ b/js/db.js @@ -466,13 +466,14 @@ export class MusicDatabase { } // User Playlists API - async createPlaylist(name, tracks = [], cover = '') { + async createPlaylist(name, tracks = [], cover = '', description = '') { const id = crypto.randomUUID(); const playlist = { id: id, name: name, tracks: tracks.map((t) => this._minifyItem('track', { ...t, addedAt: Date.now() })), cover: cover, + description: description, createdAt: Date.now(), updatedAt: Date.now(), numberOfTracks: tracks.length, @@ -667,6 +668,18 @@ export class MusicDatabase { return playlist; } + async updatePlaylistDescription(playlistId, newDescription) { + const playlist = await this.performTransaction('user_playlists', 'readonly', (store) => store.get(playlistId)); + if (!playlist) throw new Error('Playlist not found'); + playlist.description = newDescription; + playlist.updatedAt = Date.now(); + await this.performTransaction('user_playlists', 'readwrite', (store) => store.put(playlist)); + + this._dispatchPlaylistSync('update', playlist); + + return playlist; + } + async updatePlaylistTracks(playlistId, tracks) { const db = await this.open(); return new Promise((resolve, reject) => { diff --git a/js/events.js b/js/events.js index cbccdee..0a87f00 100644 --- a/js/events.js +++ b/js/events.js @@ -649,6 +649,7 @@ export async function showAddToPlaylistModal(track) { document.getElementById('playlist-modal-title').textContent = 'Create Playlist'; document.getElementById('playlist-name-input').value = ''; document.getElementById('playlist-cover-input').value = ''; + document.getElementById('playlist-description-input').value = ''; createModal.dataset.editingId = ''; document.getElementById('csv-import-section').style.display = 'none'; @@ -1005,6 +1006,7 @@ export async function handleTrackAction( document.getElementById('playlist-modal-title').textContent = 'Create Playlist'; document.getElementById('playlist-name-input').value = ''; document.getElementById('playlist-cover-input').value = ''; + document.getElementById('playlist-description-input').value = ''; createModal.dataset.editingId = ''; document.getElementById('csv-import-section').style.display = 'none';