Experiment to rebuild Diffuse using web applets.
0

Configure Feed

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

refactor: shared workers

+74 -62
+3 -3
src/pages/configurator/input/_applet.astro
··· 45 45 // CONNECTIONS 46 46 ////////////////////////////////////////////// Applet connections 47 47 const CONNECTIONS = { 48 - "file+local": "../../input/native-fs", 49 - opensubsonic: "../../input/opensubsonic", 50 - s3: "../../input/s3", 48 + "file+local": "/input/native-fs", 49 + opensubsonic: "/input/opensubsonic", 50 + s3: "/input/s3", 51 51 }; 52 52 53 53 type Scheme = keyof typeof CONNECTIONS;
+13 -9
src/pages/constituent/blur/artwork-controller/_applet.astro
··· 100 100 border-radius: 4px; 101 101 } 102 102 103 - progress[value]::-webkit-progress-value, 103 + progress[value]::-webkit-progress-value { 104 + border-radius: 4px; 105 + background-color: color-mix(in oklch, currentColor 90%, transparent); 106 + } 107 + 104 108 progress[value]::-moz-progress-bar { 105 109 border-radius: 4px; 106 110 background-color: color-mix(in oklch, currentColor 50%, transparent); ··· 334 338 335 339 // Applet connections 336 340 const configurator = { 337 - input: await applet("../../../configurator/input"), 338 - output: await applet<ManagedOutput>("../../../configurator/output"), 341 + input: await applet("/configurator/input"), 342 + output: await applet<ManagedOutput>("/configurator/output"), 339 343 }; 340 344 341 345 const engine = { 342 - audio: await applet<AudioEngine.State>("../../engine/audio", { groupId: groupId() }), 343 - queue: await applet<QueueEngine.State>("../../engine/queue", { groupId: groupId() }), 346 + audio: await applet<AudioEngine.State>("/engine/audio", { groupId: groupId() }), 347 + queue: await applet<QueueEngine.State>("/engine/queue", { groupId: groupId() }), 344 348 }; 345 349 346 350 const _orchestrator = { 347 - queueAudio: await applet("../../../orchestrator/queue-audio", { 351 + queueAudio: await applet("/orchestrator/queue-audio", { 348 352 groupId: groupId(), 349 353 }), 350 354 351 355 // When using the `main` group, load additional orchestrators: 352 356 inputCache: 353 357 context.groupId === undefined || context.groupId === "main" 354 - ? await applet("../../../orchestrator/input-cache") 358 + ? await applet("/orchestrator/input-cache") 355 359 : undefined, 356 360 queueTracks: 357 361 context.groupId === undefined || context.groupId === "main" 358 - ? applet("../../../orchestrator/queue-tracks") 362 + ? applet("/orchestrator/queue-tracks") 359 363 : undefined, 360 364 }; 361 365 362 366 const processor = { 363 - artwork: await applet("../../../processor/artwork"), 367 + artwork: await applet("/processor/artwork"), 364 368 }; 365 369 366 370 ////////////////////////////////////////////
+2 -2
src/pages/engine/queue/_applet.astro
··· 4 4 import type { State } from "./types.d.ts"; 5 5 6 6 import { register } from "@scripts/applet/common"; 7 - import { endpoint } from "@scripts/common"; 7 + import { endpoint, SharedWorker } from "@scripts/common"; 8 8 9 9 //////////////////////////////////////////// 10 10 // SETUP 11 11 //////////////////////////////////////////// 12 12 const worker = endpoint<Actions>( 13 - new Worker("../../../scripts/engine/queue/worker", { type: "module" }), 13 + new SharedWorker("../../../scripts/engine/queue/worker", { type: "module" }).port, 14 14 ); 15 15 16 16 // Register applet
+1 -1
src/pages/index.astro
··· 26 26 27 27 // Constituents 28 28 const constituents = [ 29 - { url: "constituent/blur/artwork-controller", title: "(WIP) Blur ⦚ Artwork Controller" }, 29 + { url: "constituent/blur/artwork-controller/", title: "(WIP) Blur ⦚ Artwork Controller" }, 30 30 ]; 31 31 32 32 // Applets
+2 -2
src/pages/input/native-fs/_applet.astro
··· 19 19 import type { Actions } from "@scripts/input/native-fs/worker"; 20 20 import type { Track } from "@applets/core/types.d.ts"; 21 21 import { register } from "@scripts/applet/common"; 22 - import { endpoint, inIframe } from "@scripts/common"; 22 + import { endpoint, inIframe, SharedWorker } from "@scripts/common"; 23 23 import * as Mounting from "@scripts/input/native-fs/mounting"; 24 24 25 25 //////////////////////////////////////////// 26 26 // SETUP 27 27 //////////////////////////////////////////// 28 28 const worker = endpoint<Actions>( 29 - new Worker("../../../scripts/input/native-fs/worker", { type: "module" }), 29 + new SharedWorker("../../../scripts/input/native-fs/worker", { type: "module" }).port, 30 30 ); 31 31 32 32 // Register applet
+2 -2
src/pages/input/opensubsonic/_applet.astro
··· 21 21 import type { Actions } from "@scripts/input/opensubsonic/worker"; 22 22 import type { Track } from "@applets/core/types.d.ts"; 23 23 import { register } from "@scripts/applet/common"; 24 - import { endpoint, inIframe } from "@scripts/common"; 24 + import { endpoint, inIframe, SharedWorker } from "@scripts/common"; 25 25 26 26 //////////////////////////////////////////// 27 27 // SETUP 28 28 //////////////////////////////////////////// 29 29 const worker = endpoint<Actions>( 30 - new Worker("../../../scripts/input/opensubsonic/worker", { type: "module" }), 30 + new SharedWorker("../../../scripts/input/opensubsonic/worker", { type: "module" }).port, 31 31 ); 32 32 33 33 // Register applet
+2 -2
src/pages/input/s3/_applet.astro
··· 41 41 42 42 import type { Track } from "@applets/core/types.d.ts"; 43 43 import { register } from "@scripts/applet/common"; 44 - import { endpoint, inIframe } from "@scripts/common"; 44 + import { endpoint, inIframe, SharedWorker } from "@scripts/common"; 45 45 46 46 //////////////////////////////////////////// 47 47 // SETUP 48 48 //////////////////////////////////////////// 49 49 const worker = endpoint<Actions>( 50 - new Worker("../../../scripts/input/s3/worker", { type: "module" }), 50 + new SharedWorker("../../../scripts/input/s3/worker", { type: "module" }).port, 51 51 ); 52 52 53 53 // Register applet
+3 -3
src/pages/orchestrator/input-cache/_applet.astro
··· 14 14 15 15 // Applet connections 16 16 const configurator = { 17 - input: applet("../../configurator/input"), 18 - output: applet<ManagedOutput>("../../configurator/output"), 17 + input: applet("/configurator/input"), 18 + output: applet<ManagedOutput>("/configurator/output"), 19 19 }; 20 20 21 21 const processor = { 22 - metadata: applet("../../processor/metadata"), 22 + metadata: applet("/processor/metadata"), 23 23 }; 24 24 25 25 // Start processing once settled and tracks are loaded
+4 -4
src/pages/orchestrator/queue-audio/_applet.astro
··· 14 14 15 15 // Applet connections 16 16 const configurator = { 17 - input: await applet("../../configurator/input"), 18 - output: await applet<ManagedOutput>("../../configurator/output"), 17 + input: await applet("/configurator/input"), 18 + output: await applet<ManagedOutput>("/configurator/output"), 19 19 }; 20 20 21 21 const engine = { 22 - audio: await applet<AudioEngine.State>("../../engine/audio", { groupId: context.groupId }), 23 - queue: await applet<QueueEngine.State>("../../engine/queue", { groupId: context.groupId }), 22 + audio: await applet<AudioEngine.State>("/engine/audio", { groupId: context.groupId }), 23 + queue: await applet<QueueEngine.State>("/engine/queue", { groupId: context.groupId }), 24 24 }; 25 25 26 26 ////////////////////////////////////////////
+2 -2
src/pages/orchestrator/queue-tracks/_applet.astro
··· 13 13 14 14 // Applet connections 15 15 const configurator = { 16 - output: await applet<ManagedOutput>("../../configurator/output"), 16 + output: await applet<ManagedOutput>("/configurator/output"), 17 17 }; 18 18 19 19 const engine = { 20 - queue: await applet<QueueEngine.State>("../../engine/queue", { groupId: context.groupId }), 20 + queue: await applet<QueueEngine.State>("/engine/queue", { groupId: context.groupId }), 21 21 }; 22 22 23 23 ////////////////////////////////////////////
+2 -2
src/pages/output/indexed-db/_applet.astro
··· 2 2 import type { Actions } from "@scripts/output/indexed-db/worker"; 3 3 import type { ManagedOutput, Track } from "@applets/core/types.d.ts"; 4 4 import { register } from "@scripts/applet/common"; 5 - import { endpoint } from "@scripts/common"; 5 + import { SharedWorker, endpoint } from "@scripts/common"; 6 6 import { INITIAL_MANAGED_OUTPUT, outputManager } from "@scripts/output/common"; 7 7 8 8 //////////////////////////////////////////// 9 9 // SETUP 10 10 //////////////////////////////////////////// 11 11 const worker = endpoint<Actions>( 12 - new Worker("../../../scripts/output/indexed-db/worker", { type: "module" }), 12 + new SharedWorker("../../../scripts/output/indexed-db/worker", { type: "module" }).port, 13 13 ); 14 14 15 15 // Register applet
+2 -2
src/pages/output/native-fs/_applet.astro
··· 6 6 import type { ManagedOutput, Track } from "@applets/core/types"; 7 7 import { register } from "@scripts/applet/common"; 8 8 import { INITIAL_MANAGED_OUTPUT, outputManager } from "@scripts/output/common"; 9 - import { endpoint, jsonDecode, jsonEncode } from "@scripts/common"; 9 + import { endpoint, SharedWorker } from "@scripts/common"; 10 10 import { IDB_DEVICE_KEY } from "@scripts/output/native-fs/constants"; 11 11 12 12 //////////////////////////////////////////// 13 13 // SETUP 14 14 //////////////////////////////////////////// 15 15 const worker = endpoint<Actions>( 16 - new Worker("../../../scripts/output/native-fs/worker", { type: "module" }), 16 + new SharedWorker("../../../scripts/output/native-fs/worker", { type: "module" }).port, 17 17 ); 18 18 19 19 // Register applet
+2 -2
src/pages/processor/artwork/_applet.astro
··· 2 2 import type { Actions } from "@scripts/processor/artwork/worker"; 3 3 import type { ArtworkRequest } from "./types.d.ts"; 4 4 import { register } from "@scripts/applet/common"; 5 - import { endpoint } from "@scripts/common"; 5 + import { endpoint, SharedWorker } from "@scripts/common"; 6 6 7 7 //////////////////////////////////////////// 8 8 // SETUP 9 9 //////////////////////////////////////////// 10 10 const worker = endpoint<Actions>( 11 - new Worker("../../../scripts/processor/artwork/worker", { type: "module" }), 11 + new SharedWorker("../../../scripts/processor/artwork/worker", { type: "module" }).port, 12 12 ); 13 13 14 14 // Register
+2 -2
src/pages/processor/metadata/_applet.astro
··· 1 1 <script> 2 2 import type { Actions } from "@scripts/processor/metadata/worker"; 3 3 import { register } from "@scripts/applet/common"; 4 - import { endpoint } from "@scripts/common"; 4 + import { endpoint, SharedWorker } from "@scripts/common"; 5 5 6 6 //////////////////////////////////////////// 7 7 // SETUP 8 8 //////////////////////////////////////////// 9 9 const worker = endpoint<Actions>( 10 - new Worker("../../../scripts/processor/metadata/worker", { type: "module" }), 10 + new SharedWorker("../../../scripts/processor/metadata/worker", { type: "module" }).port, 11 11 ); 12 12 13 13 // Register applet
+13 -2
src/scripts/common.ts
··· 4 4 5 5 import type { Track } from "@applets/core/types"; 6 6 7 + export { SharedWorkerPolyfill as SharedWorker } from "@okikio/sharedworker"; 8 + 7 9 export function arrayShuffle<T>(array: Array<T>): Array<T> { 8 10 if (array.length === 0) { 9 11 return []; ··· 43 45 return xxh32(JSON.stringify(value)); 44 46 } 45 47 46 - export const endpoint = createEndpoint; 48 + export function endpoint<T extends Record<string, any>>(port: MessagePort) { 49 + const e = createEndpoint<T>(port); 50 + if ("start" in port) port.start(); 51 + return e; 52 + } 47 53 48 54 export function expose<T extends Record<string, any>>(actions: T): T { 49 - createEndpoint<T>(self as MessageEndpoint).expose(actions); 55 + (self as unknown as SharedWorkerGlobalScope).onconnect = (event: MessageEvent) => { 56 + const port = event.ports[0]; 57 + createEndpoint<T>(port).expose(actions); 58 + if ("start" in port) port.start(); 59 + }; 60 + 50 61 return actions; 51 62 } 52 63
+2 -2
src/scripts/configurator/output/constants.ts
··· 1 1 export const METHODS = ["browser", "custom", "device"] as const; 2 2 3 3 export const CONNECTIONS = { 4 - browser: "../../output/indexed-db/", 4 + browser: "/output/indexed-db/", 5 5 custom: undefined, 6 - device: "../../output/native-fs/", 6 + device: "/output/native-fs/", 7 7 }; 8 8 9 9 export const DEFAULT_METHOD: (typeof METHODS)[number] = "browser";
+2 -5
src/scripts/processor/artwork/worker.ts
··· 1 1 import type { IPicture } from "music-metadata"; 2 - import { SharedWorkerPolyfill as SharedWorker } from "@okikio/sharedworker"; 3 2 import * as IDB from "idb-keyval"; 4 3 5 4 import type { Actions as MetadataActions } from "../metadata/worker"; 6 5 import type { Artwork, ArtworkRequest } from "./types"; 7 - import { endpoint, expose } from "@scripts/common"; 6 + import { SharedWorker, endpoint, expose } from "@scripts/common"; 8 7 import { IDB_ARTWORK_PREFIX } from "./constants"; 9 8 10 9 // State ··· 12 11 13 12 // Metadata worker 14 13 const metadataWorker = endpoint<MetadataActions>( 15 - new SharedWorker("../metadata/worker", { 16 - type: "module", 17 - }).port, 14 + new SharedWorker("../metadata/worker", { type: "module" }).port, 18 15 ); 19 16 20 17 ////////////////////////////////////////////
+6 -6
src/scripts/theme/blur/index.ts
··· 18 18 const labelB = "Deck B"; 19 19 20 20 const configurator = { 21 - output: await applet<ManagedOutput>("../../configurator/output"), 21 + output: await applet<ManagedOutput>("/configurator/output"), 22 22 }; 23 23 24 24 const _constituent = { 25 - a: applet("../../constituent/blur/artwork-controller", { container, groupId: labelA }), 26 - b: applet("../../constituent/blur/artwork-controller", { container, groupId: labelB }), 25 + a: applet("/constituent/blur/artwork-controller", { container, groupId: labelA }), 26 + b: applet("/constituent/blur/artwork-controller", { container, groupId: labelB }), 27 27 }; 28 28 29 29 const _orchestrator = { 30 - queueTracks: applet("../../orchestrator/queue-tracks", { groupId: labelA }), 30 + queueTracks: applet("/orchestrator/queue-tracks", { groupId: labelA }), 31 31 }; 32 32 33 33 // const engine = { 34 34 // queue: { 35 - // a: await applet<QueueEngine.State>("../../engine/queue", { groupId: labelA }), 36 - // b: await applet<QueueEngine.State>("../../engine/queue", { groupId: labelB }), 35 + // a: await applet<QueueEngine.State>("/engine/queue", { groupId: labelA }), 36 + // b: await applet<QueueEngine.State>("/engine/queue", { groupId: labelB }), 37 37 // }, 38 38 // }; 39 39
+6 -6
src/scripts/theme/pilot/index.ts
··· 14 14 import type * as AudioUI from "@applets/constituent/pilot/audio/types"; 15 15 16 16 const engine = { 17 - audio: await applet<AudioEngine.State>("../../engine/audio"), 18 - queue: await applet<QueueEngine.State>("../../engine/queue"), 17 + audio: await applet<AudioEngine.State>("/engine/audio"), 18 + queue: await applet<QueueEngine.State>("/engine/queue"), 19 19 }; 20 20 21 21 const _orchestrator = { 22 - input: await applet("../../orchestrator/input-cache"), 23 - queueAudio: await applet("../../orchestrator/queue-audio"), 24 - queueTracks: await applet("../../orchestrator/queue-tracks"), 22 + input: await applet("/orchestrator/input-cache"), 23 + queueAudio: await applet("/orchestrator/queue-audio"), 24 + queueTracks: await applet("/orchestrator/queue-tracks"), 25 25 }; 26 26 27 27 const ui = { 28 - audio: await applet<AudioUI.State>("../../constituent/pilot/audio/", { setHeight: true }), 28 + audio: await applet<AudioUI.State>("/constituent/pilot/audio/", { setHeight: true }), 29 29 }; 30 30 31 31 ////////////////////////////////////////////
+3 -3
src/scripts/theme/webamp/index.ts
··· 13 13 // 🗂️ Applets 14 14 //////////////////////////////////////////// 15 15 const configurator = { 16 - input: await applet("../../configurator/input"), 17 - output: await applet<ManagedOutput>("../../configurator/output"), 16 + input: await applet("/configurator/input"), 17 + output: await applet<ManagedOutput>("/configurator/output"), 18 18 }; 19 19 20 20 const orchestrator = { 21 - input: await applet("../../orchestrator/input-cache"), 21 + input: await applet("/orchestrator/input-cache"), 22 22 }; 23 23 24 24 ////////////////////////////////////////////