typed events

This commit is contained in:
Chris Wanstrath 2025-10-08 10:38:41 -07:00
parent 52aae6c8f0
commit dd7ca72f3a
4 changed files with 54 additions and 14 deletions

View File

@ -1,5 +1,5 @@
//// ////
// version: 7f31112 // version: 52aae6c
// src/js/dom.ts // src/js/dom.ts
var content2 = $("content"); var content2 = $("content");
@ -160,6 +160,16 @@ function handleOutput(msg) {
addOutput(id, result.output); addOutput(id, result.output);
} }
// src/js/event.ts
function fire(eventName, detail) {
window.dispatchEvent(new CustomEvent(eventName, { detail }));
}
function on(eventName, handler) {
const listener = handler;
window.addEventListener(eventName, listener);
return () => window.removeEventListener(eventName, listener);
}
// src/js/session.ts // src/js/session.ts
var sessionId = randomId(); var sessionId = randomId();
var sessionStore = new Map; var sessionStore = new Map;
@ -167,13 +177,13 @@ function initSession() {}
function handleSessionStart(msg) { function handleSessionStart(msg) {
for (const key of Object.keys(msg.data)) for (const key of Object.keys(msg.data))
sessionStore.set(key, msg.data[key] || ""); sessionStore.set(key, msg.data[key] || "");
window.dispatchEvent(new CustomEvent("session:update", { detail: msg.data })); fire("session:update", msg.data);
mode(msg.data.mode); mode(msg.data.mode);
} }
function handleSessionUpdate(msg) { function handleSessionUpdate(msg) {
for (const key of Object.keys(msg.data)) for (const key of Object.keys(msg.data))
sessionStore.set(key, msg.data[key] || ""); sessionStore.set(key, msg.data[key] || "");
window.dispatchEvent(new CustomEvent("session:update", { detail: msg.data })); fire("session:update", msg.data);
} }
// src/js/webapp.ts // src/js/webapp.ts
@ -1293,8 +1303,8 @@ function initStatusbar() {
registerEvents(); registerEvents();
} }
function registerEvents() { function registerEvents() {
window.addEventListener("apps:change", (e) => updateWww(sessionStore.get("project") || "root")); on("apps:change", (e) => updateWww(sessionStore.get("project") || "root"));
window.addEventListener("session:update", (e) => { on("session:update", (e) => {
const ev = e; const ev = e;
const data = ev.detail; const data = ev.detail;
if (data.project) if (data.project)

31
src/js/event.ts Normal file
View File

@ -0,0 +1,31 @@
////
// Custom event system
type Events = {
"apps:change": {},
"session:update": Record<string, string>,
}
export function fire<K extends keyof Events>(eventName: K, detail: Events[K]) {
window.dispatchEvent(new CustomEvent(eventName, { detail }))
}
export function on<K extends keyof Events>(eventName: K, handler: (e: CustomEvent<Events[K]>) => void) {
const listener = handler as EventListener
window.addEventListener(eventName, listener)
// cleanup
return () => window.removeEventListener(eventName, listener)
}
export function once<K extends keyof Events>(eventName: K, handler: (e: CustomEvent<Events[K]>) => void) {
const listener = handler as EventListener;
window.addEventListener(eventName, listener, { once: true })
// cleanup
return () => window.removeEventListener(eventName, listener)
}
export function off<K extends keyof Events>(eventName: K, handler: (e: CustomEvent<Events[K]>) => void) {
window.removeEventListener(eventName, handler as EventListener)
}

View File

@ -5,6 +5,7 @@
import type { SessionStartMessage, SessionUpdateMessage } from "@/shared/types" import type { SessionStartMessage, SessionUpdateMessage } from "@/shared/types"
import { randomId } from "../shared/utils" import { randomId } from "../shared/utils"
import { mode } from "./commands" import { mode } from "./commands"
import { fire } from "./event"
export const sessionId = randomId() export const sessionId = randomId()
export const sessionStore = new Map<string, string>() export const sessionStore = new Map<string, string>()
@ -15,8 +16,7 @@ export function handleSessionStart(msg: SessionStartMessage) {
for (const key of Object.keys(msg.data)) for (const key of Object.keys(msg.data))
sessionStore.set(key, (msg.data as any)[key] || "") sessionStore.set(key, (msg.data as any)[key] || "")
window.dispatchEvent(new CustomEvent("session:update", { detail: msg.data })) fire("session:update", msg.data)
mode(msg.data.mode) mode(msg.data.mode)
} }
@ -24,5 +24,5 @@ export function handleSessionUpdate(msg: SessionUpdateMessage) {
for (const key of Object.keys(msg.data)) for (const key of Object.keys(msg.data))
sessionStore.set(key, msg.data[key] || "") sessionStore.set(key, msg.data[key] || "")
window.dispatchEvent(new CustomEvent("session:update", { detail: msg.data })) fire("session:update", msg.data)
} }

View File

@ -2,6 +2,7 @@
// Temporarily display a message to the user in the status bar. // Temporarily display a message to the user in the status bar.
import { $ } from "./dom" import { $ } from "./dom"
import { on } from "./event"
import { sessionStore } from "./session" import { sessionStore } from "./session"
import { apps } from "./webapp" import { apps } from "./webapp"
@ -21,19 +22,17 @@ export function initStatusbar() {
} }
function registerEvents() { function registerEvents() {
window.addEventListener("apps:change", e => on("apps:change", e =>
updateWww(sessionStore.get("project") || "root") updateWww(sessionStore.get("project") || "root")
) )
window.addEventListener("session:update", (e) => { on("session:update", (e) => {
const ev = e as CustomEvent const ev = e as CustomEvent
const data = ev.detail const data = ev.detail
if (data.project) if (data.project) updateProjectName(data.project)
updateProjectName(data.project)
if (data.cwd) if (data.cwd) updateCwd(data.cwd)
updateCwd(data.cwd)
}) })
} }