Add serial number display
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user