diff options
author | metamuffin <metamuffin@disroot.org> | 2023-10-01 12:50:03 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-10-01 12:50:03 +0200 |
commit | 0c0403ebe239dcf6781565a61d1e62e4c81e5db1 (patch) | |
tree | e3abe9c57280ac1b6f886fa7b199a3e6b3529ea4 | |
parent | fc19087e5c1a34d6139892f12520e7b17eda47b4 (diff) | |
download | jellything-0c0403ebe239dcf6781565a61d1e62e4c81e5db1.tar jellything-0c0403ebe239dcf6781565a61d1e62e4c81e5db1.tar.bz2 jellything-0c0403ebe239dcf6781565a61d1e62e4c81e5db1.tar.zst |
port the old jsplayer
-rw-r--r-- | web/js-player.css | 12 | ||||
-rw-r--r-- | web/script/js-player.js | 125 | ||||
m--------- | web/script/jshelper | 0 | ||||
-rw-r--r-- | web/script/main.ts | 1 | ||||
-rw-r--r-- | web/script/player/mod.ts | 120 |
5 files changed, 127 insertions, 131 deletions
diff --git a/web/js-player.css b/web/js-player.css index 79dffa0..b6133f9 100644 --- a/web/js-player.css +++ b/web/js-player.css @@ -4,11 +4,11 @@ Copyright (C) 2023 metamuffin <metamuffin.org> */ -.js-player { +.jsp { --csize: 50px; } -.js-player .controls { +.jsp .jsp-controls { position: absolute; bottom: 0px; left: 0px; @@ -21,7 +21,7 @@ flex-direction: row; } -.js-player .controls button { +.jsp .jsp-controls button { padding: 0px; width: var(--csize); height: 100%; @@ -29,7 +29,7 @@ background-color: #ffffff10; } -.js-player .controls p.status { +.jsp .jsp-controls p.jsp-status { display: inline-block; width: 6em; text-align: right; @@ -38,7 +38,7 @@ margin: 0.4em; } -.pri { +.jsp .jsp-pri { flex-grow: 1; padding: 0px; display: inline-block; @@ -46,7 +46,7 @@ width: calc(100% - var(--csize) * 2 - 2px); height: var(--csize); } -.pri-current { +.jsp .jsp-pri-current { height: var(--csize); background-color: #ffffff20; } diff --git a/web/script/js-player.js b/web/script/js-player.js deleted file mode 100644 index 7c3bb43..0000000 --- a/web/script/js-player.js +++ /dev/null @@ -1,125 +0,0 @@ -/* - This file is part of jellything (https://codeberg.org/metamuffin/jellything) - which is licensed under the GNU Affero General Public License (version 3); see /COPYING. - Copyright (C) 2023 metamuffin <metamuffin.org> -*/ - -globalThis.addEventListener("load", () => { - for (const e of document.getElementsByTagName("video")) - patch_video(e) -}) - -function patch_video(e) { - // move the video to a div - const d = document.createElement("div") - const p = e.parentElement - p.removeChild(e) - d.appendChild(e) - p.prepend(d) - - e.removeAttribute("controls") - d.classList.add("js-player") - - const controls = document.createElement("div") - controls.classList.add("controls") - - const pause_button = document.createElement("button") - pause_button.textContent = "|>" - - const fullscreen_button = document.createElement("button") - fullscreen_button.textContent = "X" - - const status_display = document.createElement("p") - status_display.classList.add("status") - - const pri = document.createElement("div") - pri.classList.add("pri") - const pri_current = document.createElement("div") - pri_current.style.width = "0px" - pri_current.classList.add("pri-current") - pri.append(pri_current) - - controls.append(pause_button, status_display, pri, fullscreen_button) - d.append(controls) - - - e.onloadedmetadata = () => { - - } - e.ondurationchange = () => { - - } - e.ontimeupdate = () => { - status_display.innerHTML = display_time(e.currentTime) + "<br/>" + display_time(e.currentTime - e.duration); // TODO can we have <br> with textContent?! - pri_current.style.width = (e.currentTime / e.duration * 100) + "%" - } - e.onplay = () => { - pause_button.textContent = "..." - } - e.onwaiting = () => { - pause_button.textContent = "..." - } - e.onplaying = () => { - pause_button.textContent = "||" - } - e.onpause = () => { - pause_button.textContent = "|>" - } - const toggle_playing = () => e.paused ? e.play() : e.pause() - - mouse_idle(e, 1000, idle => { - controls.style.opacity = idle ? 0 : 1 - e.style.cursor = idle ? "none" : "default" - }) - - e.addEventListener("click", toggle_playing) - pause_button.addEventListener("click", toggle_playing) - fullscreen_button.addEventListener("click", () => { - if (document.fullscreenElement) document.exitFullscreen() - else document.documentElement.requestFullscreen() - }) - const seek_ev = ev => { - const r = pri.getBoundingClientRect() - const p = (ev.clientX - r.left) / (r.right - r.left) - e.currentTime = p * e.duration - } - pri.addEventListener("mousedown", ev => { - seek_ev(ev) - }) - document.body.addEventListener("keydown", k => { - if (k.code == "Period") e.seekToNextFrame() - else if (k.code == "Space") toggle_playing() - else if (k.code == "ArrowLeft") e.currentTime -= 5 - else if (k.code == "ArrowRight") e.currentTime += 5 - else if (k.code == "ArrowUp") e.currentTime -= 60 - else if (k.code == "ArrowDown") e.currentTime += 60 - else return; - k.preventDefault() - }) -} - -function mouse_idle(e, timeout, cb) { - let ct; - 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) { - 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" : "") -} diff --git a/web/script/jshelper b/web/script/jshelper -Subproject 4c6a395de093dce24c688276a8b04a93093fd11 +Subproject 18cc95742b9e43f1739385ce3bb673c7095a66a diff --git a/web/script/main.ts b/web/script/main.ts index 8b13789..bd66342 100644 --- a/web/script/main.ts +++ b/web/script/main.ts @@ -1 +1,2 @@ +import "./player/mod.ts" diff --git a/web/script/player/mod.ts b/web/script/player/mod.ts new file mode 100644 index 0000000..20f47ca --- /dev/null +++ b/web/script/player/mod.ts @@ -0,0 +1,120 @@ +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" : "") +} |