Experiment to rebuild Diffuse using web applets.
0

Configure Feed

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

1import type { URLTrack } from "webamp"; 2import Webamp from "webamp"; 3 4import type { ManagedOutput, ResolvedUri, Track } from "@applets/core/types.d.ts"; 5import { applet, wait } from "@scripts/applet/common"; 6 7//////////////////////////////////////////// 8// 🎨 Styles 9//////////////////////////////////////////// 10import "@styles/theme/webamp/index.css"; 11 12//////////////////////////////////////////// 13// 🗂️ Applets 14//////////////////////////////////////////// 15const configurator = { 16 input: await applet("/configurator/input"), 17 output: await applet<ManagedOutput>("/configurator/output"), 18}; 19 20const orchestrator = { 21 input: await applet("/orchestrator/input-cache"), 22}; 23 24//////////////////////////////////////////// 25// ⚡ 26//////////////////////////////////////////// 27const amp = new Webamp({ 28 initialTracks: [], 29}); 30 31const ampNode = document.createElement("div"); 32ampNode.style = "height: 100vh; left: 0; position: absolute; top: 0; width: 100%; z-index: -1000;"; 33document.body.appendChild(ampNode); 34amp.renderWhenReady(ampNode); 35 36wait(configurator.output, (d) => d?.tracks.state === "loaded").then(loadAndInsert); 37configurator.output.ondata = loadAndInsert; 38 39let inserting = false; 40 41async function loadAndInsert() { 42 if (configurator.output.data.tracks.state !== "loaded") return; 43 if (inserting) return; 44 inserting = true; 45 const tracks = await loadTracks(); 46 amp.setTracksToPlay([]); 47 amp.appendTracks(tracks); 48 amp.nextTrack(); 49 inserting = false; 50} 51 52//////////////////////////////////////////// 53// 🛠️ 54//////////////////////////////////////////// 55async function loadTracks(): Promise<URLTrack[]> { 56 return await configurator.output.data.tracks.collection.reduce( 57 async (promise: Promise<URLTrack[]>, track: Track) => { 58 const acc = await promise; 59 60 // TODO: Ideally the URL should only be resolved when needed, 61 // but webamp doesn't allow for that. 62 // Maybe you could work around it with a service worker. 63 const resGet = await configurator.input.sendAction<ResolvedUri>( 64 "resolve", 65 { method: "GET", uri: track.uri }, 66 { 67 timeoutDuration: 60000 * 5, 68 }, 69 ); 70 71 if (!resGet) return acc; 72 73 const urlTrack: URLTrack = { 74 url: resGet.url, 75 metaData: { 76 title: track.tags?.title || "", 77 artist: track.tags?.artist || "", 78 album: track.tags?.album, 79 }, 80 duration: track.stats?.duration, 81 }; 82 83 return [...acc, urlTrack]; 84 }, 85 Promise.resolve([]), 86 ); 87}