refactor: Making the front end modular using webpack.
This commit is contained in:
parent
6e08769a8d
commit
6ed9ab8f24
@ -21,7 +21,8 @@ package MY {
|
|||||||
my $return = $self->SUPER::top_targets(@_);
|
my $return = $self->SUPER::top_targets(@_);
|
||||||
$return = [ split /\n/, $return ];
|
$return = [ split /\n/, $return ];
|
||||||
for my $i ( keys @$return ) {
|
for my $i ( keys @$return ) {
|
||||||
$return->[$i] .= ' install_config' if $return->[$i] =~ /^all :/;
|
$return->[$i] .= ' install_config build_frontend install_frontend'
|
||||||
|
if $return->[$i] =~ /^all :/;
|
||||||
}
|
}
|
||||||
return join "\n", @$return;
|
return join "\n", @$return;
|
||||||
}
|
}
|
||||||
@ -42,6 +43,12 @@ THEME = ' . ( $config->{theme} // 'default' ) . "\n";
|
|||||||
sub postamble {
|
sub postamble {
|
||||||
return
|
return
|
||||||
"\n"
|
"\n"
|
||||||
|
. "install_frontend : build_frontend\n"
|
||||||
|
. "\tif [ ! -e lib/Peertube/DL/public/ ];"
|
||||||
|
. " then mkdir -pv lib/Peertube/DL/public/;" . " fi\n"
|
||||||
|
. "\tcp -rfv themes/\${THEME}/public/dist/* lib/Peertube/DL/public/\n"
|
||||||
|
. "build_frontend :\n"
|
||||||
|
. "\tcd themes/\${THEME}/public && yarn build\n"
|
||||||
. "install_config :\n"
|
. "install_config :\n"
|
||||||
. "\tinstall peertube-dl-web.conf bin/peertube-dl-web.conf\n"
|
. "\tinstall peertube-dl-web.conf bin/peertube-dl-web.conf\n"
|
||||||
. "src: src/Makefile\n"
|
. "src: src/Makefile\n"
|
||||||
|
@ -29,6 +29,10 @@ a:hover,a:focus {
|
|||||||
border: black 1px solid;
|
border: black 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#modal-video-container.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.video-container-bar {
|
.video-container-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: right;
|
justify-content: right;
|
||||||
@ -245,6 +249,7 @@ h2 {
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: black;
|
color: black;
|
||||||
background: #eee;
|
background: #eee;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.format-list > div > a:hover {
|
.format-list > div > a:hover {
|
||||||
|
File diff suppressed because one or more lines are too long
274
themes/default/public/dist/css/index.css
vendored
Normal file
274
themes/default/public/dist/css/index.css
vendored
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
body {
|
||||||
|
height: 99.9%;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover,a:focus {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#video {
|
||||||
|
width: 100%;
|
||||||
|
margin: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-video-container {
|
||||||
|
display: none;
|
||||||
|
background: white;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
border: black 1px solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-video-container.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.video-container-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-and-reset-video-container {
|
||||||
|
margin-top: 0.25rem;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-and-reset-video-container:hover:#close-and-reset-video-container:focus {
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#download-video-container {
|
||||||
|
margin: 10px;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#download-video-container a {
|
||||||
|
display: none;
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-right: 5px;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
width: 100%;
|
||||||
|
background: #0a0;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-size: 30px;
|
||||||
|
color: white;
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#download-video-container a.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#download-video-container a embed {
|
||||||
|
height: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#video-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.block {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.application-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
text-align: center;
|
||||||
|
height: 100%;
|
||||||
|
background: #000;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#download-form {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#download-form-button {
|
||||||
|
margin-top: 5px;
|
||||||
|
height: 50px;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
background: #fff;
|
||||||
|
color: black;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-loading {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
border: black 1px solid;
|
||||||
|
justify-content: right;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-loading.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-loading embed {
|
||||||
|
width: 10%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#poping-notice {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
border: black 1px solid;
|
||||||
|
width: 91%;
|
||||||
|
background: white;
|
||||||
|
padding: 10px;
|
||||||
|
border-radius: 15px;
|
||||||
|
max-height: 95%;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#poping-notice.active {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#poping-notice-container-bar {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-poping-notice {
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
text-align: center;
|
||||||
|
justify-content: center;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #0f0;
|
||||||
|
color: black;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-poping-notice:hover,#close-poping-notice:focus {
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-format-selector {
|
||||||
|
display: none;
|
||||||
|
background: white;
|
||||||
|
position: fixed;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
border: black 1px solid;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-format-selector.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-format-selector > h2 {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-format-selector > p {
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modal-format-selector .format-list {
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: #fff;
|
||||||
|
margin: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-modal-format-selector {
|
||||||
|
margin-top: 0.50rem;
|
||||||
|
margin-right: 0.50rem;
|
||||||
|
border: 1px solid black;
|
||||||
|
background: grey;
|
||||||
|
color: white;
|
||||||
|
width: 25px;
|
||||||
|
height: 25px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#close-modal-format-selector:hover,#close-modal-format-selector:focus {
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-list > div {
|
||||||
|
width: 100%;
|
||||||
|
display: grid;
|
||||||
|
grid-auto-columns: 50%;
|
||||||
|
grid-template-areas: "a a";
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-list > div > a {
|
||||||
|
border: 1px solid black;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
padding-right: 5%;
|
||||||
|
padding-left: 5%;
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
background: #eee;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-list > div > a:hover {
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-list > div > a:after {
|
||||||
|
padding-bottom: 100%;
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
}
|
||||||
|
|
||||||
|
div.video-formats a {
|
||||||
|
background: #f00;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 668px) {
|
||||||
|
#poping-notice {
|
||||||
|
width: 629px;
|
||||||
|
}
|
||||||
|
}
|
68
themes/default/public/dist/index.html
vendored
Normal file
68
themes/default/public/dist/index.html
vendored
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="js/peertube-dl-web.js"></script>
|
||||||
|
<link rel="stylesheet" href="css/index.css"></script>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="application-container">
|
||||||
|
<h2>Peertube-dl Web Application</h2>
|
||||||
|
<form id="download-form">
|
||||||
|
<input class="block" type="text" id="download-form-url" placeholder="Introduce the url you want to download."/>
|
||||||
|
<button class="block" id="download-form-button" >Fetch from api</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
<div id="modal-format-selector">
|
||||||
|
<div class="video-container-bar">
|
||||||
|
<a id="close-modal-format-selector">x</a>
|
||||||
|
</div>
|
||||||
|
<h2>Example video</h2>
|
||||||
|
<p>Example description</p>
|
||||||
|
<div class="format-list">
|
||||||
|
<h3>Video Formats.</h3>
|
||||||
|
<div class="video-formats">
|
||||||
|
</div>
|
||||||
|
<h3>Audio Formats.</h3>
|
||||||
|
<div class="audio-formats">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="modal-loading">
|
||||||
|
<embed src="img/spinner.svg"/>
|
||||||
|
</div>
|
||||||
|
<div id="modal-video-container">
|
||||||
|
<div class="video-container-bar">
|
||||||
|
<a id="close-and-reset-video-container">x</a>
|
||||||
|
</div>
|
||||||
|
<div id="video-container">
|
||||||
|
<div class="block">
|
||||||
|
<video id="video" controls="controls"></video>
|
||||||
|
</div>
|
||||||
|
<div id="download-video-container" class="block">
|
||||||
|
<a id="download-video-prepare" class="active">Prepare download</a>
|
||||||
|
<a id="download-video-loading"><embed src="img/spinner.svg"/></a>
|
||||||
|
<a id="download-video">Download</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="poping-notice">
|
||||||
|
<div id="poping-notice-content">
|
||||||
|
<p>This webpage is free as in freedom software, it is offered to you with the hope it will be useful, but without any warranty,
|
||||||
|
you can find the source code at <a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl">my gitea</a> with docs to setup your own
|
||||||
|
webpage like this, this software is licensed under the AGPLv3 license which means you MUST convey the source code in a human readable form
|
||||||
|
if you distribute this software or use it as an service to users of service or distributees.<p>
|
||||||
|
|
||||||
|
<p>I hope that if you find a non supported url which should be supported, a bug, or a feature you would like this webpage to have you file an issue in
|
||||||
|
<a href="https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues">https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues</a>
|
||||||
|
to help this software improve since I find tracking users a pretty bad way to discover bugs and potential good features.</p>
|
||||||
|
|
||||||
|
<p>This webpage may load third party resources depending on the url you give to it which may put cookies in your browser, you are
|
||||||
|
encouraged to frecuently delete your browser cookies to avoid those third parties tracking you on internet, Firefox offers you an
|
||||||
|
option to delete cookies as soon as you close the browser which may be a good idea to enable in the orwellian internet of today.</p>
|
||||||
|
</div>
|
||||||
|
<div id="poping-notice-container-bar">
|
||||||
|
<a id="close-poping-notice" href="#">X</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
13
themes/default/public/package.json
Normal file
13
themes/default/public/package.json
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "default-theme",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"private": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"scripts": {
|
||||||
|
"build": "webpack"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"webpack": "^5.15.0",
|
||||||
|
"webpack-cli": "^4.3.1"
|
||||||
|
}
|
||||||
|
}
|
106
themes/default/public/src/application.js
Normal file
106
themes/default/public/src/application.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
import { PopingNotice } from './view/poping_notice.js';
|
||||||
|
import { DownloadForm } from './view/download_form.js';
|
||||||
|
import { LoadingModal } from './view/loading_modal.js';
|
||||||
|
import { VideoContainer } from './view/video_container.js';
|
||||||
|
import { FormatSelector } from './view/format_selector.js';
|
||||||
|
|
||||||
|
class Application {
|
||||||
|
constructor() {
|
||||||
|
this.poping_notice = new PopingNotice();
|
||||||
|
this.download_form = new DownloadForm(this.onDownloadFormGot.bind(this));
|
||||||
|
this.loading_modal = new LoadingModal();
|
||||||
|
this.video_container = new VideoContainer();
|
||||||
|
this.format_selector = new FormatSelector();
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.popingNotice.setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
onDownloadFormGot(url) {
|
||||||
|
this.dispatchURL(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatchURL(url, format) {
|
||||||
|
this.loadingModal.setVisible(true);
|
||||||
|
let error_str;
|
||||||
|
let success = this.queryAPI(url, format).then( (response) => {
|
||||||
|
if ( response.options !== undefined && response.options.list_formats !== undefined && response.options.list_formats ) {
|
||||||
|
if ( response.formats === undefined
|
||||||
|
|| response.formats.audio_formats === undefined
|
||||||
|
|| response.formats.video_formats === undefined ) {
|
||||||
|
throw 'Format object is not valid.';
|
||||||
|
}
|
||||||
|
this.formatSelector.prepareFormatSelector(
|
||||||
|
response.title, response.description,
|
||||||
|
response.formats.audio_formats, response.formats.video_formats,
|
||||||
|
( id ) => {
|
||||||
|
this.loadingModal.setVisible(true);
|
||||||
|
this.dispatchURL(url, id);
|
||||||
|
});
|
||||||
|
this.formatSelector.setVisible(true);
|
||||||
|
this.loadingModal.setVisible(false);
|
||||||
|
} else {
|
||||||
|
this.videoContainer.onCanPlay(this.onCanPlayVideoContainer.bind(this));
|
||||||
|
this.videoContainer.setURLVideo(response.url);
|
||||||
|
this.videoContainer.setFilename(response.filename);
|
||||||
|
}
|
||||||
|
}).catch( (error) => {
|
||||||
|
error_str = error.toString();
|
||||||
|
this.loadingModal.setVisible(false);
|
||||||
|
let input_url = document.createElement('a');
|
||||||
|
input_url.href = url;
|
||||||
|
input_url.innerText = url;
|
||||||
|
let issues_url = document.createElement('a');
|
||||||
|
issues_url.href = 'https://gitea.sergiotarxz.freemyip.com/sergiotarxz/Peertube-dl/issues';
|
||||||
|
issues_url.innerText = 'here';
|
||||||
|
this.popingNotice.setMessage( [ 'The url ', input_url, ' is not supported, the error was: ', error_str , ' if you think this is an error, report it ', issues_url, '.' ]);
|
||||||
|
this.popingNotice.setVisible(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onCanPlayVideoContainer() {
|
||||||
|
this.videoContainer.setVisible(true);
|
||||||
|
this.loadingModal.setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async queryAPI(url, format) {
|
||||||
|
let request = { url: url };
|
||||||
|
if (format !== undefined)
|
||||||
|
request.format = format;
|
||||||
|
const response = await fetch('/api', {
|
||||||
|
method: 'POST',
|
||||||
|
mode: 'cors',
|
||||||
|
cache: 'no-cache',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(request),
|
||||||
|
});
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
get formatSelector() {
|
||||||
|
return this.format_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
get videoContainer() {
|
||||||
|
return this.video_container;
|
||||||
|
}
|
||||||
|
|
||||||
|
get downloadForm() {
|
||||||
|
return this.download_form;
|
||||||
|
}
|
||||||
|
|
||||||
|
get popingNotice() {
|
||||||
|
return this.poping_notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
get loadingModal() {
|
||||||
|
return this.loading_modal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Application };
|
10
themes/default/public/src/index.js
Normal file
10
themes/default/public/src/index.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
import { Application } from './application.js';
|
||||||
|
|
||||||
|
window.addEventListener('load', (event) => {
|
||||||
|
let application = new Application();
|
||||||
|
application.init();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
35
themes/default/public/src/view/download_form.js
Normal file
35
themes/default/public/src/view/download_form.js
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
class DownloadForm {
|
||||||
|
constructor(callback) {
|
||||||
|
this.query_selector = '#download-form';
|
||||||
|
this.callback = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
callback(this.downloadFormUrl.value);
|
||||||
|
};
|
||||||
|
this.addEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListeners() {
|
||||||
|
this.downloadFormButton.addEventListener('click', this.callback);
|
||||||
|
this.element.addEventListener('submit', this.callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
get downloadFormButton() {
|
||||||
|
return this.element.querySelector('#download-form-button');
|
||||||
|
}
|
||||||
|
|
||||||
|
get downloadFormUrl() {
|
||||||
|
return this.element.querySelector('#download-form-url');
|
||||||
|
}
|
||||||
|
|
||||||
|
get querySelector() {
|
||||||
|
return this.query_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
get element() {
|
||||||
|
return document.querySelector(this.querySelector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { DownloadForm };
|
87
themes/default/public/src/view/format_selector.js
Normal file
87
themes/default/public/src/view/format_selector.js
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
class FormatSelector {
|
||||||
|
constructor() {
|
||||||
|
this.query_selector = '#modal-format-selector';
|
||||||
|
this.addEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
appendFormat(container, object, is_video, callback) {
|
||||||
|
let a = document.createElement('a');
|
||||||
|
if ( is_video ) {
|
||||||
|
a.innerText = 'Id: ' + object.id + "\n"
|
||||||
|
+ 'Format: ' + object.mimeType + "\n"
|
||||||
|
+ 'QualityLabel: ' + object.qualityLabel + "p\n"
|
||||||
|
+ 'Bitrate: ' + object.bitrate + "\n"
|
||||||
|
+ (
|
||||||
|
( object.audioSampleRate !== undefined ) ?
|
||||||
|
'AudioSampleRate: ' + object.audioSampleRate + ".\n" :
|
||||||
|
"No audio."
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
a.innerText = 'Id: ' + object.id + "\n"
|
||||||
|
+ 'Format: ' + object.mimeType + "\n"
|
||||||
|
+ 'AudioSampleRate: ' + object.audioSampleRate + "\n"
|
||||||
|
+ 'Bitrate: ' + object.bitrate + ".\n";
|
||||||
|
}
|
||||||
|
a.addEventListener( 'click', (event) => {
|
||||||
|
callback(object.id);
|
||||||
|
});
|
||||||
|
container.appendChild(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareFormatSelector(title, description, audio_formats, video_formats, callback) {
|
||||||
|
this.titleFormatSelector.innerText = title;
|
||||||
|
this.descriptionFormatSelector.innerText = description;
|
||||||
|
this.videoFormats.innerHTML = '';
|
||||||
|
this.audioFormats.innerHTML = '';
|
||||||
|
for ( let x of audio_formats) {
|
||||||
|
this.appendFormat(this.audioFormats, x, false, callback);
|
||||||
|
}
|
||||||
|
for ( let x of video_formats ) {
|
||||||
|
this.appendFormat(this.videoFormats, x, true, callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setVisible(option) {
|
||||||
|
if (option) {
|
||||||
|
this.element.classList.add('active');
|
||||||
|
} else {
|
||||||
|
this.element.classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListeners() {
|
||||||
|
this.closeFormatSelector.addEventListener('click', (event) => { this.setVisible(false); });
|
||||||
|
}
|
||||||
|
|
||||||
|
get videoFormats() {
|
||||||
|
return this.element.querySelector('.video-formats');
|
||||||
|
}
|
||||||
|
|
||||||
|
get audioFormats() {
|
||||||
|
return this.element.querySelector('.audio-formats');
|
||||||
|
}
|
||||||
|
|
||||||
|
get titleFormatSelector() {
|
||||||
|
return this.element.querySelector('h2');
|
||||||
|
}
|
||||||
|
|
||||||
|
get descriptionFormatSelector() {
|
||||||
|
return this.element.querySelector('p');
|
||||||
|
}
|
||||||
|
|
||||||
|
get closeFormatSelector() {
|
||||||
|
return this.element.querySelector('#close-modal-format-selector');
|
||||||
|
}
|
||||||
|
|
||||||
|
get element() {
|
||||||
|
return document.querySelector(this.querySelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
get querySelector() {
|
||||||
|
return this.query_selector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { FormatSelector };
|
25
themes/default/public/src/view/loading_modal.js
Normal file
25
themes/default/public/src/view/loading_modal.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
class LoadingModal {
|
||||||
|
constructor() {
|
||||||
|
this.query_selector = '#modal-loading';
|
||||||
|
}
|
||||||
|
|
||||||
|
setVisible(option) {
|
||||||
|
if (option) {
|
||||||
|
this.element.classList.add('active');
|
||||||
|
} else {
|
||||||
|
this.element.classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get element() {
|
||||||
|
return document.querySelector(this.querySelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
get querySelector() {
|
||||||
|
return this.query_selector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { LoadingModal };
|
56
themes/default/public/src/view/poping_notice.js
Normal file
56
themes/default/public/src/view/poping_notice.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
class PopingNotice {
|
||||||
|
constructor() {
|
||||||
|
this.query_selector = '#poping-notice';
|
||||||
|
this.closePopingNotice.addEventListener('click', (event) => {
|
||||||
|
this.setVisible(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setVisible(option) {
|
||||||
|
if (option) {
|
||||||
|
this.element.classList.add('active');
|
||||||
|
} else {
|
||||||
|
this.element.classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setMessage(message) {
|
||||||
|
if (!message instanceof Array)
|
||||||
|
throw 'Message is not instance of Array.';
|
||||||
|
let p = document.createElement('p');
|
||||||
|
for (let node of message) {
|
||||||
|
if (typeof node === "string"
|
||||||
|
|| node instanceof String) {
|
||||||
|
node = document.createTextNode(node);
|
||||||
|
p.appendChild(node);
|
||||||
|
} else if ( node instanceof Node) {
|
||||||
|
p.appendChild(node);
|
||||||
|
} else {
|
||||||
|
throw ('Node is not a instance of Node nor a String');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.popingNoticeContent.innerHTML = '';
|
||||||
|
this.popingNoticeContent.appendChild(p);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get querySelector() {
|
||||||
|
return this.query_selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
get element() {
|
||||||
|
return document.querySelector(this.querySelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
get popingNoticeContent() {
|
||||||
|
return this.element.querySelector('#poping-notice-content');
|
||||||
|
}
|
||||||
|
|
||||||
|
get closePopingNotice() {
|
||||||
|
return this.element.querySelector('#close-poping-notice');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { PopingNotice };
|
112
themes/default/public/src/view/video_container.js
Normal file
112
themes/default/public/src/view/video_container.js
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
class VideoContainer {
|
||||||
|
constructor() {
|
||||||
|
this.query_selector = '#modal-video-container';
|
||||||
|
this.addEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
setVisible(option) {
|
||||||
|
if (option) {
|
||||||
|
this.element.classList.add('active');
|
||||||
|
} else {
|
||||||
|
this.element.classList.remove('active');
|
||||||
|
this.downloadVideoPrepare.classList.add('active');
|
||||||
|
this.downloadVideoLoading.classList.remove('active');
|
||||||
|
this.downloadVideo.classList.remove('active');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListeners() {
|
||||||
|
this.downloadVideoPrepare.addEventListener('click', this.downloadPrepareHandler.bind(this));
|
||||||
|
this.closeAndResetVideoContainer.addEventListener('click', (event) => {
|
||||||
|
this.setVisible(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
downloadPrepareHandler(event) {
|
||||||
|
this.downloadVideoPrepare.classList.remove('active');
|
||||||
|
this.downloadVideoLoading.classList.add('active');
|
||||||
|
this.generateBlobVideo(this.URLVideo).then( blob => {
|
||||||
|
this.downloadVideo.href = URL.createObjectURL(blob);
|
||||||
|
this.downloadVideo.download = this.filename;
|
||||||
|
this.downloadVideoLoading.classList.remove('active');
|
||||||
|
this.downloadVideo.classList.add('active');
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateBlobVideo(url) {
|
||||||
|
const blob = await fetch(url, { mode: 'cors', })
|
||||||
|
.then(res => res.blob())
|
||||||
|
.catch( err => this.generateBlobVideoByProxy(url) );
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateBlobVideoByProxy(url) {
|
||||||
|
const blob = await fetch( '/proxy_to_get', {
|
||||||
|
method: 'POST',
|
||||||
|
mode: 'cors',
|
||||||
|
cache: 'no-cache',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: JSON.stringify({url: url}),
|
||||||
|
}
|
||||||
|
).then(res => res.blob());
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
onCanPlay(callback) {
|
||||||
|
video.addEventListener('canplay', (event) => {
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setURLVideo(url) {
|
||||||
|
this.url_video = url;
|
||||||
|
video.src = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFilename(filename) {
|
||||||
|
this.filename = filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
get closeAndResetVideoContainer() {
|
||||||
|
return this.element.querySelector('#close-and-reset-video-container');
|
||||||
|
}
|
||||||
|
|
||||||
|
get downloadVideo() {
|
||||||
|
return this.element.querySelector('#download-video');
|
||||||
|
}
|
||||||
|
|
||||||
|
get URLVideo() {
|
||||||
|
return this.url_video;
|
||||||
|
}
|
||||||
|
|
||||||
|
get closeAndResetVideoContainer() {
|
||||||
|
return this.element.querySelector('#close-and-reset-video-container');
|
||||||
|
}
|
||||||
|
|
||||||
|
get downloadVideoLoading() {
|
||||||
|
return this.element.querySelector('#download-video-loading');
|
||||||
|
}
|
||||||
|
|
||||||
|
get downloadVideoPrepare() {
|
||||||
|
return this.element.querySelector('#download-video-prepare');
|
||||||
|
}
|
||||||
|
|
||||||
|
get video() {
|
||||||
|
return this.element.querySelector('#video');
|
||||||
|
}
|
||||||
|
|
||||||
|
get element() {
|
||||||
|
return document.querySelector(this.querySelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
get querySelector() {
|
||||||
|
return this.query_selector;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { VideoContainer };
|
10
themes/default/public/webpack.config.js
Normal file
10
themes/default/public/webpack.config.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
entry: './src/index.js',
|
||||||
|
devtool: 'source-map',
|
||||||
|
output: {
|
||||||
|
filename: 'peertube-dl-web.js',
|
||||||
|
path: path.resolve(__dirname, 'dist/js'),
|
||||||
|
},
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user