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';