the home site for me: also iteration 3 or 4 of my site
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: poll the music

+46 -10
+15
sass/css/mods.css
··· 13 13 #now-playing:not(:empty) { 14 14 font-size: 0.85rem; 15 15 color: var(--text-light); 16 + display: flex; 17 + align-items: center; 18 + max-width: 50vw; 19 + } 20 + 21 + #now-playing .track-name { 22 + overflow: hidden; 23 + text-overflow: ellipsis; 24 + white-space: nowrap; 25 + min-width: 0; 26 + } 27 + 28 + #now-playing .artist-name { 29 + white-space: nowrap; 30 + flex-shrink: 0; 16 31 } 17 32 18 33 #now-playing a {
+23 -7
templates/header.html
··· 20 20 </nav> 21 21 </div> 22 22 <script> 23 - document.addEventListener("DOMContentLoaded", () => { 23 + let nowPlayingTimeout = null; 24 + function fetchNowPlaying() { 25 + if (nowPlayingTimeout) clearTimeout(nowPlayingTimeout); 24 26 fetch("https://bsky.social/xrpc/com.atproto.repo.getRecord?repo=did:plc:krxbvxvis5skq7jj6eot23ul&collection=fm.teal.alpha.actor.status&rkey=self") 25 27 .then((response) => response.ok ? response.json() : null) 26 28 .then((data) => { 27 - if (!data?.value?.item) return; 29 + const el = document.getElementById("now-playing"); 30 + if (!data?.value?.item) { 31 + el.innerHTML = ""; 32 + nowPlayingTimeout = setTimeout(fetchNowPlaying, 60000); 33 + return; 34 + } 28 35 const item = data.value.item; 29 36 const expiry = parseInt(data.value.expiry, 10) * 1000; 30 - if (Date.now() > expiry) return; 31 - const el = document.getElementById("now-playing"); 32 - el.innerHTML = `🎵 <a href="${item.originUrl || '#'}" target="_blank" rel="noopener">${item.trackName}</a> - ${item.artists?.[0]?.artistName || 'Unknown'}`; 37 + const now = Date.now(); 38 + if (now > expiry) { 39 + el.innerHTML = ""; 40 + nowPlayingTimeout = setTimeout(fetchNowPlaying, 60000); 41 + return; 42 + } 43 + el.innerHTML = `🎵&nbsp;<a href="${item.originUrl || '#'}" target="_blank" rel="noopener"><span class="track-name">${item.trackName}</span></a>&nbsp;-&nbsp;<span class="artist-name">${item.artists?.[0]?.artistName || 'Unknown'}</span>`; 44 + const timeUntilExpiry = expiry - now + 1000; 45 + nowPlayingTimeout = setTimeout(fetchNowPlaying, timeUntilExpiry); 33 46 }) 34 - .catch(() => {}); 35 - }); 47 + .catch(() => { 48 + nowPlayingTimeout = setTimeout(fetchNowPlaying, 60000); 49 + }); 50 + } 51 + document.addEventListener("DOMContentLoaded", fetchNowPlaying); 36 52 </script> 37 53 {% endif %}
+8 -3
templates/shortcodes/is.md
··· 3 3 </div> 4 4 5 5 <script> 6 - document.addEventListener("DOMContentLoaded", () => { 6 + function fetchStatus() { 7 7 fetch( 8 8 "https://bsky.social/xrpc/com.atproto.repo.listRecords?repo=dunkirk.sh&collection=a.status.update", 9 9 ) ··· 14 14 return response.json(); 15 15 }) 16 16 .then((statusData) => { 17 + const bubble = document.querySelector(".bubble"); 17 18 if (statusData.records && statusData.records.length > 0) { 18 19 if (statusData.records[0].value.createdAt) { 19 20 const createdAt = statusData.records[0].value.createdAt; ··· 23 24 const diffInMins = Math.floor(diffInMs / (1000 * 60)); 24 25 const diffInHours = Math.floor(diffInMs / (1000 * 60 * 60)); 25 26 if (diffInHours > 12) { 27 + bubble.style.visibility = "hidden"; 26 28 return; 27 29 } 28 30 const latestStatus = `"${statusData.records[0].value.text}"`; ··· 38 40 const verbLink = document.getElementById("verb-link"); 39 41 if (diffInMins > 30) { 40 42 verbLink.textContent = "Kieran was"; 43 + } else { 44 + verbLink.textContent = "Kieran is"; 41 45 } 42 - const bubble = document.querySelector(".bubble"); 43 46 bubble.style.visibility = "visible"; 44 47 bubble.classList.add("animate-in"); 45 48 if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) { ··· 52 55 .catch((error) => { 53 56 console.error("Error fetching status update:", error); 54 57 }); 55 - }); 58 + } 59 + document.addEventListener("DOMContentLoaded", fetchStatus); 60 + setInterval(fetchStatus, 3600000); 56 61 </script>