user playlists descriptions

This commit is contained in:
Eduard Prigoana 2026-02-09 20:34:40 +00:00
parent 62b83ea9e9
commit f73c75f668
6 changed files with 58 additions and 12 deletions

View file

@ -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 &&

View file

@ -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)
</p>
<textarea
id="playlist-description-input"
class="template-input"
placeholder="Description (optional)"
style="margin: 0.5rem 0; min-height: 80px; resize: vertical"
></textarea>
<br />
<div
id="csv-import-section"

View file

@ -348,11 +348,17 @@ const syncManager = {
}
if (!finalTitle) finalTitle = 'Untitled Playlist';
let finalDescription = record.description || '';
if (!finalDescription && extraData && typeof extraData === 'object') {
finalDescription = extraData.description || '';
}
return {
...record,
id: record.uuid,
name: finalTitle,
title: finalTitle,
description: finalDescription,
cover: finalCover,
image: finalCover,
tracks: tracks,
@ -384,11 +390,13 @@ const syncManager = {
image: playlist.cover,
cover: playlist.cover,
playlist_cover: playlist.cover,
description: playlist.description || '',
tracks: JSON.stringify(playlist.tracks || []),
isPublic: true,
data: {
title: playlist.name,
cover: playlist.cover,
description: playlist.description || '',
},
};

View file

@ -649,6 +649,7 @@ document.addEventListener('DOMContentLoaded', async () => {
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');

View file

@ -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) => {

View file

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