From ad1866146410c4435d5ca82930d21aebd28fa10c Mon Sep 17 00:00:00 2001 From: Jonathan Raphaelson Date: Sat, 11 Oct 2025 14:34:05 -0600 Subject: [PATCH] fixed custom event bubbling --- src/client/page-app.tsx | 6 ++++- src/client/realm/service-connection.ts | 5 +++- src/client/skypod/context.tsx | 36 ++++++++++++++------------ src/client/skypod/feed-fetch.worker.ts | 2 ++ src/cmd/server.ts | 2 +- 5 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/client/page-app.tsx b/src/client/page-app.tsx index 36a6812..b83f57a 100644 --- a/src/client/page-app.tsx +++ b/src/client/page-app.tsx @@ -17,10 +17,14 @@ export const App: preact.FunctionComponent = () => { const connectionFallback = (p: RealmConnectionFallbackProps) => p.error ?

Connection Error! {p.error.message}

:

Connection Loading

+ const wshost = window.location.host + const wsproto = window.location.protocol === 'https' ? 'wss' : 'ws' + const wsurl = `${wsproto}://${wshost}/stream` + return ( - + diff --git a/src/client/realm/service-connection.ts b/src/client/realm/service-connection.ts index b7d0423..4db5342 100644 --- a/src/client/realm/service-connection.ts +++ b/src/client/realm/service-connection.ts @@ -92,6 +92,7 @@ export class RealmConnection extends EventTarget { } send(identid: IdentID, data: T) { + console.debug('sending:', identid, data) this.sendRaw(identid, JSON.stringify(data)) } @@ -103,6 +104,7 @@ export class RealmConnection extends EventTarget { } broadcast(data: unknown, self = false) { + console.debug('broadcasting:', self, data) this.broadcastRaw(JSON.stringify(data), self) } @@ -128,7 +130,7 @@ export class RealmConnection extends EventTarget { } #dispatchCustomEvent(type: string, detail?: object) { - this.dispatchEvent(new CustomEvent(type, {detail})) + this.dispatchEvent(new CustomEvent(type, {bubbles: true, detail})) } // typed helpers @@ -224,6 +226,7 @@ export class RealmConnection extends EventTarget { for (const peerid of resp.dat.peers) { if (peerid === this.#identity.identid) continue + console.debug('connecting...:', peerid) this.#connectPeer(peerid, true) } diff --git a/src/client/skypod/context.tsx b/src/client/skypod/context.tsx index 3679a29..a28fea5 100644 --- a/src/client/skypod/context.tsx +++ b/src/client/skypod/context.tsx @@ -1,4 +1,3 @@ -import {useSignalEffect} from '@preact/signals' import {createContext} from 'preact' import {useContext, useEffect, useRef} from 'preact/hooks' import {z} from 'zod/v4' @@ -81,10 +80,16 @@ export const SkypodProvider: preact.FunctionComponent<{children: preact.Componen }, ]) - const context: SkypodContext = { + const context = useRef({ dispatch: async (action: ActionMap[K]) => { const actions = [action] as Action[] + // broadcast if not a local action + if (!action.opt?.local) { + realm.value?.broadcast(action, false) + // TODO: queue these for rebroadcast if not connected + } + for (const action of actions) { for (const mware of middleware.current) { const mwarefn = @@ -99,11 +104,6 @@ export const SkypodProvider: preact.FunctionComponent<{children: preact.Componen } } } - - // no-op if not connected - if (!action.opt?.local) { - realm.value?.broadcast(action, false) - } } }, @@ -151,11 +151,11 @@ export const SkypodProvider: preact.FunctionComponent<{children: preact.Componen middleware.current = [...prefix, ...suffix] } }, - } + }) // watch the connection // while we're connected, watch peers for action messages - useSignalEffect(() => { + useEffect(() => { const connection = realm.value if (!connection?.connected) return @@ -165,7 +165,7 @@ export const SkypodProvider: preact.FunctionComponent<{children: preact.Componen const parsed = schema.safeParse(event.detail.data) if (parsed.success) { console.log('handling forwarded event:', parsed) - context.dispatch({...parsed.data, opt: {local: true}}).catch((ex: unknown) => { + context.current.dispatch({...parsed.data, opt: {local: true}}).catch((ex: unknown) => { console.error('couldnt dispatch realm action!', ex) }) } @@ -175,7 +175,7 @@ export const SkypodProvider: preact.FunctionComponent<{children: preact.Componen return () => { connection.removeEventListener('peerdata', handler as EventListener) } - }) + }, [context, realm.value]) const patchSchema = z.union([ z.object({ @@ -199,11 +199,15 @@ export const SkypodProvider: preact.FunctionComponent<{children: preact.Componen console.log('message from fetch worker', parsed) switch (parsed.data?.msg) { - case 'patch': - await context.dispatch( - context.action('feed:patch', {url: parsed.data.key, payload: parsed.data.changes}), - ) + case 'patch': { + const action = context.current.action('feed:patch', { + url: parsed.data.key, + payload: parsed.data.changes, + }) + console.log('sending action:', action) + await context.current.dispatch(action) break + } case 'error': default: @@ -224,7 +228,7 @@ export const SkypodProvider: preact.FunctionComponent<{children: preact.Componen }) console.log('rendering the skypod context') - return {props.children} + return {props.children} } export function useSkypod() { diff --git a/src/client/skypod/feed-fetch.worker.ts b/src/client/skypod/feed-fetch.worker.ts index e28576a..1b70ac2 100644 --- a/src/client/skypod/feed-fetch.worker.ts +++ b/src/client/skypod/feed-fetch.worker.ts @@ -74,6 +74,7 @@ class FeedFetch { key: feed.url, changes: { ...parsed, + lock: null, lastRefresh: { hp: 100, at: lock, @@ -91,6 +92,7 @@ class FeedFetch { msg: 'patch', key: feed.url, changes: { + lock: null, lastRefresh: { hp: feed.lastRefresh.hp - 10, at: lock, diff --git a/src/cmd/server.ts b/src/cmd/server.ts index f318ac2..937b234 100644 --- a/src/cmd/server.ts +++ b/src/cmd/server.ts @@ -11,7 +11,7 @@ const __dirname = dirname(__filename) const args = parseArgs({ args: process.argv.slice(2), options: { - port: {type: 'string', default: '3001'}, + port: {type: 'string', default: '4001'}, host: {type: 'string', default: '127.0.0.1'}, }, }) -- 2.51.2