From b384858e2b3b7df2383571736a6a1b8c396dc34a Mon Sep 17 00:00:00 2001 From: Richard <richard@fsmpi.rwth-aachen.de> Date: Sat, 31 Oct 2020 00:08:25 +0100 Subject: [PATCH] showing download links in the player as well Thanks to V for mentioning this issue! (some courses apparently linke to the video player (paella), instead of embedded it in an iframe) --- README.md | 13 +++--- free.css | 40 +++++++++++++++-- free.js | 120 +++++++++++++++++++++++++++++++++++++++++++++----- manifest.json | 2 +- 4 files changed, 155 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 9a9b2b5..58ff893 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Nevertheless, in the code it is called _Open Excellence Media_ or for short **O ## what is it good for? -Most videos (eg. lecture recordings) embedded in RWTH Aachen University's moodle are hosted on an OpenCast. +Most videos (eg. lecture recordings) embedded in RWTH Aachen University's moodle are hosted on an OpenCast instance. These videos are usually embedded using an iframe, which makes it (intentionally) hard to download them for offline use. This extension want's to help by liberating lecture recordings and other videos provided in this rather restrictive manner. @@ -55,15 +55,18 @@ Nevertheless it is possible to get extensions signed by Mozilla and self-distrib ### downloads, with caveats _\*sigh\*_ +tl;dr: Build it from source yourself, or use [the download/install site](https://dev.sudo42.de/public/ff-addons/oem.html).\ +Read below for slightly more in-depth information. + #### external site -You should (hopefully) be able to directly download the latest version from:\ +~~You should (hopefully) be able to directly download the latest version from:\ <https://dev.sudo42.de/public/ff-addons/openexcellencemedia-latest.xpi>\ **Caveat:** Simply clicking the link is unlikely to work. Firefox seems to block installations of extensions, if a link does not point to the same domain.\ -~~I'm sorry … please just copy it and open the page yourself.~~ +I'm sorry … please just copy it and open the page yourself.~~ -**Update (and potential solution for the caveat described above):** +**Update (and potential solution for the caveat described above):**\ Here is a simple page with the sole purpose of being on the same domain as the extension file it links to:\ <https://dev.sudo42.de/public/ff-addons/oem.html>\ (This should kinda work around the problem mentioned above. @@ -84,7 +87,7 @@ This project is licensed unser EUPL, so feel free to use, read, adapt, or share ## 2do - [X] going to bed - [ ] styling (I love CSS, not joking here! **Update:** A little bit of css is present. Should work for now.) - - [ ] adding links in video-only tabs, too + - [X] adding links in video-only tabs, too - [X] packaging - [X] good name + icon (kinda done … _"good"_ is highly subjective, but I will give it a pass) - [ ] further investigation into the OpenCast API (looks like one might be able to have some fun with it) diff --git a/free.css b/free.css index 684339a..cf4521d 100644 --- a/free.css +++ b/free.css @@ -1,17 +1,47 @@ -._ext-openExcellenceMedia_container .videoLinkList { +._ext-openExcellenceMedia_container, +.openExcellenceMediaPlugin { --c-rwth-violett: rgb(97,33,88); --c-link-bg: var(--c-rwth-violett); --c-link-fg: #fff; } -._ext-openExcellenceMedia_container .videoLinkList { +.openExcellenceMediaPlugin.oemPopOut { + position: fixed; + top: 3.4em; + left: 2.1em; + right: 2.1em; + bottom: unset; + z-index: 42021; + text-align: center; + font-size: 1.1em; +} +._ext-openExcellenceMedia_container .videoLinkList, +.openExcellenceMediaPlugin .videoLinkList { list-style-type: none; padding: 0; display: flex; flex-direction: row; } +.openExcellenceMediaPlugin .videoLinkList { +/* flex-direction: column; + width: max-content; + align-items: stretch; + margin: .5em .25em; */ + margin: .5em auto; + width: max-content; + max-width: 100%; + padding: .5em .25em; + background: rgba(242, 242, 242, .7); + opacity: .7; + box-shadow: 0 0 1em 0 rgba(0,0,0,.7); +} +.openExcellenceMediaPlugin .videoLinkList:hover, +.openExcellenceMediaPlugin .videoLinkList:focus-within { + opacity: 1; +} -._ext-openExcellenceMedia_container .videoLinkList .videoLink { +._ext-openExcellenceMedia_container .videoLinkList .videoLink, +.openExcellenceMediaPlugin .videoLinkList .videoLink { display: inline-block; padding: .5em 1em; background: var(--c-link-bg); @@ -19,3 +49,7 @@ margin: .25em .5em; border-radius: .2em; } +/* .openExcellenceMediaPlugin .videoLinkList .videoLink { + display: block; + text-align: center; +} */ diff --git a/free.js b/free.js index 928a6a9..f9bcbff 100644 --- a/free.js +++ b/free.js @@ -19,8 +19,8 @@ if (window.location.host === 'engage.streaming.rwth-aachen.de') { videoTracks.forEach(t=>console.debug(t.id, t.mimetype, t.video.resolution, t.url)) if (inFrame) { window.parent.postMessage({videoTracks, meta}, '*') - } else { - // TODO: add download links to video + } /*/ else /* */ { + addLinksToVideoPlayer(videoTracks, meta) } }) } else if (window.location.host === 'moodle.rwth-aachen.de') { @@ -76,15 +76,8 @@ const FMT = (()=>{ } })() -function genLinkContainer(tracks, meta) { +function genLinkList(tracks, meta) { let videoTitle = meta['search-results'].result.dcTitle || '?' - let details = document.createElement('details') - details.id = genVideoContainerId(meta) - details.classList.add('_ext-openExcellenceMedia_container') - let summary = document.createElement('summary') - summary.innerText = `Download video: ${videoTitle}` - details.appendChild(summary) - let videoLinkList = document.createElement('ul') videoLinkList.classList.add('videoLinkList') tracks.forEach(track => { @@ -102,7 +95,112 @@ Audio: ${mAud.channels}ch@${FMT.hz(mAud.samplingrate)} (${FMT.bps(mAud.bitrate)} li.appendChild(a) videoLinkList.appendChild(li) }) - details.appendChild(videoLinkList) + + return videoLinkList +} + +function genLinkContainer(tracks, meta) { + let videoTitle = meta['search-results'].result.dcTitle || '?' + let details = document.createElement('details') + details.id = genVideoContainerId(meta) + details.classList.add('_ext-openExcellenceMedia_container') + let summary = document.createElement('summary') + summary.innerText = `Download video: ${videoTitle}` + details.appendChild(summary) + details.appendChild(genLinkList(tracks, meta)) return details } + +const _PLAYER_CONTROL_BUTTON_ID = '_ext_openExcellence_btn-ctrl-bar' +function genPlayerControlsButton() { + let container = document.createElement('div'); + ['buttonPlugin', 'right', 'openExcellenceMediaPlugin'].forEach(c=>container.classList.add(c)) + container.id = _PLAYER_CONTROL_BUTTON_ID + container.setAttribute('title', 'Show downloadable video links'); + + let icon = document.createElement('i'); + ['button-icon', 'icon-download'].forEach(c=>icon.classList.add(c)) + container.appendChild(icon) + + return container +} + +const _PLAYER_CONTROL_POPOUT_ID = '_ext_openExcellence_ctr-bar-pop-out' +function genPlayerControlsPopOut(tracks, meta) { + let container = document.createElement('div'); + ['openExcellenceMediaPlugin', 'oemPopOut'].forEach(c=>container.classList.add(c)) + container.id = _PLAYER_CONTROL_POPOUT_ID + container.appendChild(genLinkList(tracks, meta)) + + return container +} + +function addLinksToVideoPlayer(videoTracks, meta) { + // removing old elements, if they are still here ... + document.querySelectorAll(`#${_PLAYER_CONTROL_BUTTON_ID}, #${_PLAYER_CONTROL_POPOUT_ID}`) + .forEach(n => n.remove()) + + console.debug('adding links to page ...', document.readyState) + + let toolbarBtn = genPlayerControlsButton() + let toolbarPopOut = genPlayerControlsPopOut(videoTracks, meta) + document.body.appendChild(toolbarPopOut) + console.debug(toolbarPopOut) + + let timeoutFn = ()=>{ + // waiting for things like the toolbar to be ready + if (!document.querySelector('.playbackControls')) { + setTimeout(timeoutFn, 250) + return + } + console.debug('page seems to be ready ... adding things ...') + +/* + // web extensions can not trivially access properties in the window object of the page context + // just using paella's API and adding a regular plugin for this would have been nice + console.debug(window, window.paella) + window.paella.addPlugin(()=>{ + return class OpenExcellenceMedia extends paella.ButtonPlugin { + getIndex() { return 42021; } + getAlignment() { return 'right' } + getSubclass() { return "openExcellenceMedia-ctrl-btn" } + getIconClass() { return 'icon-download' } + getName() { return "_.OpenExcellenceMedia.ff-ext" } + getButtonType() { return paella.ButtonPlugin.type.popUpButton } + buildContent(domElement) { + let linkList = genLinkList(videoTracks, meta) + domElement.appendChild(linkList) + domElement.classList.add('OpenExcellenceMediaPlugin') + } + + } + }) +*/ + + let open = false + let buttonBarContainer = document.querySelector('.playbackBarPlugins') + let popOutContainer = document.querySelector('.popUpPluginContainer') + buttonBarContainer.appendChild(toolbarBtn) + popOutContainer.appendChild(toolbarPopOut) + let _setOpen = (newState = null) => { + if (newState === undefined || newState === null) newState = !open + open = newState + let style = toolbarPopOut.style + if (open) { + style.display = null + toolbarBtn.classList.add('selected') + } else { + style.display = 'none' + toolbarBtn.classList.remove('selected') + } + } + _setOpen(false) + toolbarBtn.addEventListener('click', e=>{ + _setOpen() + }) + } + console.debug('wating for player interface to get ready ...') + timeoutFn() + +} diff --git a/manifest.json b/manifest.json index 2985996..767a54e 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "OpenExcellenceMedia", - "version": "0.0.2", + "version": "0.0.3", "description": "Adds download links to videos on RWTH moodle which are served using an OpenCast iframe.", "homepage_url": "https://git.fsmpi.rwth-aachen.de/moodleOpenCastDownloads/ff-ext", "icons": { -- GitLab