Experiment to rebuild Diffuse using web applets.
0
fork

Configure Feed

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

refactor: Introduce `reactive` helper fn

+23 -19
+23 -19
src/pages/index.astro
··· 14 14 </style> 15 15 16 16 <script> 17 - import { applets } from "@web-applets/sdk"; 17 + import { type Applet, type AppletEvent, applets } from "@web-applets/sdk"; 18 18 import { effect, signal } from "spellcaster/spellcaster.js"; 19 19 20 20 //////////////////////////////////////////// ··· 28 28 audio: await applet("interface/audio", { setHeight: true }), 29 29 }, 30 30 }; 31 - 32 - //////////////////////////////////////////// 33 - // 🔮 Signals & effects 34 - //////////////////////////////////////////// 35 - const [progress, setProgress] = signal(0); 36 - const [isPlaying, setIsPlaying] = signal(false); 37 - 38 - effect(() => index.interface.audio.sendAction("set_is_playing", isPlaying())); 39 - effect(() => index.interface.audio.sendAction("set_progress", progress())); 40 31 41 32 //////////////////////////////////////////// 42 33 // ⚡ Connect applets 43 34 //////////////////////////////////////////// 44 - index.engines.audio.ondata = (event) => { 45 - // NOTE: Instead of sending actions to the audio interface every time 46 - // this event is dispatched, which is at least every second when 47 - // audio is playing, we use signals and effects to manage that. 48 - setIsPlaying(event.data.isPlaying); 49 - setProgress(event.data.progress); 50 - }; 51 - 52 35 index.interface.audio.ondata = (event) => { 53 36 if (event.data.isPlaying) { 54 37 index.engines.audio.sendAction("play", null); ··· 57 40 } 58 41 }; 59 42 43 + reactive(index.engines.audio, "isPlaying", (isPlaying: boolean) => 44 + index.interface.audio.sendAction("set_is_playing", isPlaying), 45 + ); 46 + 47 + reactive(index.engines.audio, "progress", (progress: number) => 48 + index.interface.audio.sendAction("set_progress", progress), 49 + ); 50 + 60 51 //////////////////////////////////////////// 61 - // 🛠️ Applet initialiser 52 + // 🪟 Applet initialiser 62 53 //////////////////////////////////////////// 63 54 async function applet(src: string, opts: { setHeight?: boolean } = {}) { 64 55 const frame: HTMLIFrameElement = document.querySelector( ··· 76 67 } 77 68 78 69 return await applets.connect(frame.contentWindow); 70 + } 71 + 72 + //////////////////////////////////////////// 73 + // 🔮 Reactive state management 74 + //////////////////////////////////////////// 75 + function reactive<P extends string, T>(applet: Applet, property: P, effectFn: (t: T) => void) { 76 + const [getter, setter] = signal(applet.data[property] as T); 77 + 78 + effect(() => effectFn(getter())); 79 + 80 + applet.addEventListener("data", (event: AppletEvent) => { 81 + setter(event.data[property]); 82 + }); 79 83 } 80 84 </script>