Experiment to rebuild Diffuse using web applets.
0
fork

Configure Feed

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

refactor: output applets

+126 -57
-1
package.json
··· 18 18 "iconoir": "^7.11.0", 19 19 "idb-keyval": "^6.2.1", 20 20 "music-metadata": "^11.2.3", 21 - "native-file-system-adapter": "^3.0.1", 22 21 "query-string": "^9.1.2", 23 22 "spellcaster": "^6.0.0", 24 23 "subsonic-api": "^3.1.2",
+6 -1
src/pages/constituent/blur/artwork-controller/_applet.astro
··· 344 344 }; 345 345 346 346 const _orchestrator = { 347 - inputCache: await applet("../../../orchestrator/input-cache"), 348 347 queueAudio: await applet("../../../orchestrator/queue-audio", { 349 348 groupId: groupId(), 350 349 }), 350 + 351 + // When using the `main` group, load additional orchestrators: 352 + inputCache: 353 + context.groupId === undefined || context.groupId === "main" 354 + ? await applet("../../../orchestrator/input-cache") 355 + : undefined, 351 356 queueTracks: 352 357 context.groupId === undefined || context.groupId === "main" 353 358 ? applet("../../../orchestrator/queue-tracks")
+10 -20
src/pages/output/indexed-db/_applet.astro
··· 1 1 <script> 2 - import * as IDB from "idb-keyval"; 3 - 2 + import type { Actions } from "@scripts/output/indexed-db/worker"; 4 3 import type { ManagedOutput, Track } from "@applets/core/types.d.ts"; 5 4 import { register } from "@scripts/applet/common"; 5 + import { endpoint } from "@scripts/common"; 6 6 import { INITIAL_MANAGED_OUTPUT, outputManager } from "@scripts/output/common"; 7 - import { jsonDecode, jsonEncode } from "@scripts/common"; 8 7 9 8 //////////////////////////////////////////// 10 9 // SETUP 11 10 //////////////////////////////////////////// 12 - const IDB_PREFIX = "@applets/output/indexed-db"; 11 + const worker = endpoint<Actions>( 12 + new Worker("../../../scripts/output/indexed-db/worker", { type: "module" }), 13 + ); 13 14 15 + // Register applet 14 16 const context = register<ManagedOutput>(); 17 + 18 + // Initial state 15 19 context.data = INITIAL_MANAGED_OUTPUT; 16 20 17 21 // Output manager ··· 19 23 context, 20 24 tracks: { 21 25 async get() { 22 - const encoded = await get({ name: "tracks.json" }); 23 - if (!encoded) return []; 24 - return jsonDecode<Track[]>(encoded); 26 + return worker.call.getTracks(); 25 27 }, 26 28 27 29 async put(tracks: Track[]) { 28 - const data = jsonEncode(tracks); 29 - await put({ name: "tracks.json", data }); 30 + return worker.call.putTracks(tracks); 30 31 }, 31 32 }, 32 33 }); ··· 41 42 42 43 context.setActionHandler("mount", mount); 43 44 context.setActionHandler("unmount", unmount); 44 - 45 - //////////////////////////////////////////// 46 - // 🛠️ 47 - //////////////////////////////////////////// 48 - async function get({ name }: { name: string }) { 49 - return await IDB.get(`${IDB_PREFIX}/${name}`); 50 - } 51 - 52 - async function put({ data, name }: { data: Uint8Array; name: string }) { 53 - return await IDB.set(`${IDB_PREFIX}/${name}`, data); 54 - } 55 45 </script>
+12 -35
src/pages/output/native-fs/_applet.astro
··· 1 1 <script> 2 + import type { Actions } from "@scripts/output/native-fs/worker"; 2 3 import * as IDB from "idb-keyval"; 3 - import type * as FSA from "wicg-file-system-access"; 4 + import "wicg-file-system-access"; 4 5 5 6 import type { ManagedOutput, Track } from "@applets/core/types"; 6 7 import { register } from "@scripts/applet/common"; 7 8 import { INITIAL_MANAGED_OUTPUT, outputManager } from "@scripts/output/common"; 8 - import { jsonDecode, jsonEncode } from "@scripts/common"; 9 + import { endpoint, jsonDecode, jsonEncode } from "@scripts/common"; 10 + import { IDB_DEVICE_KEY } from "@scripts/output/native-fs/constants"; 9 11 10 12 //////////////////////////////////////////// 11 13 // SETUP 12 14 //////////////////////////////////////////// 13 - const IDB_PREFIX = "@applets/output/native-fs"; 14 - const IDB_DEVICE_KEY = `${IDB_PREFIX}/device`; 15 + const worker = endpoint<Actions>( 16 + new Worker("../../../scripts/output/native-fs/worker", { type: "module" }), 17 + ); 15 18 19 + // Register applet 16 20 const context = register<ManagedOutput>(); 21 + 22 + // Initial state 17 23 context.data = INITIAL_MANAGED_OUTPUT; 18 24 19 25 // Output manager ··· 26 32 27 33 tracks: { 28 34 async get() { 29 - const encoded = await get({ name: "tracks.json" }); 30 - if (!encoded) return []; 31 - return jsonDecode<Track[]>(encoded); 35 + return worker.call.getTracks(); 32 36 }, 33 37 34 38 async put(tracks: Track[]) { 35 - const data = jsonEncode(tracks); 36 - await put({ name: "tracks.json", data }); 39 + return worker.call.putTracks(tracks); 37 40 }, 38 41 }, 39 42 }); ··· 65 68 66 69 context.setActionHandler("mount", mount); 67 70 context.setActionHandler("unmount", unmount); 68 - 69 - //////////////////////////////////////////// 70 - // 🛠️ 71 - //////////////////////////////////////////// 72 - async function get({ name }: { name: string }) { 73 - const handle: FileSystemDirectoryHandle | null = (await IDB.get(IDB_DEVICE_KEY)) ?? null; 74 - if (!handle) throw new Error("Storage not configured properly, handle not found."); 75 - 76 - try { 77 - const fileHandle = await handle.getFileHandle(name); 78 - const file = await fileHandle.getFile(); 79 - const data = await file.bytes(); 80 - return data; 81 - } catch (err) { 82 - return undefined; 83 - } 84 - } 85 - 86 - async function put({ data, name }: { data: Uint8Array; name: string }) { 87 - const handle: FileSystemDirectoryHandle | null = (await IDB.get(IDB_DEVICE_KEY)) ?? null; 88 - if (!handle) throw new Error("Storage not configured properly, handle not found."); 89 - const fileHandle = await handle.getFileHandle(name, { create: true }); 90 - const stream = await fileHandle.createWritable(); 91 - await stream.write(data); 92 - await stream.close(); 93 - } 94 71 </script>
+1
src/scripts/output/indexed-db/constants.ts
··· 1 + export const IDB_PREFIX = "@applets/output/indexed-db";
+40
src/scripts/output/indexed-db/worker.ts
··· 1 + import * as IDB from "idb-keyval"; 2 + 3 + import { expose, jsonDecode, jsonEncode } from "@scripts/common"; 4 + import type { Track } from "@applets/core/types"; 5 + import { IDB_PREFIX } from "./constants"; 6 + 7 + //////////////////////////////////////////// 8 + // ACTIONS 9 + //////////////////////////////////////////// 10 + const actions = expose({ 11 + getTracks, 12 + putTracks, 13 + }); 14 + 15 + export type Actions = typeof actions; 16 + 17 + // Actions 18 + 19 + async function getTracks() { 20 + const encoded = await get({ name: "tracks.json" }); 21 + if (!encoded) return []; 22 + return jsonDecode<Track[]>(encoded); 23 + } 24 + 25 + async function putTracks(tracks: Track[]) { 26 + const data = jsonEncode(tracks); 27 + await put({ name: "tracks.json", data }); 28 + } 29 + 30 + //////////////////////////////////////////// 31 + // 🛠️ 32 + //////////////////////////////////////////// 33 + 34 + async function get({ name }: { name: string }) { 35 + return await IDB.get(`${IDB_PREFIX}/${name}`); 36 + } 37 + 38 + async function put({ data, name }: { data: Uint8Array; name: string }) { 39 + return await IDB.set(`${IDB_PREFIX}/${name}`, data); 40 + }
+2
src/scripts/output/native-fs/constants.ts
··· 1 + export const IDB_PREFIX = "@applets/output/native-fs"; 2 + export const IDB_DEVICE_KEY = `${IDB_PREFIX}/device`;
+55
src/scripts/output/native-fs/worker.ts
··· 1 + import * as IDB from "idb-keyval"; 2 + 3 + import { expose, jsonDecode, jsonEncode } from "@scripts/common"; 4 + import type { Track } from "@applets/core/types"; 5 + import { IDB_DEVICE_KEY, IDB_PREFIX } from "./constants"; 6 + 7 + //////////////////////////////////////////// 8 + // ACTIONS 9 + //////////////////////////////////////////// 10 + const actions = expose({ 11 + getTracks, 12 + putTracks, 13 + }); 14 + 15 + export type Actions = typeof actions; 16 + 17 + // Actions 18 + 19 + async function getTracks() { 20 + const encoded = await get({ name: "tracks.json" }); 21 + if (!encoded) return []; 22 + return jsonDecode<Track[]>(encoded); 23 + } 24 + 25 + async function putTracks(tracks: Track[]) { 26 + const data = jsonEncode(tracks); 27 + await put({ name: "tracks.json", data }); 28 + } 29 + 30 + //////////////////////////////////////////// 31 + // 🛠️ 32 + //////////////////////////////////////////// 33 + 34 + async function get({ name }: { name: string }) { 35 + const handle: FileSystemDirectoryHandle | null = (await IDB.get(IDB_DEVICE_KEY)) ?? null; 36 + if (!handle) throw new Error("Storage not configured properly, handle not found."); 37 + 38 + try { 39 + const fileHandle = await handle.getFileHandle(name); 40 + const file = await fileHandle.getFile(); 41 + const data = await file.bytes(); 42 + return data; 43 + } catch (err) { 44 + return undefined; 45 + } 46 + } 47 + 48 + async function put({ data, name }: { data: Uint8Array; name: string }) { 49 + const handle: FileSystemDirectoryHandle | null = (await IDB.get(IDB_DEVICE_KEY)) ?? null; 50 + if (!handle) throw new Error("Storage not configured properly, handle not found."); 51 + const fileHandle = await handle.getFileHandle(name, { create: true }); 52 + const stream = await fileHandle.createWritable(); 53 + await stream.write(data); 54 + await stream.close(); 55 + }