95 lines
2.5 KiB
TypeScript
95 lines
2.5 KiB
TypeScript
/**
|
|
* Convert big-endian u32 to native JavaScript number.
|
|
*/
|
|
export function uint_bytes_to_num(value: Uint8Array): number {
|
|
if (value.length != 4) { throw new Error("can't convert non 4-byte integer"); }
|
|
const data_view = new DataView(value.buffer);
|
|
return data_view.getUint32(0, false);
|
|
}
|
|
|
|
export function utf8_encode(value: string): Uint8Array {
|
|
const encoder = new TextEncoder();
|
|
return encoder.encode(value);
|
|
}
|
|
|
|
export function utf8_decode(value: Uint8Array): string {
|
|
const decoder = new TextDecoder("utf-8");
|
|
return decoder.decode(value);
|
|
}
|
|
|
|
export async function sleep(millis: number): Promise<void> {
|
|
await new Promise<void>((resolver) => {
|
|
setTimeout(resolver, millis);
|
|
});
|
|
}
|
|
|
|
export namespace el {
|
|
function add_classes(target: HTMLElement, classes?: string[]): void {
|
|
if (classes === undefined) { return; }
|
|
for (const cls of classes) {
|
|
target.classList.add(cls);
|
|
}
|
|
}
|
|
|
|
export function div(children: HTMLElement[], classes?: string[]): HTMLDivElement {
|
|
const el = document.createElement("div");
|
|
add_classes(el, classes);
|
|
el.append(...children);
|
|
return el;
|
|
}
|
|
|
|
export function h1(text: string, classes?: string[]): HTMLHeadingElement {
|
|
const el = document.createElement("h1");
|
|
el.innerText = text;
|
|
add_classes(el, classes);
|
|
return el;
|
|
}
|
|
|
|
export function h2(text: string, classes?: string[]): HTMLHeadingElement {
|
|
const el = document.createElement("h2");
|
|
el.innerText = text;
|
|
add_classes(el, classes);
|
|
return el;
|
|
}
|
|
|
|
export function p(text: string, classes?: string[]): HTMLParagraphElement {
|
|
const el = document.createElement("p");
|
|
el.innerText = text;
|
|
add_classes(el, classes);
|
|
return el;
|
|
}
|
|
|
|
export async function img(src: string, classes?: string[]): Promise<HTMLImageElement> {
|
|
const el = new Image();
|
|
el.src = src;
|
|
el.draggable = false;
|
|
add_classes(el, classes);
|
|
await new Promise<void>((resolver) => {
|
|
el.addEventListener("load", () => { resolver(); });
|
|
});
|
|
return el;
|
|
}
|
|
|
|
export async function video(
|
|
src: string,
|
|
subtitles_url: string | null,
|
|
classes?: string[],
|
|
): Promise<HTMLVideoElement> {
|
|
const blob = await (await fetch(src)).blob();
|
|
const el = document.createElement("video");
|
|
el.autoplay = true;
|
|
const source = document.createElement("source");
|
|
source.src = URL.createObjectURL(blob);
|
|
el.appendChild(source);
|
|
if (subtitles_url !== null) {
|
|
const subs = document.createElement("track");
|
|
subs.src = subtitles_url;
|
|
subs.kind = "subtitles";
|
|
subs.default = true;
|
|
el.appendChild(subs);
|
|
}
|
|
add_classes(el, classes);
|
|
return el;
|
|
}
|
|
}
|