feat: Add initial spotify widget
All checks were successful
Build Docker / BuildImage (push) Successful in 57s

This commit is contained in:
2025-10-26 20:43:48 +11:00
parent 372ba908b8
commit a8b2c02164
5 changed files with 280 additions and 2 deletions

View File

@@ -292,7 +292,161 @@ Check them out here!</blockquote><img class="img-fluid" src="/assets/img/pfront.
<div class="d-none d-print-none d-sm-none d-md-block d-lg-block d-xl-block d-xxl-block clock" style="padding: 1em;background: #10101039;border-top-right-radius: 10px;"><svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 20 20" fill="none" class="fs-2">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10 18C14.4183 18 18 14.4183 18 10C18 5.58172 14.4183 2 10 2C5.58172 2 2 5.58172 2 10C2 14.4183 5.58172 18 10 18ZM11 6C11 5.44772 10.5523 5 10 5C9.44771 5 9 5.44772 9 6V10C9 10.2652 9.10536 10.5196 9.29289 10.7071L12.1213 13.5355C12.5118 13.9261 13.145 13.9261 13.5355 13.5355C13.9261 13.145 13.9261 12.5118 13.5355 12.1213L11 9.58579V6Z" fill="currentColor"></path>
</svg><span style="margin-left: 10px;font-family: 'Anonymous Pro', monospace;">{{time|safe}}</span></div>
</svg><span style="margin-left: 10px;font-family: 'Anonymous Pro', monospace;">{{time|safe}}</span></div><!-- Pop-out button for mobile -->
<button id="spotify-toggle" style="
display: none;
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
width: 50px;
height: 50px;
border: none;
background: none;
cursor: pointer;
padding: 0;
">
<img src="/assets/img/external/spotify.png" alt="Spotify" style="
width: 100%;
height: 100%;
border-radius: 50%;
"></img>
</button>
<div id="spotify-widget" style="
position: fixed;
bottom: 20px;
right: 20px;
display: flex;
align-items: center;
background: #121212;
color: white;
padding: 10px 15px;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0,0,0,0.4);
font-family: sans-serif;
max-width: 300px;
z-index: 9999;
transition: transform 0.3s ease, opacity 0.3s ease;
opacity: 0.9;
transform: translateX(120%); /* start hidden off-screen */
">
<img id="spotify-album-art" src="" alt="Album Art" style="
width: 56px;
height: 56px;
border-radius: 6px;
margin-right: 12px;
flex-shrink: 0;
">
<div style="flex: 1; overflow: hidden;">
<div id="spotify-song" style="
font-weight: bold;
font-size: 0.95rem;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
"></div>
<div id="spotify-artist" style="
font-size: 0.85rem;
color: #ccc;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
"></div>
<div id="spotify-album" style="
font-size: 0.75rem;
color: #888;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
"></div>
</div>
</div>
<script>
const widget = document.getElementById('spotify-widget');
const toggleBtn = document.getElementById('spotify-toggle');
function isMobile() {
return window.innerWidth <= 768;
}
function updateVisibility() {
if(isMobile()){
widget.style.transform = 'translateX(120%)'; // hidden off-screen
toggleBtn.style.display = 'block';
} else {
widget.style.transform = 'translateX(0)'; // visible
toggleBtn.style.display = 'none';
}
}
// Toggle widget slide in/out on mobile
toggleBtn.addEventListener('click', (e) => {
widget.style.transform = 'translateX(0)'; // slide in
e.stopPropagation();
});
// Close widget when clicking outside
document.addEventListener('click', (e) => {
if(isMobile()){
if(!widget.contains(e.target) && e.target !== toggleBtn){
widget.style.transform = 'translateX(120%)'; // slide out
}
}
});
// Prevent clicks inside widget from closing it
widget.addEventListener('click', (e) => {
e.stopPropagation();
});
// --- Spotify fetch ---
async function updateSpotifyWidget() {
try {
const res = await fetch('/spotify/');
if (!res.ok) return;
const data = await res.json();
// Check if data contains an error or message indicating nothing is playing
if (data.error || data.message) {
widget.style.opacity = 0.5;
// If existing data
if (document.getElementById('spotify-song').textContent) {
return false;
}
// Alternate text when nothing is playing
document.getElementById('spotify-album-art').src = '/assets/img/external/spotify.png';
document.getElementById('spotify-song').textContent = 'Not Playing';
document.getElementById('spotify-artist').textContent = '';
document.getElementById('spotify-album').textContent = '';
return false;
}
const track = data.spotify;
document.getElementById('spotify-album-art').src = track.album_art;
document.getElementById('spotify-song').textContent = track.song_name;
document.getElementById('spotify-artist').textContent = track.artist;
document.getElementById('spotify-album').textContent = track.album_name;
widget.style.opacity = track.is_playing ? 0.9 : 0.5;
return true;
} catch (err) {
console.error('Failed to fetch Spotify data', err);
}
}
// Wait for Spotify API to have responded before initial display
updateSpotifyWidget().then(success => {
if(success) updateVisibility();
});
window.addEventListener('resize', updateVisibility);
setInterval(updateSpotifyWidget, 15000);
</script>
<script src="/assets/bootstrap/js/bootstrap.min.js"></script>
<script src="/assets/js/script.min.js"></script>
<script src="/assets/js/grayscale.min.js"></script>