From c5c9da6a7ed83761fe5f7741705ddb347f1c7202 Mon Sep 17 00:00:00 2001 From: Hayden <64056131+hay-kot@users.noreply.github.com> Date: Wed, 2 Aug 2023 11:49:10 -0500 Subject: [PATCH] refactor event system to use composables --- frontend/composables/use-server-events.ts | 67 +++++++++++++++++++++++ frontend/layouts/default.vue | 37 +++++-------- 2 files changed, 80 insertions(+), 24 deletions(-) create mode 100644 frontend/composables/use-server-events.ts diff --git a/frontend/composables/use-server-events.ts b/frontend/composables/use-server-events.ts new file mode 100644 index 0000000..f394c04 --- /dev/null +++ b/frontend/composables/use-server-events.ts @@ -0,0 +1,67 @@ +export enum ServerEvent { + LocationMutation = "location.mutation", + ItemMutation = "item.mutation", + LabelMutation = "label.mutation", +} + +export type EventMessage = { + event: ServerEvent; +}; + +let socket: WebSocket | null = null; + +const listeners = new Map void)[]>(); + +function connect(onmessage: (m: EventMessage) => void) { + const ws = new WebSocket(`ws://${window.location.host}/api/v1/ws/events`); + + ws.onopen = () => { + console.debug("connected to server"); + }; + + ws.onclose = () => { + console.debug("disconnected from server"); + setTimeout(() => { + connect(onmessage); + }, 3000); + }; + + ws.onerror = err => { + console.error("websocket error", err); + }; + + ws.onmessage = msg => { + onmessage(JSON.parse(msg.data)); + }; + + socket = ws; +} + +export function onServerEvent(event: ServerEvent, callback: () => void) { + if (socket === null) { + connect(e => { + listeners.get(e.event)?.forEach(c => c()); + }); + } + + onMounted(() => { + if (!listeners.has(event)) { + listeners.set(event, []); + } + listeners.get(event)?.push(callback); + }); + + onUnmounted(() => { + const got = listeners.get(event); + if (got) { + listeners.set( + event, + got.filter(c => c !== callback) + ); + } + + if (listeners.get(event)?.length === 0) { + listeners.delete(event); + } + }); +} diff --git a/frontend/layouts/default.vue b/frontend/layouts/default.vue index 81a8b83..e5e590c 100644 --- a/frontend/layouts/default.vue +++ b/frontend/layouts/default.vue @@ -178,31 +178,20 @@ const locationStore = useLocationStore(); - type EventMessage = { - event: string; - }; + onServerEvent(ServerEvent.LabelMutation, () => { + labelStore.refresh(); + }); - onMounted(() => { - const ws = new WebSocket(`ws://${window.location.host}/api/v1/ws/events`); - ws.onmessage = event => { - const msg: EventMessage = JSON.parse(event.data); - console.debug("recieved event", msg); - switch (msg.event) { - case "label.mutation": - labelStore.refresh(); - break; - case "location.mutation": - locationStore.refreshChildren(); - locationStore.refreshParents(); - break; - case "item.mutation": - // item mutations can affect locations counts - // so we need to refresh those as well - locationStore.refreshChildren(); - locationStore.refreshParents(); - break; - } - }; + onServerEvent(ServerEvent.LocationMutation, () => { + locationStore.refreshChildren(); + locationStore.refreshParents(); + }); + + onServerEvent(ServerEvent.ItemMutation, () => { + // item mutations can affect locations counts + // so we need to refresh those as well + locationStore.refreshChildren(); + locationStore.refreshParents(); }); const authCtx = useAuthContext();