♫ SPOTIFY CONNECT
♫
Aucune musique en coursLance un morceau sur un appareil Spotify.
Tu peux aussi dire « Dona, mets en pause », « morceau suivant » ou écrire ta demande dans le champ principal.
`;
overlay.addEventListener('click',e=>{if(e.target===overlay)toggle(false);});document.body.append(overlay);
$('donaSpotifyClose').addEventListener('click',()=>toggle(false));
overlay.querySelectorAll('[data-saction]').forEach(b=>b.addEventListener('click',()=>{
const action=b.dataset.saction==='toggle'?(state.data?.is_playing?'pause':'play'):b.dataset.saction;
send(action);
}));
$('donaSpotifySeek').addEventListener('change',e=>send('seek',{position_ms:Number(e.target.value)}));
$('donaSpotifyVolume').addEventListener('change',e=>send('volume',{volume_percent:Number(e.target.value)}));
$('donaSpotifyDevice').addEventListener('change',e=>{if(e.target.value)send('transfer',{device_id:e.target.value});});
window.addEventListener('keydown',e=>{if(e.key==='Escape'&&state.expanded)toggle(false);});
setInterval(updateBar,1000);
setInterval(()=>{if(!document.hidden)load();},12000);
document.addEventListener('visibilitychange',()=>{if(!document.hidden)load();});
load();
}
function toggle(flag){state.expanded=flag;const overlay=$('donaSpotifyOverlay');overlay.hidden=!flag;document.body.classList.toggle('dona-spotify-open',flag);if(flag)load();}
function message(txt){const m=$('donaSpotifyMessage');if(m)m.textContent=txt;}
function updateBar(){
const d=state.data;if(!d)return;
$('donaSpotifyElapsed').textContent=fmt(progress());$('donaSpotifyDuration').textContent=fmt(d.duration_ms||0);
const seek=$('donaSpotifySeek');if(document.activeElement!==seek){seek.max=Math.max(1,d.duration_ms||1);seek.value=Math.min(seek.max,progress());seek.disabled=!d.available;}
}
function redraw(){
const d=state.data;if(!d)return;
const active=Boolean(d.available);
$('donaSpotifyMini').hidden=!active;
$('donaMiniTitle').textContent=d.title||'Spotify';$('donaMiniArtist').textContent=d.artist||'';
$('donaSpotifyTitle').textContent=d.title||(d.devices?.length?'Aucune lecture active':'Aucun appareil connecté');
$('donaSpotifyArtist').textContent=d.artist||(d.devices?.length?'Choisis un appareil et lance un morceau.':'Ouvre Spotify sur un appareil.');
$('donaSpotifyAlbum').textContent=d.album||'';
const cover=$('donaSpotifyCover');cover.hidden=!d.cover;if(d.cover)cover.src=d.cover;else cover.removeAttribute('src');
$('donaSpotifyFallback').hidden=!!d.cover;
$('donaSpotifyPause').textContent=d.is_playing?icons.pause:icons.play;
$('donaSpotifyPause').setAttribute('aria-label',d.is_playing?'Mettre en pause':'Reprendre la lecture');
const select=$('donaSpotifyDevice');const chosen=select.value;
select.replaceChildren();
const option=node('option','',d.device_name||'Choisir un appareil');option.value='';select.append(option);
(d.devices||[]).forEach(x=>{const o=node('option','',x.name||x.id);o.value=x.id;select.append(o);});
select.value=(d.devices||[]).some(x=>x.id===d.device_id)?d.device_id:(chosen&&[...select.options].some(x=>x.value===chosen)?chosen:'');
select.disabled=!d.devices?.length;
const volume=$('donaSpotifyVolume');if(document.activeElement!==volume && Number.isFinite(d.volume_percent))volume.value=d.volume_percent;
$('donaSpotifyVolumeNum').textContent=Number.isFinite(d.volume_percent)?d.volume_percent+' %':'—';
updateBar();
}
async function load(){
if(state.busy)return;
state.busy=true;
try{
const r=await fetch('/api/dona/spotify/state',{cache:'no-store',credentials:'same-origin'});
const d=await r.json();if(!r.ok||!d.ok)throw Error(d.error||'Spotify non disponible');
state.data=d;state.timestamp=Date.now();state.loaded=true;redraw();message('');
}catch(e){if(state.expanded||!state.loaded)message(e.message||'Spotify indisponible');}
finally{state.busy=false;}
}
async function send(action,extra={}){
message('Commande en cours…');
try{
const r=await fetch('/api/dona/spotify/control',{method:'POST',credentials:'same-origin',headers:{'Content-Type':'application/json','X-Alfred-Request':'1'},body:JSON.stringify({action,...extra})});
const data=await r.json();if(!r.ok||!data.ok)throw Error(data.error||'Commande refusée');
message('');await new Promise(resolve=>setTimeout(resolve,450));await load();
}catch(e){message(e.message||'Commande indisponible');}
}
init();
})();