1import { BroadcastableDiffuseElement, query } from "@common/element.js";
2import { untracked } from "@common/signal.js";
3
4/**
5 * @import {Track} from "@definitions/types.d.ts"
6 * @import {ProxiedActions} from "@common/worker.d.ts"
7 * @import {InputElement} from "@components/input/types.d.ts"
8 * @import {OutputElement} from "@components/output/types.d.ts"
9 *
10 * @import {Actions} from "./types.d.ts"
11 */
12
13////////////////////////////////////////////
14// ELEMENT
15////////////////////////////////////////////
16
17/**
18 * Update the queue pool whenever
19 * tracks have been loaded,
20 * or the tracks collection changes.
21 */
22class QueueTracksOrchestrator extends BroadcastableDiffuseElement {
23 static NAME = "diffuse/orchestrator/queue-tracks";
24 static WORKER_URL = "components/orchestrator/queue-tracks/worker.js";
25
26 /** @type {ProxiedActions<Actions>} */
27 #proxy;
28
29 constructor() {
30 super();
31 this.#proxy = this.workerProxy({
32 forceNew: {
33 dependencies: {
34 input: true,
35 },
36 },
37 });
38 }
39
40 // LIFECYCLE
41
42 /**
43 * @override
44 */
45 async connectedCallback() {
46 // Broadcast if needed
47 if (this.hasAttribute("group")) {
48 this.broadcast(this.nameWithGroup, {});
49 }
50
51 // Super
52 super.connectedCallback();
53
54 /** @type {InputElement} */
55 const input = query(this, "input-selector");
56
57 /** @type {OutputElement<Track[]>} */
58 const output = query(this, "output-selector");
59
60 /** @type {import("@components/engine/queue/element.js").CLASS} */
61 const queue = query(this, "queue-engine-selector");
62
63 // Assign to self
64 this.input = input;
65 this.output = output;
66 this.queue = queue;
67
68 // When defined
69 await customElements.whenDefined(this.input.localName);
70 await customElements.whenDefined(this.output.localName);
71 await customElements.whenDefined(this.queue.localName);
72
73 // Watch tracks collection
74 this.effect(() => {
75 const tracks = output.tracks.collection();
76
77 this.isLeader().then((isLeader) => {
78 if (!isLeader) return;
79 untracked(() => this.#proxy.poolAvailable(tracks));
80 });
81 });
82
83 // 🌸
84 }
85
86 // WORKERS
87
88 /**
89 * @override
90 */
91 dependencies() {
92 if (!this.input) throw new Error("Input element not defined yet");
93 if (!this.queue) throw new Error("Queue element not defined yet");
94
95 return {
96 input: this.input,
97 queue: this.queue,
98 };
99 }
100}
101
102export default QueueTracksOrchestrator;
103
104////////////////////////////////////////////
105// REGISTER
106////////////////////////////////////////////
107
108export const CLASS = QueueTracksOrchestrator;
109export const NAME = "do-queue-tracks";
110
111customElements.define(NAME, QueueTracksOrchestrator);