bluetooth-buzzer/src/routes/+page.svelte
Dorian Zedler 48fe73611d
All checks were successful
/ build (push) Successful in 3m40s
Fix: properly wait for audio
2024-01-20 11:16:01 +01:00

98 lines
2.3 KiB
Svelte

<script lang="ts">
import { checkAvailability, doOneTimeSync, startBluetooth } from '$lib/bluetooth';
import { A, Alert, Button } from 'flowbite-svelte';
import { bluetoothState } from '../stores';
import { UAParser } from 'ua-parser-js';
import Timer from './Timer.svelte';
const uap = new UAParser();
let timer: Timer;
let state: 'idle' | 'wait' | 'ready' | 'running' = 'idle';
const delay = (time: number) => {
return new Promise((resolve) => setTimeout(resolve, time));
};
const start = async () => {
state = 'wait';
await delay(3000);
state = 'ready';
const audio = new Audio('/sound/ok-ready-go.mp3');
const audioDone = new Promise<void>((resolve) => {
audio.onended = () => {
resolve();
};
});
await audio.play();
await audioDone;
timer.start(200n);
state = 'running';
};
const PLACEHOLDERS = {
idle: 'Press start!',
wait: 'At your marks!',
ready: 'Ready!',
running: ''
};
$: {
checkAvailability();
}
</script>
<div class="p-8 flex flex-col">
{#if $bluetoothState == 'DISCONNECTED'}
<Button
on:click={() => {
startBluetooth();
}}>Connect</Button
>
{:else if $bluetoothState == 'UNAVAILABLE'}
<span
class="text-xl text-white rounded-md font-bold border-primary-600 border-4 border-r-4 p-3"
>
Your Browser is not compatible with this website, as it does not support <A
class="font-bold"
href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility"
>
web bluetooth
</A>.
</span>
<span class="text-xl mt-3">
Please use a browser which supports web bluetooth, for example
{#if uap.getOS().name === 'iOS'}
<A href="https://apps.apple.com/us/app/bluefy-web-ble-browser/id1492822055">Bluefy</A>
{:else}
<A href="https://www.google.com/chrome/">Google Chrome</A>
{/if}.
</span>
{:else if $bluetoothState == 'CONNECTED'}
<Timer placeholder={PLACEHOLDERS[state]} bind:this={timer} />
<Button
disabled={state == 'wait' || state == 'ready'}
on:click={() => {
if (state == 'idle') {
start();
} else if (state == 'running') {
timer.reset();
state = 'idle';
}
}}
>
{#if state == 'idle'}
Start!
{:else if state == 'running'}
Reset!
{:else}
Wait ...
{/if}
</Button>
{:else}
<Alert color="yellow">Connecting...</Alert>
{/if}
</div>