Initial srt support setup; ntfy bind change, seek event alterations; js-cookie file upgraded
This commit is contained in:
parent
5ef1259bb4
commit
5f9dfa12f4
@ -96,7 +96,7 @@ def _start_rtsp_and_ntfy_server():
|
|||||||
@daemon_threaded
|
@daemon_threaded
|
||||||
def _start_ntfy_server_threaded():
|
def _start_ntfy_server_threaded():
|
||||||
os.chdir(NTFY_PATH)
|
os.chdir(NTFY_PATH)
|
||||||
command = ["./ntfy", "serve", "--behind-proxy", "--listen-http", ":7777"]
|
command = ["./ntfy", "serve", "--behind-proxy", "--listen-http", "127.0.0.1:7777"]
|
||||||
process = subprocess.Popen(command)
|
process = subprocess.Popen(command)
|
||||||
process.wait()
|
process.wait()
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import requests
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
# Lib imports
|
# Lib imports
|
||||||
|
from flask import abort
|
||||||
from flask import make_response
|
from flask import make_response
|
||||||
from flask import redirect
|
from flask import redirect
|
||||||
from flask import request
|
from flask import request
|
||||||
@ -42,6 +43,17 @@ def home():
|
|||||||
message = 'Must use GET request type...')
|
message = 'Must use GET request type...')
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: Yeah, not exactly logged but meh.
|
||||||
|
@app.route('/log-client-exception', methods=['GET', 'POST'])
|
||||||
|
def ui_failure_exception_tracker():
|
||||||
|
if request.method == 'POST':
|
||||||
|
DATA = str(request.values['exception_data']).strip()
|
||||||
|
print(f"\n\n{DATA}")
|
||||||
|
return json_message.create("success", "UI Exception logged...")
|
||||||
|
|
||||||
|
return json_message.create("danger", "Must use POST request type...")
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/list-files/<_hash>', methods=['GET', 'POST'])
|
@app.route('/api/list-files/<_hash>', methods=['GET', 'POST'])
|
||||||
def list_files(_hash = None):
|
def list_files(_hash = None):
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
@ -93,7 +105,12 @@ def file_manager_action(_type, _hash = None):
|
|||||||
|
|
||||||
folder = view.get_current_directory()
|
folder = view.get_current_directory()
|
||||||
file = view.get_path_part_from_hash(_hash)
|
file = view.get_path_part_from_hash(_hash)
|
||||||
|
fpath = None;
|
||||||
|
try:
|
||||||
fpath = os.path.join(folder, file)
|
fpath = os.path.join(folder, file)
|
||||||
|
except Exception as e:
|
||||||
|
return abort(404)
|
||||||
|
|
||||||
logger.debug(fpath)
|
logger.debug(fpath)
|
||||||
|
|
||||||
if _type == "files":
|
if _type == "files":
|
||||||
|
@ -46,6 +46,15 @@
|
|||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#selectedFile,
|
||||||
|
#video-controls {
|
||||||
|
font-size: x-large;
|
||||||
|
}
|
||||||
|
|
||||||
|
#seek-slider {
|
||||||
|
width: -moz-available !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* CLASSES */
|
/* CLASSES */
|
||||||
.scroller {
|
.scroller {
|
||||||
|
Before Width: | Height: | Size: 680 KiB After Width: | Height: | Size: 680 KiB |
@ -1,88 +1,76 @@
|
|||||||
/*!
|
|
||||||
* JavaScript Cookie v2.2.0
|
|
||||||
* https://github.com/js-cookie/js-cookie
|
|
||||||
*
|
|
||||||
* Copyright 2006, 2015 Klaus Hartl & Fagner Brack
|
|
||||||
* Released under the MIT license
|
|
||||||
*/
|
|
||||||
;(function (factory) {
|
|
||||||
var registeredInModuleLoader;
|
|
||||||
if (typeof define === 'function' && define.amd) {
|
|
||||||
define(factory);
|
|
||||||
registeredInModuleLoader = true;
|
|
||||||
}
|
|
||||||
if (typeof exports === 'object') {
|
|
||||||
module.exports = factory();
|
|
||||||
registeredInModuleLoader = true;
|
|
||||||
}
|
|
||||||
if (!registeredInModuleLoader) {
|
|
||||||
var OldCookies = window.Cookies;
|
|
||||||
var api = window.Cookies = factory();
|
|
||||||
api.noConflict = function () {
|
|
||||||
window.Cookies = OldCookies;
|
|
||||||
return api;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}(function () {
|
|
||||||
function extend () {
|
|
||||||
var i = 0;
|
|
||||||
var result = {};
|
|
||||||
for (; i < arguments.length; i++) {
|
|
||||||
var attributes = arguments[ i ];
|
|
||||||
for (var key in attributes) {
|
|
||||||
result[key] = attributes[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
function decode (s) {
|
/*! js-cookie v3.0.4 | MIT */
|
||||||
return s.replace(/(%[0-9A-Z]{2})+/g, decodeURIComponent);
|
;
|
||||||
|
(function (global, factory) {
|
||||||
|
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
|
||||||
|
typeof define === 'function' && define.amd ? define(factory) :
|
||||||
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, (function () {
|
||||||
|
var current = global.Cookies;
|
||||||
|
var exports = global.Cookies = factory();
|
||||||
|
exports.noConflict = function () { global.Cookies = current; return exports; };
|
||||||
|
})());
|
||||||
|
})(this, (function () { 'use strict';
|
||||||
|
|
||||||
|
/* eslint-disable no-var */
|
||||||
|
function assign (target) {
|
||||||
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
|
var source = arguments[i];
|
||||||
|
for (var key in source) {
|
||||||
|
target[key] = source[key];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
/* eslint-enable no-var */
|
||||||
|
|
||||||
function init (converter) {
|
/* eslint-disable no-var */
|
||||||
function api() {}
|
var defaultConverter = {
|
||||||
|
read: function (value) {
|
||||||
|
if (value[0] === '"') {
|
||||||
|
value = value.slice(1, -1);
|
||||||
|
}
|
||||||
|
return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent)
|
||||||
|
},
|
||||||
|
write: function (value) {
|
||||||
|
return encodeURIComponent(value).replace(
|
||||||
|
/%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g,
|
||||||
|
decodeURIComponent
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
/* eslint-enable no-var */
|
||||||
|
|
||||||
function set (key, value, attributes) {
|
/* eslint-disable no-var */
|
||||||
|
|
||||||
|
function init (converter, defaultAttributes) {
|
||||||
|
function set (name, value, attributes) {
|
||||||
if (typeof document === 'undefined') {
|
if (typeof document === 'undefined') {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
attributes = extend({
|
attributes = assign({}, defaultAttributes, attributes);
|
||||||
path: '/'
|
|
||||||
}, api.defaults, attributes);
|
|
||||||
|
|
||||||
if (typeof attributes.expires === 'number') {
|
if (typeof attributes.expires === 'number') {
|
||||||
attributes.expires = new Date(new Date() * 1 + attributes.expires * 864e+5);
|
attributes.expires = new Date(Date.now() + attributes.expires * 864e5);
|
||||||
|
}
|
||||||
|
if (attributes.expires) {
|
||||||
|
attributes.expires = attributes.expires.toUTCString();
|
||||||
}
|
}
|
||||||
|
|
||||||
// We're using "expires" because "max-age" is not supported by IE
|
name = encodeURIComponent(name)
|
||||||
attributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';
|
.replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent)
|
||||||
|
.replace(/[()]/g, escape);
|
||||||
try {
|
|
||||||
var result = JSON.stringify(value);
|
|
||||||
if (/^[\{\[]/.test(result)) {
|
|
||||||
value = result;
|
|
||||||
}
|
|
||||||
} catch (e) {}
|
|
||||||
|
|
||||||
value = converter.write ?
|
|
||||||
converter.write(value, key) :
|
|
||||||
encodeURIComponent(String(value))
|
|
||||||
.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);
|
|
||||||
|
|
||||||
key = encodeURIComponent(String(key))
|
|
||||||
.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent)
|
|
||||||
.replace(/[\(\)]/g, escape);
|
|
||||||
|
|
||||||
var stringifiedAttributes = '';
|
var stringifiedAttributes = '';
|
||||||
for (var attributeName in attributes) {
|
for (var attributeName in attributes) {
|
||||||
if (!attributes[attributeName]) {
|
if (!attributes[attributeName]) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
stringifiedAttributes += '; ' + attributeName;
|
stringifiedAttributes += '; ' + attributeName;
|
||||||
|
|
||||||
if (attributes[attributeName] === true) {
|
if (attributes[attributeName] === true) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Considers RFC 6265 section 5.2:
|
// Considers RFC 6265 section 5.2:
|
||||||
@ -95,69 +83,66 @@
|
|||||||
stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
|
stringifiedAttributes += '=' + attributes[attributeName].split(';')[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return (document.cookie = key + '=' + value + stringifiedAttributes);
|
return (document.cookie =
|
||||||
|
name + '=' + converter.write(value, name) + stringifiedAttributes)
|
||||||
}
|
}
|
||||||
|
|
||||||
function get (key, json) {
|
function get (name) {
|
||||||
if (typeof document === 'undefined') {
|
if (typeof document === 'undefined' || (arguments.length && !name)) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var jar = {};
|
|
||||||
// To prevent the for loop in the first place assign an empty array
|
// To prevent the for loop in the first place assign an empty array
|
||||||
// in case there are no cookies at all.
|
// in case there are no cookies at all.
|
||||||
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
||||||
var i = 0;
|
var jar = {};
|
||||||
|
for (var i = 0; i < cookies.length; i++) {
|
||||||
for (; i < cookies.length; i++) {
|
|
||||||
var parts = cookies[i].split('=');
|
var parts = cookies[i].split('=');
|
||||||
var cookie = parts.slice(1).join('=');
|
var value = parts.slice(1).join('=');
|
||||||
|
|
||||||
if (!json && cookie.charAt(0) === '"') {
|
|
||||||
cookie = cookie.slice(1, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var name = decode(parts[0]);
|
var found = decodeURIComponent(parts[0]);
|
||||||
cookie = (converter.read || converter)(cookie, name) ||
|
jar[found] = converter.read(value, found);
|
||||||
decode(cookie);
|
|
||||||
|
|
||||||
if (json) {
|
if (name === found) {
|
||||||
try {
|
break
|
||||||
cookie = JSON.parse(cookie);
|
|
||||||
} catch (e) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
jar[name] = cookie;
|
|
||||||
|
|
||||||
if (key === name) {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return key ? jar[key] : jar;
|
return name ? jar[name] : jar
|
||||||
}
|
}
|
||||||
|
|
||||||
api.set = set;
|
return Object.create(
|
||||||
api.get = function (key) {
|
{
|
||||||
return get(key, false /* read as raw */);
|
set,
|
||||||
};
|
get,
|
||||||
api.getJSON = function (key) {
|
remove: function (name, attributes) {
|
||||||
return get(key, true /* read as json */);
|
set(
|
||||||
};
|
name,
|
||||||
api.remove = function (key, attributes) {
|
'',
|
||||||
set(key, '', extend(attributes, {
|
assign({}, attributes, {
|
||||||
expires: -1
|
expires: -1
|
||||||
}));
|
})
|
||||||
};
|
);
|
||||||
|
},
|
||||||
|
withAttributes: function (attributes) {
|
||||||
|
return init(this.converter, assign({}, this.attributes, attributes))
|
||||||
|
},
|
||||||
|
withConverter: function (converter) {
|
||||||
|
return init(assign({}, this.converter, converter), this.attributes)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
attributes: { value: Object.freeze(defaultAttributes) },
|
||||||
|
converter: { value: Object.freeze(converter) }
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
api.defaults = {};
|
var api = init(defaultConverter, { path: '/' });
|
||||||
|
/* eslint-enable no-var */
|
||||||
api.withConverter = init;
|
|
||||||
|
|
||||||
return api;
|
return api;
|
||||||
}
|
|
||||||
|
|
||||||
return init(function () {});
|
|
||||||
}));
|
}));
|
||||||
|
2
src/core/static/js/libs/srt-support.js
Normal file
2
src/core/static/js/libs/srt-support.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
(function(){"use strict";class i{number;startTime;endTime;text;constructor(t,e,s,r){this.number=t,this.startTime=e,this.endTime=s,this.text=r}}function c(n){try{if(!n||n===" ")return!1;const t={number:parseInt(n.match(/^\d+/g)[0]),timing:{start:n.match(/(\d+:){2}\d+,\d+/g)[0].replace(",","."),end:n.match(/(\d+:){2}\d+,\d+/g)[1].replace(",",".")},text:n.split(/\r?\n/g).slice(2,n.split(/\r?\n/g).length).join(`
|
||||||
|
`)};return new i(t.number,a(t.timing.start),a(t.timing.end),t.text)}catch{return!1}}function a(n){let t=n.split(":"),e=0,s=1;for(;t.length>0;)e+=s*parseFloat(t.pop(),10),s*=60;return e}async function o(n,t="utf-8"){return(!t||t==="")&&(t="utf-8"),fetch(n).then(e=>e.arrayBuffer()).then(e=>new TextDecoder(t).decode(e))}class d{src;encoding;lang;kind;label;default;body;needsTransform;cues=[];constructor(t){this.src=t.src,this.encoding=t.dataset.encoding,this.lang=t.srclang,this.kind=t.kind,this.label=t.label,this.default=t.default,this.needsTransform=!this.src.toLowerCase().endsWith(".vtt")}async parse(){this.body=await o(this.src,this.encoding),this.cues=this.body.split(/\r?\n\r?\n/g).map(c).filter(Boolean)}}async function l(n){const t=[...n.querySelectorAll("track")].map(e=>new d(e));for(const e of t){if(!e.needsTransform)continue;await e.parse();const s=n.addTextTrack(e.kind,e.label,e.lang);e.cues.forEach(r=>s.addCue(new VTTCue(r.startTime,r.endTime,r.text))),e.default&&(s.mode="showing")}}document.addEventListener("DOMContentLoaded",()=>[...document.querySelectorAll("video")].forEach(l))})();
|
@ -1,17 +1,41 @@
|
|||||||
const img2TabElm = document.getElementById("img2Tab");
|
const img2TabElm = document.getElementById("img2Tab");
|
||||||
const ctxDownloadElm = document.getElementById("ctxDownload");
|
const ctxDownloadElm = document.getElementById("ctxDownload");
|
||||||
|
const txt2copy = document.getElementById("txt2copy");
|
||||||
const menu = document.querySelector(".menu");
|
const menu = document.querySelector(".menu");
|
||||||
|
|
||||||
|
let text2copy = "";
|
||||||
let menuVisible = false;
|
let menuVisible = false;
|
||||||
let img2TabSrc = null;
|
let img2TabSrc = null;
|
||||||
let active_card = null;
|
let active_card = null;
|
||||||
|
|
||||||
|
|
||||||
const img2Tab = () => {
|
const img2Tab = () => {
|
||||||
if (img2TabSrc !== null) {
|
if (img2TabSrc !== null) {
|
||||||
window.open(img2TabSrc,'_blank');
|
window.open(img2TabSrc,'_blank');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const text2Clipboard = () => {
|
||||||
|
try {
|
||||||
|
navigator.clipboard.writeText(text2copy);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Failed to copy: ', err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getSelectedText = () => {
|
||||||
|
let text = "";
|
||||||
|
|
||||||
|
if (typeof window.getSelection != "undefined") {
|
||||||
|
text = window.getSelection().toString();
|
||||||
|
} else if (typeof document.selection != "undefined" && document.selection.type == "Text") {
|
||||||
|
text = document.selection.createRange().text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const toggleMenu = command => {
|
const toggleMenu = command => {
|
||||||
menu.style.display = command === "show" ? "block" : "none";
|
menu.style.display = command === "show" ? "block" : "none";
|
||||||
menu.style.zIndex = "9999";
|
menu.style.zIndex = "9999";
|
||||||
@ -25,6 +49,13 @@ const setPosition = ({ top, left }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
document.body.addEventListener("mouseup", e => {
|
||||||
|
const data = getSelectedText();
|
||||||
|
if (e.which !== 3 && e.target.innerText !== "Copy") {
|
||||||
|
text2copy = data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
document.body.addEventListener("click", e => {
|
document.body.addEventListener("click", e => {
|
||||||
if(menuVisible) toggleMenu("hide");
|
if(menuVisible) toggleMenu("hide");
|
||||||
});
|
});
|
||||||
@ -42,6 +73,7 @@ document.body.addEventListener("contextmenu", e => {
|
|||||||
elm.getAttribute("ftype") === "image")
|
elm.getAttribute("ftype") === "image")
|
||||||
)) ? "block" : "none";
|
)) ? "block" : "none";
|
||||||
img2TabElm.style.display = (elm.nodeName === "IMG") ? "block" : "none";
|
img2TabElm.style.display = (elm.nodeName === "IMG") ? "block" : "none";
|
||||||
|
txt2copy.style.display = (text2copy !== "") ? "block" : "none";
|
||||||
img2TabSrc = (elm.nodeName === "IMG") ? elm.src : null;
|
img2TabSrc = (elm.nodeName === "IMG") ? elm.src : null;
|
||||||
|
|
||||||
while (elm.nodeName != "BODY") {
|
while (elm.nodeName != "BODY") {
|
||||||
|
@ -52,15 +52,16 @@ const scrollFilesToTop = () => {
|
|||||||
const closeFile = async () => {
|
const closeFile = async () => {
|
||||||
const trailerPlayer = document.getElementById("trailerPlayer")
|
const trailerPlayer = document.getElementById("trailerPlayer")
|
||||||
let title = document.getElementById("selectedFile");
|
let title = document.getElementById("selectedFile");
|
||||||
|
let player = document.getElementById("video");
|
||||||
|
|
||||||
document.getElementById("video-container").style.display = "node";
|
document.getElementById("video-container").style.display = "node";
|
||||||
document.getElementById("image-viewer").style.display = "none";
|
document.getElementById("image-viewer").style.display = "none";
|
||||||
document.getElementById("text-viewer").style.display = "none";
|
document.getElementById("text-viewer").style.display = "none";
|
||||||
document.getElementById("pdf-viewer").style.display = "none";
|
document.getElementById("pdf-viewer").style.display = "none";
|
||||||
player.jPlayer("pause")
|
|
||||||
|
|
||||||
title.innerText = "";
|
title.innerText = "";
|
||||||
trailerPlayer.src = "#";
|
trailerPlayer.src = "#";
|
||||||
|
player.pause();
|
||||||
trailerPlayer.style.display = "none";
|
trailerPlayer.style.display = "none";
|
||||||
|
|
||||||
// FIXME: Yes, a wasted call every time there is no stream.
|
// FIXME: Yes, a wasted call every time there is no stream.
|
||||||
|
@ -4,16 +4,23 @@ let shouldPlay = null;
|
|||||||
let controlsTimeout = null;
|
let controlsTimeout = null;
|
||||||
let playListMode = false;
|
let playListMode = false;
|
||||||
let videoPlaylist = [];
|
let videoPlaylist = [];
|
||||||
|
let seekto = null;
|
||||||
|
|
||||||
|
|
||||||
const getTimeFormatted = (duration = null) => {
|
const getTimeFormatted = (duration = null) => {
|
||||||
if (duration == null) { return "00:00"; }
|
if (duration == null) { return "00:00:00"; }
|
||||||
|
|
||||||
const hours = (duration / 3600).toFixed(2).split(".")[0];
|
const hours = (duration / 3600).toFixed(2).split(".")[0];
|
||||||
const minutes = (duration / 60).toFixed(2).split(".")[0];
|
let _duration = (duration / 60).toFixed(2).split(".")[0]
|
||||||
|
const minutes = (_duration - (hours * 60)).toFixed(2).split(".")[0];
|
||||||
const time = (duration / 60).toFixed(2)
|
const time = (duration / 60).toFixed(2)
|
||||||
const seconds = Math.floor( (time - Math.floor(time) ) * 60);
|
const seconds = Math.floor( (time - Math.floor(time) ) * 60);
|
||||||
|
|
||||||
return hours + ":" + minutes + ":" + seconds;
|
return padnum(hours) + " : " + padnum(minutes) + " : " + padnum(seconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
const padnum = (value = 0) => {
|
||||||
|
return (value > 9) ? value : "0" + value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -115,9 +122,49 @@ const loadMediaToPlayer = (title = "", video_path = "") => {
|
|||||||
const modal = new bootstrap.Modal(document.getElementById('file-view-modal'), { keyboard: false });
|
const modal = new bootstrap.Modal(document.getElementById('file-view-modal'), { keyboard: false });
|
||||||
const player = document.getElementById("video");
|
const player = document.getElementById("video");
|
||||||
player.src = video_path;
|
player.src = video_path;
|
||||||
|
|
||||||
|
loadSubtitles(title);
|
||||||
modal.show();
|
modal.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const insertSubtitle = (path = "", label = "English Track: NONE") => {
|
||||||
|
fetch(path).then((response) => {
|
||||||
|
if(response.status == 200) {
|
||||||
|
const player = document.getElementById("video");
|
||||||
|
let track = document.createElement("TRACK");
|
||||||
|
|
||||||
|
track.srclang = "en";
|
||||||
|
track.kind = "subtitles";
|
||||||
|
track.label = label;
|
||||||
|
track.src = path;
|
||||||
|
track.setAttribute("default", "");
|
||||||
|
|
||||||
|
player.appendChild(track);
|
||||||
|
}
|
||||||
|
}).catch(function(error) {
|
||||||
|
let subStr1 = 'There has been a problem with your fetch operation: ' + error.message;
|
||||||
|
msg = "[Error] Status Code: 000\n[Message] -->" + subStr1;
|
||||||
|
return {'message': { 'type': "error", 'text': msg} }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadSubtitles = (title = "") => {
|
||||||
|
const player = document.getElementById("video");
|
||||||
|
const subtitle_stub = title.split(".")[0];
|
||||||
|
const subs = [`${subtitle_stub}.vtt`, `${subtitle_stub}.en.vtt`, `${subtitle_stub}.srt`, `${subtitle_stub}.en.srt`];
|
||||||
|
|
||||||
|
clearChildNodes(player)
|
||||||
|
let k = 0;
|
||||||
|
for (var i = 0; i < subs.length; i++) {
|
||||||
|
getSHA256Hash(subs[i]).then((_hash) => {
|
||||||
|
const data = "empty=NULL";
|
||||||
|
subtitle_path = "api/file-manager-action/files/" + _hash;
|
||||||
|
insertSubtitle(subtitle_path, subs[k]);
|
||||||
|
k += 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -221,12 +268,32 @@ $( "#video").bind( "stalled", async function(eve) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
$( "#seek-slider").bind( "change", async function(eve) {
|
$( "#seek-slider").bind( "change", async function(eve) {
|
||||||
const slider = eve.target;
|
const video = document.getElementById("video");
|
||||||
let video = document.getElementById("video");
|
|
||||||
let seekto = video.duration * (slider.value / 100);
|
|
||||||
video.currentTime = seekto;
|
video.currentTime = seekto;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$( "#seek-slider").bind( "mousemove", async function(eve) {
|
||||||
|
const slider = eve.target;
|
||||||
|
const video = document.getElementById("video");
|
||||||
|
const seek = document.getElementById("seek-time");
|
||||||
|
const rect = slider.getBoundingClientRect()
|
||||||
|
const offset = rect.right - rect.width;
|
||||||
|
|
||||||
|
const slider_val = Math.floor(
|
||||||
|
(
|
||||||
|
(eve.pageX - offset) / (rect.right - offset)
|
||||||
|
) * 100
|
||||||
|
)
|
||||||
|
|
||||||
|
seekto = video.duration * (slider_val / 100);
|
||||||
|
seek.innerText = getTimeFormatted(seekto);
|
||||||
|
});
|
||||||
|
|
||||||
|
$( "#seek-slider").bind( "mouseleave", async function(eve) {
|
||||||
|
const seekto = document.getElementById("seek-time");
|
||||||
|
seekto.innerText = "";
|
||||||
|
});
|
||||||
|
|
||||||
$( "#volume-slider").bind( "change", async function(eve) {
|
$( "#volume-slider").bind( "change", async function(eve) {
|
||||||
const slider = eve.target;
|
const slider = eve.target;
|
||||||
let video = document.getElementById("video");
|
let video = document.getElementById("video");
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
<li class="menu-option" onclick="goHome()">Home Directory</li>
|
<li class="menu-option" onclick="goHome()">Home Directory</li>
|
||||||
<li id="ctxDownload" class="menu-option" onclick="downloadItem()">Download</li>
|
<li id="ctxDownload" class="menu-option" onclick="downloadItem()">Download</li>
|
||||||
<li id="img2Tab" class="menu-option" onclick="img2Tab()">Image To New Tab</li>
|
<li id="img2Tab" class="menu-option" onclick="img2Tab()">Image To New Tab</li>
|
||||||
|
<li id="txt2copy" class="menu-option" onclick="text2Clipboard()">Copy</li>
|
||||||
<li class="menu-option" onclick="deleteItem()">Delete</li>
|
<li class="menu-option" onclick="deleteItem()">Delete</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -111,6 +111,7 @@
|
|||||||
|
|
||||||
<script src="{{ url_for('static', filename='js/libs/cookie-manager.js')}}"></script>
|
<script src="{{ url_for('static', filename='js/libs/cookie-manager.js')}}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/libs/color-mode-toggler.js')}}"></script>
|
<script src="{{ url_for('static', filename='js/libs/color-mode-toggler.js')}}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/libs/srt-support.js')}}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/webfm/context-menu.js')}}"></script>
|
<script src="{{ url_for('static', filename='js/webfm/context-menu.js')}}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/webfm/backgrounds-manager.js')}}"></script>
|
<script src="{{ url_for('static', filename='js/webfm/backgrounds-manager.js')}}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/webfm/sse.js')}}"></script>
|
<script src="{{ url_for('static', filename='js/webfm/sse.js')}}"></script>
|
||||||
|
@ -93,9 +93,12 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="video-controls" class="modal-footer">
|
<div id="video-controls" class="modal-footer">
|
||||||
<div class="col-md-8">
|
<div class="col-md-6">
|
||||||
<input id="seek-slider" class="form-control-range" style="width: inherit;" type="range" min="0" value="0" max="100" step="1"/>
|
<input id="seek-slider" class="form-control-range" style="width: inherit;" type="range" min="0" value="0" max="100" step="1"/>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<label id="seek-time"></label>
|
||||||
|
</div>
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<span id="videoCurrentTime"></span>
|
<span id="videoCurrentTime"></span>
|
||||||
/
|
/
|
||||||
|
Loading…
Reference in New Issue
Block a user