feat: context menu, link to current time

This commit is contained in:
Joshua Seigler 2021-11-29 23:37:45 -05:00
parent 38d372a603
commit 1b49b532dc
3 changed files with 107 additions and 38 deletions

View file

@ -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:

View file

@ -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;
}
</style>
<script type="module" defer="" src="./src/index.js"></script>
</head>
<body>
<video id="video" controls="" autoplay=""></video>
<video id="video" controls="" controlsList="nodownload" autoplay=""></video>
<div id="status"></div>
</div>
<div class="is-hidden" id="contextBackground">
<div id="contextMenu">
<div id="contextMenu-url">Copy video URL</div>
<div id="contextMenu-urlWithTime">Copy video URL at current time</div>
</div>
</div>
<section id="help">
<h1>HLS over IPFS video player</h1>
<h2 id="how-to-use">
@ -79,6 +110,7 @@
<li>
<code>title</code>: optional, allows overriding the browser tab title.
</li>
<li><code>time</code>: optional, start the video at this many seconds</li>
</ul>
<h2 id="usage-examples">
<a class="anchor" href="#usage-examples"></a>Usage Examples:

View file

@ -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()
})
}
}
})