import { OVar, e } from "../jshelper/mod.ts"; document.addEventListener("DOMContentLoaded", () => { if (document.body.classList.contains("player")) { const node_id = globalThis.location.pathname.split("/")[2]; const main = document.getElementById("main")!; initialize_player(main, node_id) } }) function initialize_player(el: HTMLElement, node_id: string) { el.innerHTML = "" // clear the body const buffering_state = new OVar(true) const playing_state = new OVar(false) const current_time = new OVar(0) const remaining_time = new OVar(0) const vel = e("video") vel.src = `/n/${node_id}/stream?tracks=1&tracks=0&format=matroska&webm=true` const toggle_playing = () => vel.paused ? vel.play() : vel.pause() let pri_current: HTMLElement; let pri: HTMLElement; const controls = e("div", { class: "jsp-controls" }, playing_state.map(playing => e("button", playing ? "||" : "|>", { onclick: toggle_playing })), e("p", { class: "jsp-status" }, current_time.map(v => e("span", display_time(v))), e("br"), remaining_time.map(v => e("span", display_time(v))) ), pri = e("div", { class: "jsp-pri" }, pri_current = e("div", { class: "jsp-pri-current" })), e("button", "X", { onclick() { if (document.fullscreenElement) document.exitFullscreen() else document.documentElement.requestFullscreen() } }) ) vel.onloadedmetadata = () => { } vel.ondurationchange = () => { } vel.ontimeupdate = () => { remaining_time.value = vel.currentTime - vel.duration; current_time.value = vel.currentTime pri_current.style.width = (vel.currentTime / vel.duration * 100) + "%" } vel.onplay = () => { buffering_state.value = false; } vel.onwaiting = () => { buffering_state.value = true; } vel.onplaying = () => { playing_state.value = true; } vel.onpause = () => { playing_state.value = false } mouse_idle(vel, 1000, idle => { controls.style.opacity = idle ? "0" : "1" vel.style.cursor = idle ? "none" : "default" }) vel.addEventListener("click", toggle_playing) pri.addEventListener("mousedown", ev => { const r = pri.getBoundingClientRect() const p = (ev.clientX - r.left) / (r.right - r.left) vel.currentTime = p * vel.duration }) document.body.addEventListener("keydown", k => { if (k.code == "Period") vel["seekToNextFrame" as "play"]() else if (k.code == "Space") toggle_playing() else if (k.code == "ArrowLeft") vel.currentTime -= 5 else if (k.code == "ArrowRight") vel.currentTime += 5 else if (k.code == "ArrowUp") vel.currentTime -= 60 else if (k.code == "ArrowDown") vel.currentTime += 60 else return; k.preventDefault() }) el.append(e("div", { class: "jsp" }, vel, controls, )) } function mouse_idle(e: HTMLElement, timeout: number, cb: (b: boolean) => unknown) { let ct: number; let idle = false e.onmouseleave = () => { clearTimeout(ct) } e.onmousemove = () => { clearTimeout(ct) if (idle) { idle = false cb(idle) } ct = setTimeout(() => { idle = true cb(idle) }, timeout) } } function display_time(t: number): string { if (t < 0) return "-" + display_time(-t) let h = 0, m = 0, s = 0; while (t > 3600) t -= 3600, h++; while (t > 60) t -= 60, m++; while (t > 1) t -= 1, s++; return (h ? h + "h" : "") + (m ? m + "m" : "") + (s ? s + "s" : "") }