Add serial number display

This commit is contained in:
daylily
2025-04-05 02:20:17 -04:00
parent 20a21c4650
commit 0583d648aa
4 changed files with 70 additions and 23 deletions
+10 -3
View File
@@ -1,17 +1,24 @@
<script lang="ts"> <script lang="ts">
import type { PopoverTriggerProps } from 'bits-ui' import type { PopoverTriggerProps } from 'bits-ui'
import type { Snippet } from 'svelte'
import IconInfo from '~icons/material-symbols/info' import IconInfo from '~icons/material-symbols/info'
import * as Popover from '$lib/components/ui/popover' import * as Popover from '$lib/components/ui/popover'
interface Props extends PopoverTriggerProps {} interface Props extends PopoverTriggerProps {
icon?: Snippet
}
const { children, ...restProps }: Props = $props() const { icon, children, ...restProps }: Props = $props()
</script> </script>
<Popover.Root> <Popover.Root>
<Popover.Trigger aria-label="More info" {...restProps}> <Popover.Trigger aria-label="More info" {...restProps}>
<IconInfo class="text-muted-foreground text-sm" aria-hidden /> {#if !icon}
<IconInfo class="text-muted-foreground text-sm" aria-hidden />
{:else}
{@render icon()}
{/if}
</Popover.Trigger> </Popover.Trigger>
<Popover.Content class="text-sm"> <Popover.Content class="text-sm">
+18 -6
View File
@@ -27,16 +27,16 @@ export function createDeviceContext(): DeviceContext {
function connectIfIdle(e: HIDConnectionEvent) { function connectIfIdle(e: HIDConnectionEvent) {
if (!isInkclip(e.device) || ctx.device !== null) return if (!isInkclip(e.device) || ctx.device !== null) return
toast.info('Device connected') toast.info('Device connected')
ctx.device = e.device ctx.device = e.device
} }
function disconnectIfSame(e: HIDConnectionEvent) { function disconnectIfSame(e: HIDConnectionEvent) {
if (ctx.device !== e.device) return if (ctx.device !== e.device) return
toast.info('Device disconnected') toast.info('Device disconnected')
ctx.device = null ctx.device = null
} }
navigator.hid.addEventListener('connect', connectIfIdle) navigator.hid.addEventListener('connect', connectIfIdle)
navigator.hid.addEventListener('disconnect', disconnectIfSame) navigator.hid.addEventListener('disconnect', disconnectIfSame)
@@ -48,3 +48,15 @@ export function createDeviceContext(): DeviceContext {
return setContext(DeviceContextToken, ctx) return setContext(DeviceContextToken, ctx)
} }
export async function tryOpenDevice(device: HIDDevice): Promise<boolean> {
if (device.opened) return true
try {
await device.open()
return true
} catch (e) {
toast.error(`Unable to open device: ${e}`)
return false
}
}
+39 -3
View File
@@ -3,9 +3,40 @@
import IconCheckCircle from '~icons/material-symbols/check-circle' import IconCheckCircle from '~icons/material-symbols/check-circle'
import ConnectButton from './ConnectButton.svelte' import ConnectButton from './ConnectButton.svelte'
import { getDeviceContext } from '$lib/contexts/device.svelte' import { getDeviceContext, tryOpenDevice } from '$lib/contexts/device.svelte'
import MoreInfo from '$lib/components/MoreInfo.svelte'
const deviceCtx = getDeviceContext() const deviceCtx = getDeviceContext()
let serial = $state('[Retrieving...]')
async function updateSerial() {
if (deviceCtx.device === null) {
serial = '[Retrieving...]'
return
}
if (!(await tryOpenDevice(deviceCtx.device))) {
serial = '[Error]'
return
}
function setSerial(e: HIDInputReportEvent) {
if (e.reportId !== 0x02) return
serial = String.fromCharCode(...Array.from(new Uint8Array(e.data.buffer)))
}
let updated = false
deviceCtx.device.addEventListener('inputreport', e => {
if (!updated) setSerial(e)
updated = true
})
deviceCtx.device.sendReport(0x02, new Uint8Array(1))
}
$effect(() => {
updateSerial()
})
</script> </script>
<section class="row gap-2 max-lg:stack max-lg:items-stretch" aria-labelledby="connect-section-label"> <section class="row gap-2 max-lg:stack max-lg:items-stretch" aria-labelledby="connect-section-label">
@@ -17,8 +48,13 @@
<IconPending aria-hidden /> Not connected to any device yet. Plug in your device, and click on the button to select <IconPending aria-hidden /> Not connected to any device yet. Plug in your device, and click on the button to select
it. it.
{:else} {:else}
<IconCheckCircle aria-hidden /> Successfully conected to device. If you want to, you can connect to another device <MoreInfo>
instead. {#snippet icon()}
<IconCheckCircle aria-hidden />
{/snippet}
The serial ID of this device is <code>{serial}</code>.
</MoreInfo>
Successfully conected to device. If you want to, you can connect to another device instead.
{/if} {/if}
</div> </div>
</div> </div>
+3 -11
View File
@@ -2,7 +2,7 @@
import { Button } from '$lib/components/ui/button' import { Button } from '$lib/components/ui/button'
import { toast } from 'svelte-sonner' import { toast } from 'svelte-sonner'
import { getDeviceContext } from '$lib/contexts/device.svelte' import { getDeviceContext, tryOpenDevice } from '$lib/contexts/device.svelte'
import { getRenderedContext } from '$lib/contexts/rendered.svelte' import { getRenderedContext } from '$lib/contexts/rendered.svelte'
import { BYTES_IN_A_ROW, DEVICE_HEIGHT, DEVICE_WIDTH, WRITE_TIME } from '$lib/constants' import { BYTES_IN_A_ROW, DEVICE_HEIGHT, DEVICE_WIDTH, WRITE_TIME } from '$lib/constants'
@@ -22,15 +22,7 @@
async function connectAndWrite() { async function connectAndWrite() {
if (deviceCtx.device === null || renderedCtx.rendered === null) return if (deviceCtx.device === null || renderedCtx.rendered === null) return
if (!(await tryOpenDevice(deviceCtx.device))) return
if (!deviceCtx.device.opened) {
try {
await deviceCtx.device.open()
} catch (e) {
toast.error(`Unable to open device: ${e}`)
return
}
}
const buffer = new Uint8Array(DEVICE_HEIGHT * BYTES_IN_A_ROW) const buffer = new Uint8Array(DEVICE_HEIGHT * BYTES_IN_A_ROW)
for (let y = 0; y < DEVICE_HEIGHT; y++) { for (let y = 0; y < DEVICE_HEIGHT; y++) {
@@ -47,7 +39,7 @@
inProgress = true inProgress = true
try { try {
await deviceCtx.device.sendReport(0, buffer) await deviceCtx.device.sendReport(0x01, buffer)
} catch (e) { } catch (e) {
toast.error(`Error writing to device: ${e}`) toast.error(`Error writing to device: ${e}`)
return return