From d3740f20ef1133a391dccb498eac108abea5e4bc Mon Sep 17 00:00:00 2001 From: daylily Date: Sat, 5 Apr 2025 02:18:35 -0400 Subject: [PATCH] Remove event listeners on dismount for reactive primitives --- src/lib/contexts/device.svelte.ts | 20 ++++++++++++++------ src/lib/utils/media.svelte.ts | 9 ++++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/lib/contexts/device.svelte.ts b/src/lib/contexts/device.svelte.ts index 164d8e2..1560100 100644 --- a/src/lib/contexts/device.svelte.ts +++ b/src/lib/contexts/device.svelte.ts @@ -1,5 +1,5 @@ import { DEVICE_PID, DEVICE_VID } from '$lib/constants' -import { getContext, setContext } from 'svelte' +import { getContext, onDestroy, setContext } from 'svelte' import { toast } from 'svelte-sonner' function isInkclip(dev: HIDDevice) { @@ -24,18 +24,26 @@ export function createDeviceContext(): DeviceContext { if (dev !== undefined) ctx.device = dev }) - navigator.hid.addEventListener('connect', e => { - if (isInkclip(e.device) && ctx.device === null) { + function connectIfIdle(e: HIDConnectionEvent) { + if (!isInkclip(e.device) || ctx.device !== null) return + toast.info('Device connected') ctx.device = e.device } - }) - navigator.hid.addEventListener('disconnect', e => { - if (ctx.device === e.device) { + function disconnectIfSame(e: HIDConnectionEvent) { + if (ctx.device !== e.device) return + toast.info('Device disconnected') ctx.device = null } + + navigator.hid.addEventListener('connect', connectIfIdle) + navigator.hid.addEventListener('disconnect', disconnectIfSame) + + onDestroy(() => { + navigator.hid.removeEventListener('connect', connectIfIdle) + navigator.hid.removeEventListener('disconnect', disconnectIfSame) }) return setContext(DeviceContextToken, ctx) diff --git a/src/lib/utils/media.svelte.ts b/src/lib/utils/media.svelte.ts index 34efefc..26b92a1 100644 --- a/src/lib/utils/media.svelte.ts +++ b/src/lib/utils/media.svelte.ts @@ -1,3 +1,5 @@ +import { onDestroy } from 'svelte' + export interface ReactiveMediaQuery { readonly matches: boolean } @@ -7,9 +9,10 @@ export function createMediaQuery(query: string): ReactiveMediaQuery { const queryState = $state({ matches: queryList.matches }) - queryList.addEventListener('change', self => { - queryState.matches = self.matches - }) + const updateQueryState = (e: MediaQueryListEvent) => (queryState.matches = e.matches) + + queryList.addEventListener('change', updateQueryState) + onDestroy(() => queryList.removeEventListener('change', updateQueryState)) return queryState }