Experiment to rebuild Diffuse using web applets.

refactor: Easier reactive state + some other improvements

+27 -39
+1 -1
src/pages/engines/audio/index.astro src/pages/engine/audio/index.astro
··· 2 2 import Applet from "../../../layouts/applet.astro"; 3 3 --- 4 4 5 - <Applet title="Diffuse engines/audio applet"> 5 + <Applet title="Diffuse engine/audio applet"> 6 6 <div id="container"> 7 7 <audio 8 8 src="https://archive.org/download/lp_moonlight-sonata_ludwig-van-beethoven-frdric-chopin-alexand/disc1%2F01.02.%20Moonlight%20Sonata%20Op.%2027%2C%20No.%202%20In%20C%20Sharp%20Minor%3A%20Allegretto.mp3?tunnel=1"
+1 -1
src/pages/engines/audio/manifest.json.ts src/pages/engine/audio/manifest.json.ts
··· 1 1 import { manifest } from "../../../common/pages/manifest.ts"; 2 2 3 3 export const GET = manifest({ 4 - name: "diffuse/engines/audio", 4 + name: "diffuse/engine/audio", 5 5 entrypoint: "index.html", 6 6 actions: { 7 7 load: {
+23 -35
src/pages/index.astro
··· 3 3 --- 4 4 5 5 <Page title="Diffuse Applets Usage Example"> 6 - <iframe src="engines/audio/" frameborder="0" height="0" width="0"></iframe> 7 - <iframe src="interface/audio/" frameborder="0" style="width: 100%"></iframe> 6 + <iframe src="engine/audio/" frameborder="0" height="0" width="0"></iframe> 7 + <iframe src="ui/audio/" frameborder="0" style="width: 100%"></iframe> 8 8 </Page> 9 9 10 10 <style> 11 11 body { 12 - background: darkgray; 12 + background: darkgrey; 13 13 } 14 14 </style> 15 15 ··· 18 18 import { effect, signal } from "spellcaster/spellcaster.js"; 19 19 20 20 //////////////////////////////////////////// 21 - // 🗂️ Applet index 21 + // 🗂️ Applets 22 22 //////////////////////////////////////////// 23 - const index = { 24 - engines: { 25 - audio: await applet("engines/audio"), 26 - }, 27 - interface: { 28 - audio: await applet("interface/audio", { setHeight: true }), 29 - }, 23 + const engine = { 24 + audio: await applet("engine/audio"), 25 + }; 26 + 27 + const ui = { 28 + audio: await applet("ui/audio", { setHeight: true }), 30 29 }; 31 30 32 31 //////////////////////////////////////////// 33 32 // ⚡ Connect applets 34 33 //////////////////////////////////////////// 35 - index.interface.audio.ondata = (event) => { 36 - if (event.data.isPlaying) { 37 - index.engines.audio.sendAction("play", null); 38 - } else { 39 - index.engines.audio.sendAction("pause", null); 40 - } 41 - }; 42 - 43 - reactive(index.engines.audio, "isPlaying", (isPlaying: boolean) => 44 - index.interface.audio.sendAction("set_is_playing", isPlaying), 34 + reactive(ui.audio, (isPlaying: boolean) => 35 + engine.audio.sendAction(isPlaying ? "play" : "pause", null), 45 36 ); 46 37 47 - reactive(index.engines.audio, "progress", (progress: number) => 48 - index.interface.audio.sendAction("set_progress", progress), 49 - ); 38 + reactive(engine.audio, (isPlaying: boolean) => ui.audio.sendAction("set_is_playing", isPlaying)); 39 + reactive(engine.audio, (progress: number) => ui.audio.sendAction("set_progress", progress)); 50 40 51 41 //////////////////////////////////////////// 52 42 // 🪟 Applet initialiser ··· 56 46 `[src="${src}${src.endsWith("/") ? "" : "/"}"]`, 57 47 ); 58 48 59 - if (opts.setHeight) { 60 - frame.addEventListener( 61 - "load", 62 - () => { 63 - frame.height = frame.contentWindow.document.body.scrollHeight + "px"; 64 - }, 65 - { once: true }, 66 - ); 67 - } 49 + const applet = await applets.connect(frame.contentWindow); 50 + if (opts.setHeight) applet.onresize = () => (frame.height = `${applet.height}px`); 68 51 69 - return await applets.connect(frame.contentWindow); 52 + return applet; 70 53 } 71 54 72 55 //////////////////////////////////////////// 73 56 // 🔮 Reactive state management 74 57 //////////////////////////////////////////// 75 - function reactive<P extends string, T>(applet: Applet, property: P, effectFn: (t: T) => void) { 58 + function reactive<P extends string, T>(applet: Applet, effectFn: (t: T) => void) { 59 + const property = effectFn 60 + .toString() 61 + .slice(1) 62 + .match(/([^(\)|,|\s)]+)/)[1]; 63 + 76 64 const [getter, setter] = signal(applet.data[property] as T); 77 65 78 66 effect(() => effectFn(getter()));
+1 -1
src/pages/interface/audio/index.astro src/pages/ui/audio/index.astro
··· 2 2 import Applet from "../../../layouts/applet.astro"; 3 3 --- 4 4 5 - <Applet title="Diffuse interface/audio applet"> 5 + <Applet title="Diffuse ui/audio applet"> 6 6 <div 7 7 style="background: dimgray; color: white; height: 100px; line-height: 100px; text-align: center;" 8 8 >
+1 -1
src/pages/interface/audio/manifest.json.ts src/pages/ui/audio/manifest.json.ts
··· 1 1 import { manifest } from "../../../common/pages/manifest.ts"; 2 2 3 3 export const GET = manifest({ 4 - name: "diffuse/interface/audio", 4 + name: "diffuse/ui/audio", 5 5 entrypoint: "index.html", 6 6 actions: { 7 7 set_is_playing: {