diff --git a/app.js b/app.js index 274d2d5..c7d561c 100644 --- a/app.js +++ b/app.js @@ -481,6 +481,20 @@ async function saveEditPlaylist(){ finally{btn.disabled=false;btn.textContent='Speichern';} } +let _ndToken=null; +async function ndAuth(){ + if(_ndToken)return _ndToken; + const res=await fetch(`${cfg.url}/auth/login`,{ + method:'POST', + headers:{'Content-Type':'application/json'}, + body:JSON.stringify({username:cfg.user,password:cfg.pass}) + }); + if(!res.ok)throw new Error('Navidrome login fehlgeschlagen'); + const d=await res.json(); + _ndToken=d.token; + return _ndToken; +} + function editPlUploadCover(){document.getElementById('edit-pl-file').click()} async function editPlCoverSelected(input){ @@ -489,18 +503,20 @@ async function editPlCoverSelected(input){ const preview=URL.createObjectURL(file); document.getElementById('edit-pl-cover').innerHTML=``; try{ + const token=await ndAuth(); const form=new FormData();form.append('image',file); - const auth='Basic '+btoa(`${cfg.user}:${cfg.pass}`); - const res=await fetch(`${cfg.url}/api/playlist/${_currentPlaylist.id}/image`,{method:'POST',headers:{Authorization:auth},body:form}); + const res=await fetch(`${cfg.url}/api/playlist/${_currentPlaylist.id}/image`,{ + method:'POST',headers:{'X-Nd-Authorization':'Bearer '+token},body:form + }); if(!res.ok)throw new Error(res.status); toast('Cover aktualisiert'); - // Refresh cover in detail view setTimeout(()=>{ const cv=document.getElementById('playlist-cover'); const img=cv?.querySelector('img');if(img)img.src=img.src.split('?')[0]+'?t='+Date.now(); - },500); - }catch{ - toast('Cover-Upload nicht unterstützt (Navidrome-Version)'); + },800); + }catch(e){ + _ndToken=null; + toast('Cover-Upload fehlgeschlagen: '+e.message); document.getElementById('edit-pl-cover').innerHTML= (coverUrl(_currentPlaylist.coverArt,300) ?`` @@ -511,12 +527,16 @@ async function editPlCoverSelected(input){ async function editPlRemoveCover(){ if(!_currentPlaylist)return; try{ - const auth='Basic '+btoa(`${cfg.user}:${cfg.pass}`); - const res=await fetch(`${cfg.url}/api/playlist/${_currentPlaylist.id}/image`,{method:'DELETE',headers:{Authorization:auth}}); + const token=await ndAuth(); + const res=await fetch(`${cfg.url}/api/playlist/${_currentPlaylist.id}/image`,{ + method:'DELETE',headers:{'X-Nd-Authorization':'Bearer '+token} + }); if(!res.ok)throw new Error(res.status); toast('Cover entfernt'); + _currentPlaylist.coverArt=null; document.getElementById('edit-pl-cover').innerHTML='
🎶
'; - }catch{toast('Entfernen nicht unterstützt (Navidrome-Version)')} + document.getElementById('playlist-cover').innerHTML='
🎶
'; + }catch(e){_ndToken=null;toast('Fehler: '+e.message)} } // ─── RADIO MODE (endloser Shuffle aus der eigenen Bibliothek) ─── diff --git a/sw.js b/sw.js index 93ca1a0..e6863e2 100644 --- a/sw.js +++ b/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'ns-v31'; +const CACHE = 'ns-v32'; const PRECACHE = ['/', 'index.html', 'styles.css', 'app.js', 'manifest.json', 'icon.svg']; const SKIP_PATHS = ['/rest/stream', '/rest/download', '/config.js'];