From 1b49b532dcf69d792aec6de997aa76999adf1de6 Mon Sep 17 00:00:00 2001 From: Joshua Seigler Date: Mon, 29 Nov 2021 23:37:45 -0500 Subject: [PATCH] feat: context menu, link to current time --- README.md | 1 + index.html | 34 +++++++++++++++- src/index.js | 110 ++++++++++++++++++++++++++++++++++----------------- 3 files changed, 107 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 677fda2..02a9aef 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ Accepts three query parameters: - `hash`: required. The IPFS hash of a folder containing an HLS playlist and its files. - `source`: optional, defaults to `master.m3u8`. - `title`: optional, allows overriding the browser tab title. +- `time`: optional, start video at this many seconds ## Usage Examples: diff --git a/index.html b/index.html index 3c6fa98..b443b26 100644 --- a/index.html +++ b/index.html @@ -55,13 +55,44 @@ padding: 0.5em; overflow: auto; } + #contextMenu { + position: sticky; + background-color: #2f2f2faf; + color: white; + width: 20em; + } + #contextMenu > div { + border: 1px solid #0000007f; + cursor: pointer; + padding: 0.5em; + } + #contextMenu > div + div { + border-top: none; + } + #contextBackground { + position: fixed; + bottom: 0; + right: 0; + height: 100%; + width: 100%; + } + .is-hidden { + display: none; + } - +
+ +

HLS over IPFS video player

@@ -79,6 +110,7 @@
  • title: optional, allows overriding the browser tab title.
  • +
  • time: optional, start the video at this many seconds
  • Usage Examples: diff --git a/src/index.js b/src/index.js index b82f81c..733491f 100644 --- a/src/index.js +++ b/src/index.js @@ -4,7 +4,77 @@ import { create } from 'ipfs-core' import Hls from 'hls.js' import HlsjsIpfsLoader from 'hlsjs-ipfs-loader' -let node +document.addEventListener('DOMContentLoaded', async () => { + setBodyHeight() + window.addEventListener('resize', setBodyHeight) + const hash = getUrlParameter('hash') + const source = getUrlParameter('source') + const title = getUrlParameter('title') + const time = getUrlParameter('time') + setUpContextMenu() // todo move back inside if(hash) + if (title) { + document.title = title + } + if (hash) { + document.getElementById('help').style.display = 'none' + const video = document.getElementById('video') + video.style.display = 'block' + const repoPath = 'ipfs-' + Math.random() + showStatus('Connecting to IPFS') + const node = await create({ repo: repoPath }) + showStatus('Connected') + Hls.DefaultConfig.loader = HlsjsIpfsLoader + Hls.DefaultConfig.debug = false + if (Hls.isSupported()) { + const hls = new Hls() + hls.config.ipfs = node + hls.config.ipfsHash = hash + showStatus('Video loading') + hls.loadSource(source || 'master.m3u8') + hls.attachMedia(video) + hls.on(Hls.Events.MANIFEST_PARSED, () => { + showStatus('Video loaded', true) + if (time) { + video.currentTime = time + } + video.play() + }) + } + } + + function setUpContextMenu() { + const video = document.getElementById('video') + const background = document.getElementById('contextBackground') + const menu = document.getElementById('contextMenu') + video.oncontextmenu = e => { + background.classList.toggle('is-hidden') + menu.style.left = e.pageX + 'px' + menu.style.top = e.pageY + 'px' + e.preventDefault() + } + background.onClick = e => { + e.stopPropagation() + background.classList.toggle('is-hidden') + } + const url = `http://ipfsvideo.cc?hash=${ + hash + }${ + title && '&title=' + encodeURIComponent(title) + }${ + source && '&source=' + encodeURIComponent(source) + }` + document.getElementById('contextMenu-url').onClick = e => { + e.stopPropagation() + navigator.clipboard.writeText(url) + background.classList.toggle('is-hidden') + } + document.getElementById('contextMenu-urlWithTime').onClick = e => { + e.stopPropagation() + navigator.clipboard.writeText(`${url}&time=${Math.round(video.currentTime)}`) + background.classList.toggle('is-hidden') + } + } +}) function getUrlParameter(name) { name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]') @@ -15,44 +85,10 @@ function getUrlParameter(name) { function showStatus(message, hide = false) { const status = document.getElementById('status') - status.classList.toggle("is-hiding", hide) + status.classList.toggle('is-hiding', hide) status.innerText = message } function setBodyHeight() { - document.body.style.height = window.innerHeight + "px" + document.body.style.height = window.innerHeight + 'px' } - -document.addEventListener('DOMContentLoaded', async () => { - setBodyHeight() - window.addEventListener('resize', setBodyHeight) - const hash = getUrlParameter("hash") - const source = getUrlParameter("source") || 'master.m3u8' - const title = getUrlParameter("title") - if (title) { - document.title = title - } - if (hash) { - document.getElementById("help").style.display = "none" - const video = document.getElementById('video') - video.style.display = "block" - const repoPath = 'ipfs-' + Math.random() - showStatus("Connecting to IPFS") - node = await create({ repo: repoPath }) - showStatus("Connected") - Hls.DefaultConfig.loader = HlsjsIpfsLoader - Hls.DefaultConfig.debug = false - if (Hls.isSupported()) { - const hls = new Hls() - hls.config.ipfs = node - hls.config.ipfsHash = hash - showStatus("Video loading") - hls.loadSource(source) - hls.attachMedia(video) - hls.on(Hls.Events.MANIFEST_PARSED, () => { - showStatus("Video loaded", true) - video.play() - }) - } - } -})