feat(web): Playlists und Favoriten als Liste in der Seitenleiste
Statt zweier Knoepfe, die erst eine Uebersichtsseite oeffnen, steht unter den Navigationsrubriken der Abschnitt "Deine Musik": angepinnt Favoriten und "Neu von deinen Kuenstlern", darunter die Playlists mit Cover und Titelzahl. Links und nicht rechts, weil rechts belegt ist: dort faehrt die Warteschlange als 290-px-Panel ein und am Rand sitzt der Rollbalken aus 3.1. Der Listenteil rollt eigenstaendig (nav ist jetzt eine Flex-Spalte), auf niedrigen Fenstern rollt als Rueckfall die ganze Leiste. Dieselbe gecachte Abfrage wie die Uebersichtsseite; nach Anlegen/Umbenennen/Loeschen wird der Cache verworfen und neu gezeichnet, ein Coverwechsel tauscht nur die betroffene Zeile (gleiche Adresse pl-<id>, sonst kaeme dasselbe Bild aus dem Browser-Cache). Die Kachel-Uebersicht bleibt per "Alle" erreichbar, die untere Leiste auf dem Handy bleibt unveraendert. Ausserdem: in 3.2 uebersehene Mischstelle nachgezogen — der Shuffle-Knopf der Playlist-Seite benutzte weiter sort(() => Math.random()-.5). Mein Suchmuster hatte nur die Schreibweise mit 0.5 erfasst, nicht die mit .5. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
7cdcc352d6
commit
9afd73ae7f
7 files changed
+139
-10
No files matched your search
+8
-1
@@ -3,7 +3,7 @@ import { esc, toast } from '../utils.js';
|
||||
import { api, coverUrl, ndAuth, invalidateApiCache } from '../api.js';
|
||||
// Circular — safe (only used inside function bodies)
|
||||
import { playQueue, dlSongLocal, nativeInsertAt, renderQueue } from '../player/player.js';
|
||||
import { navigate, loadPlaylists, loadPlaylistDetail } from '../views/views.js';
|
||||
import { navigate, loadPlaylists, loadPlaylistDetail, renderSidebarPlaylists, bustSidebarCover } from '../views/views.js';
|
||||
|
||||
// ─── CONTEXT MENU ───
|
||||
export function showCtxMenu(e, song, list, idx) {
|
||||
@@ -120,6 +120,8 @@ export async function createAndAddPlaylist() {
|
||||
const ids = S.plModalSongs.map(s => `&songId=${s.id}`).join('');
|
||||
await api('createPlaylist', `&name=${encodeURIComponent(name)}${ids}`);
|
||||
toast(`✅ Playlist "${name}" erstellt`);
|
||||
invalidateApiCache('getPlaylists'); // sonst zeigt die Seitenleiste die neue Liste 3 Min. nicht
|
||||
renderSidebarPlaylists();
|
||||
if(document.getElementById('page-playlists').classList.contains('active')) loadPlaylists();
|
||||
} catch(e) { toast('Fehler: ' + e.message); }
|
||||
}
|
||||
@@ -178,6 +180,8 @@ export async function saveEditPlaylist() {
|
||||
if(descEl) { descEl.textContent=comment; descEl.style.display=comment?'':'none'; }
|
||||
closeEditPlModal();
|
||||
toast('Playlist aktualisiert');
|
||||
invalidateApiCache('getPlaylists'); // Name/Sichtbarkeit stehen auch in der Seitenleiste
|
||||
renderSidebarPlaylists();
|
||||
} catch(e) { toast('Fehler: '+e.message); }
|
||||
finally { btn.disabled=false; btn.textContent='Speichern'; }
|
||||
}
|
||||
@@ -202,6 +206,7 @@ export async function editPlCoverSelected(input) {
|
||||
const detailImg = document.getElementById('playlist-cover');
|
||||
if(detailImg) detailImg.innerHTML = `<img src="${bust}" onerror="this.parentNode.innerHTML='<div class=\\'no-art\\'>🎶</div>'">`;
|
||||
document.getElementById('edit-pl-cover').innerHTML = `<img src="${bust}" style="width:100%;height:100%;object-fit:cover">`;
|
||||
bustSidebarCover(S._currentPlaylist.id, S._currentPlaylist.coverArt);
|
||||
}, 800);
|
||||
} catch(e) {
|
||||
S._ndToken = null;
|
||||
@@ -224,6 +229,7 @@ export async function editPlRemoveCover() {
|
||||
S._currentPlaylist.coverArt = null;
|
||||
document.getElementById('edit-pl-cover').innerHTML = '<div class="no-art" style="width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:36px">🎶</div>';
|
||||
document.getElementById('playlist-cover').innerHTML = '<div class="no-art">🎶</div>';
|
||||
bustSidebarCover(S._currentPlaylist?.id, null);
|
||||
} catch(e) { S._ndToken = null; toast('Fehler: '+e.message); }
|
||||
}
|
||||
|
||||
@@ -237,6 +243,7 @@ export async function deletePlaylist() {
|
||||
closeEditPlModal();
|
||||
toast(`🗑 "${pl.name}" gelöscht`);
|
||||
invalidateApiCache('getPlaylists'); // drop the 3-min cache so the list reloads without the deleted playlist
|
||||
renderSidebarPlaylists();
|
||||
navigate('playlists');
|
||||
} catch(e) { toast('Fehler beim Löschen: ' + e.message); }
|
||||
}
|
||||
Reference in new issue
Block a user