import Webamp from "webamp"; import { URLTrack } from "webamp"; import type { Output, Track } from "@applets/core/types.d.ts"; import { applet, waitUntilAppletIsReady } from "../../theme.ts"; //////////////////////////////////////////// // 🎨 Styles //////////////////////////////////////////// import "@styles/themes/webamp/index.css"; //////////////////////////////////////////// // 🗂️ Applets //////////////////////////////////////////// const configurator = { input: await applet("../../configurator/input"), }; const orchestrator = { output: await applet("../../orchestrator/output-management"), // TODO: Should this be explicitely be ran after the output orchestrator is loaded? input: await applet("../../orchestrator/input-cache"), }; //////////////////////////////////////////// // ⚡ //////////////////////////////////////////// const amp = new Webamp({ initialTracks: [], }); const ampNode = document.createElement("div"); ampNode.style = "height: 100vh; left: 0; position: absolute; top: 0; width: 100%; z-index: -1000;"; document.body.appendChild(ampNode); amp.renderWhenReady(ampNode); orchestrator.output.ondata = async () => { const tracks = await loadTracks(); amp.setTracksToPlay([]); amp.appendTracks(tracks); amp.nextTrack(); }; //////////////////////////////////////////// // 🛠️ //////////////////////////////////////////// async function loadTracks(): Promise { return await orchestrator.output.data.tracks.reduce( async (promise: Promise, track: Track) => { const acc = await promise; // TODO: Ideally the URL should only be resolved when needed, // but webamp doesn't allow for that. // Maybe you could work around it with a service worker. const url = await configurator.input.sendAction( "resolve", { method: "GET", uri: track.uri }, { timeoutDuration: 60000, }, ); if (!url) return acc; const urlTrack: URLTrack = { url, metaData: { title: track.tags?.title || "", artist: track.tags?.artist || "", album: track.tags?.album, }, duration: track.stats?.duration, }; return [...acc, urlTrack]; }, Promise.resolve([]), ); }