make the webworker typed for type safety

This commit is contained in:
Lily Tsuru 2024-09-08 18:53:07 -04:00
parent e58a765cfa
commit c8f9c9d9ea
2 changed files with 50 additions and 29 deletions

View file

@ -3,8 +3,10 @@ import { GetKeySym } from "./key";
import { MouseState } from "./mouse";
import {
PlayerConfiguredMessage,
PlayerInputMessage,
PlayerOutputMessage,
} from "./player_worker_messages";
import { TypedWorker } from "./typed_worker";
class Client {
private uri: string;
@ -21,7 +23,8 @@ class Client {
) as HTMLDivElement;
private webSocket: WebSocket;
private player: Worker | null = null;
private player: TypedWorker<PlayerInputMessage, PlayerOutputMessage> | null =
null;
private mouse = new MouseState();
@ -127,40 +130,40 @@ class Client {
if (this.player == null) {
let offscreen = this.canvas.transferControlToOffscreen();
this.player = new Worker(new URL("./player_worker.ts", import.meta.url), {
type: "module",
});
this.player = new TypedWorker<PlayerInputMessage, PlayerOutputMessage>(
new URL("./player_worker.ts", import.meta.url),
{
type: "module",
}
);
this.player.addEventListener(
"message",
(message: MessageEvent<PlayerOutputMessage>) => {
switch (message.data.type) {
case "configured": {
// set the message
let configMessage = message.data as PlayerConfiguredMessage;
let hwLabelElement = document.getElementById(
"hw-label"
) as HTMLSpanElement;
this.player.onMessage = (message: PlayerOutputMessage) => {
switch (message.type) {
case "configured": {
// set the message
let configMessage = message as PlayerConfiguredMessage;
let hwLabelElement = document.getElementById(
"hw-label"
) as HTMLSpanElement;
if (configMessage.usingHwDecode) {
if (!hwLabelElement.classList.contains("hw-good")) {
hwLabelElement.classList.add("hw-good");
hwLabelElement.innerText = "IS :)";
}
} else {
if (!hwLabelElement.classList.contains("hw-bad")) {
hwLabelElement.classList.add("hw-bad");
hwLabelElement.innerText = "is NOT :(";
}
if (configMessage.usingHwDecode) {
if (!hwLabelElement.classList.contains("hw-good")) {
hwLabelElement.classList.add("hw-good");
hwLabelElement.innerText = "IS :)";
}
} else {
if (!hwLabelElement.classList.contains("hw-bad")) {
hwLabelElement.classList.add("hw-bad");
hwLabelElement.innerText = "is NOT :(";
}
}
}
}
);
};
// Send the init message to the worker to give it
// access to the canvas
this.player.postMessage(
this.player.post(
{
type: "init",
canvas: offscreen,
@ -185,13 +188,13 @@ class Client {
}
OnWSOpen() {
this.player?.postMessage({
this.player?.post({
type: "init-decoder",
});
}
OnWSClosed() {
this.player?.postMessage({
this.player?.post({
type: "shutdown-decoder",
});
@ -203,7 +206,7 @@ class Client {
OnWSMessage(ev: MessageEvent<string | ArrayBuffer>) {
// Video data is binary
if (typeof ev.data !== "string") {
this.player?.postMessage(
this.player?.post(
{
type: "data",
data: ev.data as ArrayBuffer,

View file

@ -0,0 +1,18 @@
// It's like Worker but typed.
export class TypedWorker<TInput, TOutput> {
private worker;
public onMessage: null | ((m: TOutput) => void) = null;
constructor(uri: URL | string, opts?: WorkerOptions) {
this.worker = new Worker(uri, opts);
let self = this;
this.worker.addEventListener("message", (m: MessageEvent<TOutput>) => {
if (self.onMessage) self.onMessage(m.data);
});
}
post<M extends TInput>(msg: M, transfer?: Transferable[]) {
if (transfer) this.worker.postMessage(msg, transfer);
else this.worker.postMessage(msg);
}
}