+2
-4
src/pages/configurator/input/_applet.astro
+2
-4
src/pages/configurator/input/_applet.astro
···
30
30
</style>
31
31
32
32
<script>
33
-
import { applets } from "@web-applets/sdk";
34
-
35
33
import type { Track } from "@applets/core/types.d.ts";
36
-
import { applet } from "@scripts/theme";
34
+
import { applet, register } from "@scripts/applets/common";
37
35
38
36
////////////////////////////////////////////
39
37
// SETUP
40
38
////////////////////////////////////////////
41
-
const context = applets.register<{ ready: boolean }>();
39
+
const context = register<{ ready: boolean }>();
42
40
43
41
// Initial state
44
42
context.data = {
+2
-3
src/pages/configurator/output/_applet.astro
+2
-3
src/pages/configurator/output/_applet.astro
···
39
39
import scope from "astro:scope";
40
40
import { type Signal, computed, effect, signal } from "spellcaster/spellcaster.js";
41
41
import { type ElementConfigurator, repeat, text } from "spellcaster/hyperscript.js";
42
-
import { applets } from "@web-applets/sdk";
43
42
44
-
import { applet, hs } from "@src/scripts/theme";
43
+
import { applet, hs, register } from "@scripts/applets/common";
45
44
import type { OutputGetter, OutputSetter } from "@applets/core/types.d.ts";
46
45
47
46
const METHODS = ["browser", "custom", "device"] as const;
···
63
62
////////////////////////////////////////////
64
63
// SETUP
65
64
////////////////////////////////////////////
66
-
const context = applets.register<{ ready: boolean }>();
65
+
const context = register<{ ready: boolean }>();
67
66
68
67
// Applets container
69
68
const container = document.createElement("div");
+12
-13
src/pages/engine/audio/_applet.astro
+12
-13
src/pages/engine/audio/_applet.astro
···
1
1
<script>
2
-
import { applets } from "@web-applets/sdk";
3
-
import { State, Track, TrackState } from "./types";
2
+
import type { State, Track, TrackState } from "./types";
3
+
import { register } from "@scripts/applets/common";
4
4
5
5
////////////////////////////////////////////
6
6
// CONSTANTS
···
11
11
////////////////////////////////////////////
12
12
// SETUP
13
13
////////////////////////////////////////////
14
-
const context = applets.register<State>();
15
-
const container = document.createElement("div");
14
+
const context = register<State>();
16
15
16
+
// Audio elements container
17
+
const container = document.createElement("div");
17
18
container.id = "container";
18
19
document.body.appendChild(container);
19
20
···
40
41
////////////////////////////////////////////
41
42
// ACTIONS
42
43
////////////////////////////////////////////
43
-
context.setActionHandler(
44
-
"render",
45
-
async (args: { play?: { trackId: string; volume?: number }; tracks: Track[] }) => {
46
-
await render(args.tracks);
47
-
if (args.play) play({ trackId: args.play.trackId, volume: args.play.volume });
48
-
},
49
-
);
50
-
51
44
context.setActionHandler("pause", pause);
52
45
context.setActionHandler("play", play);
53
46
context.setActionHandler("reload", reload);
47
+
context.setActionHandler("render", render);
54
48
context.setActionHandler("seek", seek);
55
49
context.setActionHandler("volume", volume);
56
50
···
102
96
});
103
97
}
104
98
99
+
async function render(args: { play?: { trackId: string; volume?: number }; tracks: Track[] }) {
100
+
await renderTracks(args.tracks);
101
+
if (args.play) play({ trackId: args.play.trackId, volume: args.play.volume });
102
+
}
103
+
105
104
function seek({ percentage, trackId }: { percentage: number; trackId: string }) {
106
105
withAudioNode(trackId, (audio) => {
107
106
if (!isNaN(audio.duration)) {
···
122
121
////////////////////////////////////////////
123
122
// RENDER
124
123
////////////////////////////////////////////
125
-
async function render(tracks: Array<Track>) {
124
+
async function renderTracks(tracks: Array<Track>) {
126
125
const ids = tracks.map((e) => e.id);
127
126
const existingNodes: Record<string, HTMLAudioElement> = {};
128
127
+2
-2
src/pages/engine/queue/_applet.astro
+2
-2
src/pages/engine/queue/_applet.astro
···
1
1
<script>
2
-
import { applets } from "@web-applets/sdk";
3
2
import { QueueItem, State } from "./types";
3
+
import { register } from "@scripts/applets/common";
4
4
5
5
////////////////////////////////////////////
6
6
// SETUP
7
7
////////////////////////////////////////////
8
-
const context = applets.register<State>();
8
+
const context = register<State>();
9
9
10
10
// Initial state
11
11
context.data = {
+2
-2
src/pages/input/native-fs/_applet.astro
+2
-2
src/pages/input/native-fs/_applet.astro
···
16
16
</main>
17
17
18
18
<script>
19
-
import { applets } from "@web-applets/sdk";
20
19
import { computed, effect, Signal, signal } from "spellcaster";
21
20
import { repeat, tags, text } from "spellcaster/hyperscript.js";
22
21
import { type FileSystemDirectoryHandle, showDirectoryPicker } from "native-file-system-adapter";
···
26
25
27
26
import type { Track } from "@applets/core/types.d.ts";
28
27
import { isAudioFile } from "@scripts/inputs/common";
28
+
import { register } from "@scripts/applets/common";
29
29
30
30
import manifest from "./_manifest.json";
31
31
···
41
41
const SCHEME = manifest.input_properties.scheme;
42
42
43
43
// Register applet
44
-
const context = applets.register();
44
+
const context = register();
45
45
46
46
////////////////////////////////////////////
47
47
// UI
+3
-4
src/pages/input/s3/_applet.astro
+3
-4
src/pages/input/s3/_applet.astro
···
38
38
39
39
<script>
40
40
import { S3Client } from "@bradenmacdonald/s3-lite-client";
41
-
import { applets } from "@web-applets/sdk";
42
41
import { computed, effect, Signal, signal } from "spellcaster";
43
42
import { type Props, repeat, tags, text } from "spellcaster/hyperscript.js";
44
43
import * as IDB from "idb-keyval";
···
46
45
import QS from "query-string";
47
46
48
47
import type { Track } from "@applets/core/types.d.ts";
49
-
50
-
import manifest from "./_manifest.json";
51
48
import { isAudioFile } from "@scripts/inputs/common";
49
+
import { register } from "@scripts/applets/common";
50
+
import manifest from "./_manifest.json";
52
51
53
52
type Bucket = {
54
53
accessKey: string;
···
86
85
const SCHEME = manifest.input_properties.scheme;
87
86
88
87
// Register applet
89
-
const context = applets.register();
88
+
const context = register();
90
89
91
90
////////////////////////////////////////////
92
91
// UI
+6
-16
src/pages/orchestrator/single-queue/_applet.astro
+6
-16
src/pages/orchestrator/single-queue/_applet.astro
···
1
1
<script>
2
-
import { applets } from "@web-applets/sdk";
3
-
4
2
import type { ResolvedUri, Track } from "@applets/core/types.d.ts";
5
-
import { applet, comparable, reactive } from "@scripts/theme";
3
+
import { applet, comparable, reactive, register } from "@scripts/applets/common";
6
4
7
5
////////////////////////////////////////////
8
6
// SETUP
···
12
10
import type * as OutputOrchestrator from "@applets/orchestrator/output-management/types.d.ts";
13
11
14
12
// Register applet
15
-
const context = applets.register<unknown>();
13
+
const context = register<unknown>();
16
14
17
15
// Applet connections
18
16
const configurator = {
19
-
input: await applet("../../configurator/input", {
20
-
context: self.top || self.parent,
21
-
}),
17
+
input: await applet("../../configurator/input"),
22
18
};
23
19
24
20
const engine = {
25
-
audio: await applet<AudioEngine.State>("../../engine/audio", {
26
-
context: self.top || self.parent,
27
-
}),
28
-
queue: await applet<QueueEngine.State>("../../engine/queue", {
29
-
context: self.top || self.parent,
30
-
}),
21
+
audio: await applet<AudioEngine.State>("../../engine/audio"),
22
+
queue: await applet<QueueEngine.State>("../../engine/queue"),
31
23
};
32
24
33
25
const orchestrator = {
34
-
output: await applet<OutputOrchestrator.State>("../../orchestrator/output-management", {
35
-
context: self.top || self.parent,
36
-
}),
26
+
output: await applet<OutputOrchestrator.State>("../../orchestrator/output-management"),
37
27
};
38
28
39
29
////////////////////////////////////////////
+2
-2
src/pages/output/indexed-db/_applet.astro
+2
-2
src/pages/output/indexed-db/_applet.astro
···
1
1
<script>
2
2
import * as IDB from "idb-keyval";
3
-
import { applets } from "@web-applets/sdk";
4
3
5
4
import type { OutputGetter, OutputSetter } from "@applets/core/types.d.ts";
5
+
import { register } from "@scripts/applets/common";
6
6
7
7
////////////////////////////////////////////
8
8
// SETUP
9
9
////////////////////////////////////////////
10
10
const IDB_PREFIX = "@applets/output/indexed-db";
11
-
const context = applets.register();
11
+
const context = register();
12
12
13
13
////////////////////////////////////////////
14
14
// ACTIONS
+2
-2
src/pages/output/native-fs/_applet.astro
+2
-2
src/pages/output/native-fs/_applet.astro
···
1
1
<script>
2
2
import * as IDB from "idb-keyval";
3
-
import { applets } from "@web-applets/sdk";
4
3
import { type FileSystemDirectoryHandle, showDirectoryPicker } from "native-file-system-adapter";
5
4
6
5
import type { OutputGetter, OutputSetter } from "@applets/core/types.d.ts";
6
+
import { register } from "@scripts/applets/common";
7
7
8
8
////////////////////////////////////////////
9
9
// SETUP
···
11
11
const IDB_PREFIX = "@applets/output/native-fs";
12
12
const IDB_DEVICE_KEY = `${IDB_PREFIX}/device`;
13
13
14
-
const context = applets.register();
14
+
const context = register();
15
15
16
16
////////////////////////////////////////////
17
17
// ACTIONS
+4
-1
src/pages/processor/metadata-fetcher/_applet.astro
+4
-1
src/pages/processor/metadata-fetcher/_applet.astro
···
24
24
async function extract(args: { mimeType?: string; stream?: ReadableStream; urls?: Urls }) {
25
25
// Construct records
26
26
// TODO: Use other metadata lib as fallback: https://github.com/buzz/mediainfo.js
27
-
const { stats, tags } = await musicMetadataTags(args, false);
27
+
const { stats, tags } = await musicMetadataTags(args, false).catch(() => ({
28
+
stats: undefined,
29
+
tags: undefined,
30
+
}));
28
31
29
32
// Fin
30
33
return { stats, tags };
+1
-1
src/scripts/themes/webamp/index.ts
+1
-1
src/scripts/themes/webamp/index.ts
+3
astro.config.js
+3
astro.config.js
+3
-3
src/pages/index.astro
+3
-3
src/pages/index.astro
···
141
141
</Applet>
142
142
143
143
<Applet title="Orchestrators" list={orchestrators}>
144
-
These too are applet compositions. However, unlike themes, these are purely logical, and
145
-
reuse applet instances from the parent context (when available). Mostly exist in order to
146
-
construct sensible defaults to use across themes and abstractions.
144
+
These too are applet compositions. However, unlike themes, these are purely logical.
145
+
Mostly exist in order to construct sensible defaults to use across themes and
146
+
abstractions.
147
147
</Applet>
148
148
149
149
<Applet title="Output" list={output}>
-6
src/pages/orchestrator/input-cache/_applet.astro
-6
src/pages/orchestrator/input-cache/_applet.astro
···
49
49
50
50
await waitUntilAppletIsReady(configurator.input);
51
51
52
-
console.log("Ready.");
53
-
54
52
const cachedTracks = orchestrator.output.data.tracks.collection;
55
53
await configurator.input.sendAction("contextualize", cachedTracks);
56
54
57
-
console.log("Start list.");
58
-
59
55
const tracks = await configurator.input.sendAction<Track[]>("list", cachedTracks, {
60
56
timeoutDuration: 60000 * 60 * 24,
61
57
});
62
58
63
-
console.log("Got tracks", tracks);
64
-
65
59
// Process
66
60
const tracksWithMetadata = await tracks.reduce(
67
61
async (promise: Promise<Track[]>, track: Track) => {
+6
src/scripts/applets/common.ts
+6
src/scripts/applets/common.ts
···
1
1
import type { Applet, AppletEvent } from "@web-applets/sdk";
2
2
3
+
import QS from "query-string";
3
4
import { applets } from "@web-applets/sdk";
4
5
import { type ElementConfigurator, h } from "spellcaster/hyperscript.js";
5
6
import { effect, isSignal, Signal, signal } from "spellcaster/spellcaster.js";
···
12
13
src: string,
13
14
opts: {
14
15
addSlashSuffix?: boolean;
16
+
applets?: Record<string, string>;
15
17
container?: HTMLElement | Element;
16
18
id?: string;
17
19
setHeight?: boolean;
···
25
27
: ""
26
28
}`;
27
29
30
+
if (opts.applets) {
31
+
src = QS.stringifyUrl({ url: src, query: opts.applets });
32
+
}
33
+
28
34
const existingFrame: HTMLIFrameElement | null = window.document.querySelector(`[src="${src}"]`);
29
35
30
36
let frame;