A music player that connects to your cloud/distributed storage.
1import { BroadcastableDiffuseElement, defineElement } from "~/common/element.js";
2import { effect, signal } from "~/common/signal.js";
3import foundation from "~/common/foundation.js";
4
5
6/**
7 * @import {ScrobbleElement} from "~/components/supplement/types.d.ts"
8 * @import {Track} from "~/definitions/types.d.ts"
9 */
10
11let initialised = false;
12
13effect(() => {
14 const audio = foundation.signals.engine.audio();
15 if (!audio) return;
16
17 if (!initialised) {
18 setupScrobbler();
19 initialised = true;
20 }
21});
22
23/**
24 * Pretend we're a scrobbler and cache tracks whenever they are "scrobbled"
25 */
26async function setupScrobbler() {
27 await foundation.orchestrator.scrobbleAudio();
28 await customElements.whenDefined("dct-scrobbler");
29
30 const s = new PretendScrobbler();
31 s.setAttribute("group", foundation.GROUP);
32
33 const c = await foundation.configurator.scrobbles();
34 c.append(s);
35}
36
37/**
38 * @implements {ScrobbleElement}
39 */
40class PretendScrobbler extends BroadcastableDiffuseElement {
41 isAuthenticated = signal(true).get;
42 isAuthenticating = signal(false).get;
43 handle = signal(null).get;
44
45 async nowPlaying() {}
46
47 /**
48 * @param {Track} track
49 */
50 async scrobble(track) {
51 const i = await foundation.configurator.input();
52 await i.cache([track.uri]);
53 }
54
55 // LIFECYCLE
56
57 /** @override */
58 connectedCallback() {
59 // Broadcast if needed
60 if (this.hasAttribute("group")) {
61 const actions = this.broadcast(this.identifier, {
62 nowPlaying: { strategy: "leaderOnly", fn: this.nowPlaying },
63 scrobble: { strategy: "leaderOnly", fn: this.scrobble },
64 });
65
66 if (actions) {
67 this.nowPlaying = actions.nowPlaying;
68 this.scrobble = actions.scrobble;
69 }
70 }
71
72 super.connectedCallback();
73 }
74}
75
76defineElement("dct-scrobbler", PretendScrobbler);