Experiment to rebuild Diffuse using web applets.
0
fork

Configure Feed

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

refactor: queue

+78 -46
+5 -3
src/pages/engine/audio/_applet.astro
··· 53 53 context.scope.ondata = (event: any) => setDefaultVolume(event.data.volume.default); 54 54 55 55 effect(() => { 56 - const volume = defaultVolume(); 57 - if (volume === undefined) return; 58 - localStorage.setItem(VOLUME_KEY, volume.toString()); 56 + if (context.isMainInstance()) { 57 + const volume = defaultVolume(); 58 + if (volume === undefined) return; 59 + localStorage.setItem(VOLUME_KEY, volume.toString()); 60 + } 59 61 }); 60 62 61 63 ////////////////////////////////////////////
+15 -32
src/pages/engine/queue/_applet.astro
··· 1 1 <script> 2 + import type { Actions } from "@scripts/engine/queue/worker"; 2 3 import type { Track } from "@applets/core/types"; 3 4 import type { State } from "./types.d.ts"; 4 5 5 6 import { register } from "@scripts/applet/common"; 7 + import { endpoint } from "@scripts/common"; 6 8 7 9 //////////////////////////////////////////// 8 10 // SETUP 9 11 //////////////////////////////////////////// 12 + const worker = endpoint<Actions>( 13 + new Worker("../../../scripts/engine/queue/worker", { type: "module" }), 14 + ); 15 + 16 + // Register applet 10 17 const context = register<State>(); 11 18 12 19 // Initial state ··· 15 22 now: null, 16 23 future: [], 17 24 }; 18 - 19 - // State helpers 20 - function update(partial: Partial<State>): void { 21 - context.data = { ...context.data, ...partial }; 22 - } 23 25 24 26 //////////////////////////////////////////// 25 27 // ACTIONS ··· 29 31 context.setActionHandler("shift", shift); 30 32 context.setActionHandler("unshift", unshift); 31 33 32 - function add(items: Track[]) { 33 - update({ future: [...context.data.future, ...items] }); 34 + async function add(items: Track[]) { 35 + context.data = await worker.call.add(context.data, items); 34 36 } 35 37 36 - // TODO: Shuffle, limit track amount, etc. 37 - function fill(availableItems: Track[]) { 38 - add(availableItems); 39 - 40 - // Automatically insert track if there isn't any 41 - if (!context.data.now) shift(); 38 + async function fill(availableItems: Track[]) { 39 + context.data = await worker.call.fill(context.data, availableItems); 42 40 } 43 41 44 - function shift() { 45 - const now = context.data.future[0] || null; 46 - const future = context.data.future.slice(1); 47 - const past = context.data.now ? [...context.data.past, context.data.now] : context.data.past; 48 - 49 - update({ past, now, future }); 50 - 51 - return now; 42 + async function shift() { 43 + context.data = await worker.call.shift(context.data); 52 44 } 53 45 54 - function unshift() { 55 - if (context.data.past.length === 0) return; 56 - 57 - const past = [...context.data.past]; 58 - const [last] = past.splice(past.length - 1, 1); 59 - const now = last ?? null; 60 - const future = context.data.now 61 - ? [context.data.now, ...context.data.future] 62 - : context.data.future; 63 - 64 - update({ past, now, future }); 46 + async function unshift() { 47 + context.data = await worker.call.unshift(context.data); 65 48 } 66 49 </script>
+1 -7
src/pages/engine/queue/types.d.ts
··· 1 - import type { Track } from "@applets/core/types"; 2 - 3 - export interface State<Stats = TrackStats, Tags = TrackTags> { 4 - past: Track<Stats, Tags>[]; 5 - now: Track<Stats, Tags> | null; 6 - future: Track<Stats, Tags>[]; 7 - } 1 + export * from "@scripts/engine/queue/types.d.ts";
+1 -4
src/pages/input/opensubsonic/_applet.astro
··· 27 27 // SETUP 28 28 //////////////////////////////////////////// 29 29 const worker = endpoint<Actions>( 30 - new Worker("../../../scripts/input/opensubsonic/worker", { 31 - type: "module", 32 - }), 33 - self as any, 30 + new Worker("../../../scripts/input/opensubsonic/worker", { type: "module" }), 34 31 ); 35 32 36 33 // Register applet
+7
src/scripts/engine/queue/types.d.ts
··· 1 + import type { Track } from "@applets/core/types"; 2 + 3 + export interface State<Stats = TrackStats, Tags = TrackTags> { 4 + past: Track<Stats, Tags>[]; 5 + now: Track<Stats, Tags> | null; 6 + future: Track<Stats, Tags>[]; 7 + }
+49
src/scripts/engine/queue/worker.ts
··· 1 + import type { Track } from "@applets/core/types.js"; 2 + import { expose } from "../../../scripts/common.ts"; 3 + import type { State } from "./types"; 4 + 5 + //////////////////////////////////////////// 6 + // ACTIONS 7 + //////////////////////////////////////////// 8 + const actions = expose({ 9 + add, 10 + fill, 11 + shift, 12 + unshift, 13 + }); 14 + 15 + export type Actions = typeof actions; 16 + 17 + // Actions 18 + 19 + function add(state: State, items: Track[]): State { 20 + return { ...state, future: [...state.future, ...items] }; 21 + } 22 + 23 + // TODO: Shuffle, limit track amount, etc. 24 + function fill(state: State, availableItems: Track[]): State { 25 + state = add(state, availableItems); 26 + 27 + // Automatically insert track if there isn't any 28 + if (!state.now) return shift(state); 29 + return state; 30 + } 31 + 32 + function shift(state: State): State { 33 + const now = state.future[0] || null; 34 + const future = state.future.slice(1); 35 + const past = state.now ? [...state.past, state.now] : state.past; 36 + 37 + return { past, now, future }; 38 + } 39 + 40 + function unshift(state: State): State { 41 + if (state.past.length === 0) return state; 42 + 43 + const past = [...state.past]; 44 + const [last] = past.splice(past.length - 1, 1); 45 + const now = last ?? null; 46 + const future = state.now ? [state.now, ...state.future] : state.future; 47 + 48 + return { past, now, future }; 49 + }