diff options
| -rw-r--r-- | aero.js | 25 | ||||
| -rwxr-xr-x | index.html | 50 |
2 files changed, 64 insertions, 11 deletions
@@ -176,4 +176,27 @@ async function fetchVisitorCount() { return j.count; } -window.Aero = { spawnBubbles, makeClouds, sparkleCursor, makeDraggable, counterHTML, nowPlayingHTML, animateEq, musicToggleHTML, bindMusicToggle, fetchLastFm, fetchFilms, fetchVisitorCount }; +async function fetchReelMouthFeed(limit = 6) { + const url = `https://itunes.apple.com/lookup?id=1709836497&entity=podcastEpisode&limit=${limit + 1}`; + const r = await fetch(url); + if (!r.ok) throw new Error('itunes ' + r.status); + const j = await r.json(); + const podcast = j.results.find(x => x.kind === 'podcast'); + const episodes = j.results.filter(x => x.kind === 'podcast-episode').slice(0, limit); + return { + art: podcast ? podcast.artworkUrl600 : null, + episodes: episodes.map(e => { + const ms = e.trackTimeMillis || 0; + const mins = Math.floor(ms / 60000); + const h = Math.floor(mins / 60); + const m = mins % 60; + return { + title: e.trackName, + url: e.trackViewUrl, + duration: h ? `${h}:${m.toString().padStart(2, '0')}` : `${m}m`, + }; + }), + }; +} + +window.Aero = { spawnBubbles, makeClouds, sparkleCursor, makeDraggable, counterHTML, nowPlayingHTML, animateEq, musicToggleHTML, bindMusicToggle, fetchLastFm, fetchFilms, fetchVisitorCount, fetchReelMouthFeed }; @@ -207,7 +207,8 @@ <div class="titlebar" style="background: var(--title-bar);"><div class="dots"><div class="dot r no-drag" onclick="this.closest('.win').style.display='none'"></div><div class="dot y"></div><div class="dot g"></div></div>REEL MOUTH — film pod</div> <div class="body"> <div style="display: flex; gap: 12px; align-items: flex-start; margin-bottom: 12px;"> - <div class="photo" style="width: 84px; height: 84px;"><span>[ pod art ]</span></div> + <img id="pod-art" src="" alt="REEL MOUTH" style="width: 84px; height: 84px; border-radius: 12px; object-fit: cover; box-shadow: 0 3px 10px rgba(0,0,0,0.18); display: none;" /> + <div class="photo" id="pod-art-placeholder" style="width: 84px; height: 84px;"><span>🎙</span></div> <div style="font-size: 12px; line-height: 1.5;"> <div style="font-size: 16px; font-weight: 700; color: oklch(28% 0.08 230); letter-spacing: -0.3px;">REEL MOUTH</div> <div style="opacity: 0.7; margin-bottom: 4px;">a film podcast · since 2022</div> @@ -215,18 +216,13 @@ </div> </div> <div style="font-size: 11px; opacity: 0.7; text-transform: uppercase; letter-spacing: 1.5px; margin-bottom: 6px;">latest episodes</div> - <!-- TODO: wire to podcast RSS via iTunes lookup API once we know the Apple Podcasts ID --> - <div style="display: flex; flex-direction: column; gap: 4px; font-size: 12px; line-height: 1.5;"> - <div style="display:flex;justify-content:space-between;gap:8px;"><span>#84 — every wong kar-wai, ranked</span><span style="opacity:0.6;flex-shrink:0;">1:47</span></div> - <div style="display:flex;justify-content:space-between;gap:8px;"><span>#83 — paul thomas anderson cinematic universe</span><span style="opacity:0.6;flex-shrink:0;">1:32</span></div> - <div style="display:flex;justify-content:space-between;gap:8px;"><span>#82 — vietnamese cinema is real, actually</span><span style="opacity:0.6;flex-shrink:0;">1:58</span></div> - <div style="display:flex;justify-content:space-between;gap:8px;"><span>#81 — the criterion sale haul</span><span style="opacity:0.6;flex-shrink:0;">1:12</span></div> + <div id="pod-episodes" style="display: flex; flex-direction: column; gap: 4px; font-size: 12px; line-height: 1.5;"> + <div style="opacity: 0.5; font-style: italic;">loading…</div> </div> <div style="margin-top: 14px; display: flex; gap: 8px; flex-wrap: wrap;"> <a class="aqua sm" href="https://reelmouth.tv" style="text-decoration:none;">▶ reelmouth.tv</a> - <a class="aqua sm" href="#" style="text-decoration:none;">apple</a> - <a class="aqua sm" href="#" style="text-decoration:none;">spotify</a> - <a class="aqua sm" href="#" style="text-decoration:none;">rss</a> + <a class="aqua sm" href="https://podcasts.apple.com/us/podcast/reel-mouth/id1709836497" style="text-decoration:none;">apple</a> + <a class="aqua sm" href="https://anchor.fm/s/e8438774/podcast/rss" style="text-decoration:none;">rss</a> </div> </div> </div> @@ -353,6 +349,40 @@ }); }); + // podcast RSS + let podLoaded = false; + async function loadPodcast() { + if (podLoaded) return; + podLoaded = true; + try { + const { art, episodes } = await Aero.fetchReelMouthFeed(6); + if (art) { + const img = document.getElementById('pod-art'); + const ph = document.getElementById('pod-art-placeholder'); + img.src = art; + img.style.display = ''; + if (ph) ph.style.display = 'none'; + } + const container = document.getElementById('pod-episodes'); + if (episodes.length) { + container.innerHTML = episodes.map(e => + `<div style="display:flex;justify-content:space-between;gap:8px;"> + <a href="${e.url}" target="_blank" rel="noopener" style="color:inherit;text-decoration:none;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;" title="${e.title}">${e.title.toLowerCase()}</a> + <span style="opacity:0.6;flex-shrink:0;">${e.duration}</span> + </div>` + ).join(''); + } else { + container.innerHTML = '<div style="opacity:0.5;font-style:italic;">no episodes found</div>'; + } + } catch (err) { + document.getElementById('pod-episodes').innerHTML = '<div style="opacity:0.5;font-style:italic;">couldn\'t load feed</div>'; + } + } + document.querySelectorAll('.icon[data-open="podcast"]').forEach(ic => { + ic.addEventListener('click', loadPodcast); + ic.addEventListener('dblclick', loadPodcast); + }); + // music toggle + volume slider document.getElementById('mt').innerHTML = Aero.musicToggleHTML(); const mtDiv = document.getElementById('mt'); |
