Experiment to rebuild Diffuse using web applets.
1import { applet, reactive } from "@scripts/applet/common";
2
3////////////////////////////////////////////
4// 🎨 Styles
5////////////////////////////////////////////
6import "@styles/theme/pilot/index.css";
7
8////////////////////////////////////////////
9// 🗂️ Applets
10////////////////////////////////////////////
11import type * as AudioEngine from "@applets/engine/audio/types.d.ts";
12import type * as QueueEngine from "@applets/engine/queue/types.d.ts";
13
14import type * as AudioUI from "@applets/constituent/pilot/audio/types";
15
16const engine = {
17 audio: await applet<AudioEngine.State>("/engine/audio"),
18 queue: await applet<QueueEngine.State>("/engine/queue"),
19};
20
21const _orchestrator = {
22 input: await applet("/orchestrator/input-cache"),
23 queueAudio: await applet("/orchestrator/queue-audio"),
24 queueTracks: await applet("/orchestrator/queue-tracks"),
25};
26
27const ui = {
28 audio: await applet<AudioUI.State>("/constituent/pilot/audio/", { setHeight: true }),
29};
30
31////////////////////////////////////////////
32// ⚙️ [Connections → Engines]
33// 🔉 AUDIO
34////////////////////////////////////////////
35
36// NOTE:
37// These could probably be optimised, but it works.
38
39reactive(
40 engine.audio,
41 (data) =>
42 data.isPlaying && (data.items[engine.queue.data.now?.id ?? Infinity]?.isPlaying ?? false),
43 (isPlaying) => ui.audio.sendAction("modifyIsPlaying", isPlaying),
44);
45
46reactive(
47 engine.audio,
48 (data) => data.items[engine.queue.data.now?.id ?? Infinity]?.progress ?? 0,
49 (progress: number) => ui.audio.sendAction("modifyProgress", progress),
50);
51
52////////////////////////////////////////////
53// 🌅 [Connections → UI]
54// 🔉 AUDIO
55////////////////////////////////////////////
56
57reactive(
58 ui.audio,
59 (data) => data.isPlaying,
60 async (isPlaying, setter) => {
61 const audioId = engine.queue.data.now?.id;
62
63 // Automatically start playing something if nothing is playing yet.
64 if (!audioId) {
65 if (isPlaying) {
66 const now = await engine.queue.sendAction("shift");
67 if (!now) {
68 console.warn("No tracks available yet, try again later.");
69 await ui.audio.sendAction("modifyIsPlaying", false);
70 setter(false);
71 }
72 }
73 return;
74 }
75
76 // Otherwise just control the audio
77 if (isPlaying) {
78 engine.audio.sendAction("play", { audioId });
79 } else {
80 engine.audio.sendAction("pause", { audioId });
81 }
82 },
83);
84
85reactive(
86 ui.audio,
87 (data: AudioUI.State) => data.seekPosition,
88 (seekPosition) => {
89 if (seekPosition !== undefined && engine.queue.data.now?.id) {
90 engine.audio.sendAction("seek", {
91 percentage: seekPosition,
92 audioId: engine.queue.data.now.id,
93 });
94 }
95 },
96);