diff options
| author | RblSb <msrblsb@gmail.com> | 2021-01-24 13:12:58 +0300 |
|---|---|---|
| committer | RblSb <msrblsb@gmail.com> | 2021-01-24 13:12:58 +0300 |
| commit | 35beab11cdccf09dc77917a795b033314e62a5b1 (patch) | |
| tree | 23134d53f46ac678742f7fc4095b66dd68010617 | |
| parent | 3444b413ab12783c85ce73df9931142fea11b749 (diff) | |
Video title input
| -rw-r--r-- | res/client.js | 117 | ||||
| -rw-r--r-- | res/css/des.css | 18 | ||||
| -rw-r--r-- | res/index.html | 9 | ||||
| -rw-r--r-- | src/client/Buttons.hx | 17 | ||||
| -rw-r--r-- | src/client/InputWithHistory.hx | 21 | ||||
| -rw-r--r-- | src/client/Main.hx | 13 | ||||
| -rw-r--r-- | src/client/Player.hx | 4 | ||||
| -rw-r--r-- | src/client/players/Raw.hx | 27 |
8 files changed, 191 insertions, 35 deletions
diff --git a/res/client.js b/res/client.js index 1a0f9d3..071ad2c 100644 --- a/res/client.js +++ b/res/client.js @@ -99,6 +99,13 @@ HxOverrides.dateStr = function(date) { var s = date.getSeconds(); return date.getFullYear() + "-" + (m < 10 ? "0" + m : "" + m) + "-" + (d < 10 ? "0" + d : "" + d) + " " + (h < 10 ? "0" + h : "" + h) + ":" + (mi < 10 ? "0" + mi : "" + mi) + ":" + (s < 10 ? "0" + s : "" + s); }; +HxOverrides.cca = function(s,index) { + var x = s.charCodeAt(index); + if(x != x) { + return undefined; + } + return x; +}; HxOverrides.substr = function(s,pos,len) { if(len == null) { len = s.length; @@ -334,6 +341,37 @@ StringTools.endsWith = function(s,end) { return false; } }; +StringTools.isSpace = function(s,pos) { + var c = HxOverrides.cca(s,pos); + if(!(c > 8 && c < 14)) { + return c == 32; + } else { + return true; + } +}; +StringTools.ltrim = function(s) { + var l = s.length; + var r = 0; + while(r < l && StringTools.isSpace(s,r)) ++r; + if(r > 0) { + return HxOverrides.substr(s,r,l - r); + } else { + return s; + } +}; +StringTools.rtrim = function(s) { + var l = s.length; + var r = 0; + while(r < l && StringTools.isSpace(s,l - r - 1)) ++r; + if(r > 0) { + return HxOverrides.substr(s,0,l - r); + } else { + return s; + } +}; +StringTools.trim = function(s) { + return StringTools.ltrim(StringTools.rtrim(s)); +}; StringTools.replace = function(s,sub,by) { return s.split(sub).join(by); }; @@ -557,10 +595,19 @@ client_Buttons.init = function(main) { showCustomEmbed.onclick = function(e) { client_Buttons.showPlayerGroup(showCustomEmbed); }; + var mediaUrl = window.document.querySelector("#mediaurl"); + mediaUrl.oninput = function() { + var value = mediaUrl.value; + if(value != "" && main.isRawPlayerLink(value) && main.isSingleVideoLink(value)) { + return window.document.querySelector("#mediatitleblock").style.display = ""; + } else { + return window.document.querySelector("#mediatitleblock").style.display = "none"; + } + }; + mediaUrl.onfocus = mediaUrl.oninput; window.document.querySelector("#insert_template").onclick = function(e) { - var input = window.document.querySelector("#mediaurl"); - input.value = main.getTemplateUrl(); - input.focus(); + mediaUrl.value = main.getTemplateUrl(); + mediaUrl.focus(); }; var showOptions = window.document.querySelector("#showoptions"); showOptions.onclick = function(e) { @@ -793,6 +840,7 @@ client_InputWithHistory.prototype = { } this.historyId = -1; this.element.value = ""; + this.onInput(); break; case 38: this.historyId--; @@ -805,6 +853,7 @@ client_InputWithHistory.prototype = { this.historyId++; } this.element.value = this.history[this.historyId]; + this.onInput(); break; case 40: if(this.historyId == -1) { @@ -814,10 +863,17 @@ client_InputWithHistory.prototype = { if(this.historyId > this.history.length - 1) { this.historyId = -1; this.element.value = ""; - return; + } else { + this.element.value = this.history[this.historyId]; } - this.element.value = this.history[this.historyId]; + this.onInput(); break; + default: + } + } + ,onInput: function() { + if(this.element.oninput != null) { + this.element.oninput(); } } }; @@ -1025,6 +1081,11 @@ client_Main.prototype = { _gthis.addVideoUrl(true); return false; }); + window.document.querySelector("#mediatitle").onkeydown = function(e) { + if(e.keyCode == 13) { + _gthis.addVideoUrl(true); + } + }; window.document.querySelector("#ce_queue_next").onclick = function(e) { _gthis.addIframe(false); }; @@ -1080,6 +1141,18 @@ client_Main.prototype = { } this.addVideoArray(links,atEnd,isTemp); } + ,isRawPlayerLink: function(url) { + return this.player.isRawPlayerLink(url); + } + ,isSingleVideoLink: function(url) { + if(new EReg(", ?(https?)","g").match(url)) { + return false; + } + if(this.mask.match(url)) { + return false; + } + return true; + } ,sortItemsForQueueNext: function(items) { if(items.length == 0) { return; @@ -1186,7 +1259,7 @@ client_Main.prototype = { var data = JSON.parse(e.data); if(this.config != null && this.config.isVerbose) { var t = data.type; - haxe_Log.trace("Event: " + data.type,{ fileName : "src/client/Main.hx", lineNumber : 334, className : "client.Main", methodName : "onMessage", customParams : [Reflect.field(data,t.charAt(0).toLowerCase() + HxOverrides.substr(t,1,null))]}); + haxe_Log.trace("Event: " + data.type,{ fileName : "src/client/Main.hx", lineNumber : 347, className : "client.Main", methodName : "onMessage", customParams : [Reflect.field(data,t.charAt(0).toLowerCase() + HxOverrides.substr(t,1,null))]}); } client_JsApi.fireOnceEvent(data); switch(data.type) { @@ -1803,6 +1876,11 @@ client_Player.prototype = { } player.getVideoData(data,callback); } + ,isRawPlayerLink: function(url) { + return !Lambda.exists(this.players,function(player) { + return player.isSupportedLink(url); + }); + } ,getIframeData: function(data,callback) { this.iframePlayer.getVideoData(data,callback); } @@ -2351,9 +2429,12 @@ client_players_Raw.prototype = { var _gthis = this; var url = data.url; var decodedUrl = decodeURIComponent(url.split("+").join(" ")); + var optTitle = this.cutOptionalTitle(); var title = HxOverrides.substr(decodedUrl,decodedUrl.lastIndexOf("/") + 1,null); var isNameMatched = this.matchName.match(title); - if(isNameMatched) { + if(optTitle != "") { + title = optTitle; + } else if(isNameMatched) { title = this.matchName.matched(1); } else { title = Lang.get("rawVideo"); @@ -2361,12 +2442,14 @@ client_players_Raw.prototype = { var isHls = false; if(isNameMatched) { isHls = this.matchName.matched(2).indexOf("m3u8") != -1; - if(isHls && !this.isHlsLoaded) { - this.loadHlsPlugin(function() { - _gthis.getVideoData(data,callback); - }); - return; - } + } else { + isHls = StringTools.endsWith(title,"m3u8"); + } + if(isHls && !this.isHlsLoaded) { + this.loadHlsPlugin(function() { + _gthis.getVideoData(data,callback); + }); + return; } var video = window.document.createElement("video"); video.src = url; @@ -2387,6 +2470,12 @@ client_players_Raw.prototype = { this.initHlsSource(video,url); } } + ,cutOptionalTitle: function() { + var titleInput = window.document.querySelector("#mediatitle"); + var optTitle = StringTools.trim(titleInput.value); + titleInput.value = ""; + return optTitle; + } ,loadHlsPlugin: function(callback) { var _gthis = this; client_JsApi.addScriptToHead("https://cdn.jsdelivr.net/npm/hls.js@latest",function() { @@ -2405,7 +2494,7 @@ client_players_Raw.prototype = { ,loadVideo: function(item) { var _gthis = this; var url = this.main.tryLocalIp(item.url); - var isHls = item.url.indexOf("m3u8") != -1; + var isHls = item.url.indexOf("m3u8") != -1 || StringTools.endsWith(item.title,"m3u8"); if(isHls && !this.isHlsLoaded) { this.loadHlsPlugin(function() { _gthis.loadVideo(item); diff --git a/res/css/des.css b/res/css/des.css index 70a5019..aa423bd 100644 --- a/res/css/des.css +++ b/res/css/des.css @@ -223,6 +223,10 @@ button.danger-bg:focus { visibility: visible; } +.display-flex { + display: flex; +} + /* Info */ .info { @@ -342,6 +346,15 @@ header h4 { /* Add video */ +#insert_template { + min-width: 2rem; +} + +#insert_template > div:first-child { + text-align: center; + flex-grow: 1; +} + #addfromurl, #customembed { padding: 1rem; @@ -354,8 +367,9 @@ header h4 { margin-bottom: 1rem; } -#addfromurl > div:first-child { - display: flex; +#mediatitle { + margin-left: 2rem; + flex-grow: 1; } #mediaurl { diff --git a/res/index.html b/res/index.html index d901198..753a9a5 100644 --- a/res/index.html +++ b/res/index.html @@ -55,10 +55,15 @@ </div> <!-- Add video --> <div class="collapse" id="addfromurl" aria-expanded="false"> - <div> - <button id="insert_template" title="${addTemplateUrl}">></button> + <div class="display-flex"> + <button id="insert_template" title="${addTemplateUrl}"> + <div>></div> + </button> <input id="mediaurl" type="text" placeholder="${addVideoFromUrl}"> </div> + <div id="mediatitleblock" class="display-flex" style="display: none;"> + <input id="mediatitle" type="text" placeholder="${optionalTitle}"> + </div> <div> <button id="queue_next">${queueNext}</button> <button id="queue_end">${queueLast}</button> diff --git a/src/client/Buttons.hx b/src/client/Buttons.hx index cdc9780..538aaa0 100644 --- a/src/client/Buttons.hx +++ b/src/client/Buttons.hx @@ -8,6 +8,7 @@ import js.html.Element; import client.Main.ge; import js.Browser.window; import js.Browser.document; +using StringTools; class Buttons { @@ -150,10 +151,20 @@ class Buttons { final showCustomEmbed = ge("#showcustomembed"); showCustomEmbed.onclick = e -> showPlayerGroup(showCustomEmbed); + final mediaUrl:InputElement = cast ge("#mediaurl"); + mediaUrl.oninput = () -> { + final value = mediaUrl.value; + if (value != "" && main.isRawPlayerLink(value) && main.isSingleVideoLink(value)) { + ge("#mediatitleblock").style.display = ""; + } else { + ge("#mediatitleblock").style.display = "none"; + } + } + mediaUrl.onfocus = mediaUrl.oninput; + ge("#insert_template").onclick = e -> { - final input:InputElement = cast ge("#mediaurl"); - input.value = main.getTemplateUrl(); - input.focus(); + mediaUrl.value = main.getTemplateUrl(); + mediaUrl.focus(); } final showOptions = ge("#showoptions"); diff --git a/src/client/InputWithHistory.hx b/src/client/InputWithHistory.hx index ecba43a..c4e8bf4 100644 --- a/src/client/InputWithHistory.hx +++ b/src/client/InputWithHistory.hx @@ -29,8 +29,9 @@ class InputWithHistory { } function onKeyDown(e:KeyboardEvent) { - switch (e.keyCode) { - case 13: // Enter + final key:KeyCode = cast e.keyCode; + switch (key) { + case Return: final value = element.value; if (value.length == 0) return; final isAdd = onEnter(value); @@ -38,23 +39,31 @@ class InputWithHistory { if (history.length > maxItems) history.shift(); historyId = -1; element.value = ""; - case 38: // Up + onInput(); + case Up: historyId--; if (historyId == -2) { historyId = history.length - 1; if (historyId == -1) return; } else if (historyId == -1) historyId++; element.value = history[historyId]; - case 40: // Down + onInput(); + case Down: if (historyId == -1) return; historyId++; if (historyId > history.length - 1) { historyId = -1; element.value = ""; - return; + } else { + element.value = history[historyId]; } - element.value = history[historyId]; + onInput(); + default: } } + function onInput():Void { + if (element.oninput != null) element.oninput(); + } + } diff --git a/src/client/Main.hx b/src/client/Main.hx index 5c29d29..31558eb 100644 --- a/src/client/Main.hx +++ b/src/client/Main.hx @@ -146,6 +146,9 @@ class Main { addVideoUrl(true); return false; }); + ge("#mediatitle").onkeydown = (e:KeyboardEvent) -> { + if (e.keyCode == KeyCode.Return) addVideoUrl(true); + } ge("#ce_queue_next").onclick = e -> addIframe(false); ge("#ce_queue_end").onclick = e -> addIframe(true); @@ -210,6 +213,16 @@ class Main { addVideoArray(links, atEnd, isTemp); } + public function isRawPlayerLink(url:String):Bool { + return player.isRawPlayerLink(url); + } + + public function isSingleVideoLink(url:String):Bool { + if (~/, ?(https?)/g.match(url)) return false; + if (mask.match(url)) return false; + return true; + } + public function sortItemsForQueueNext<T>(items:Array<T>):Void { if (items.length == 0) return; // except first item when list empty diff --git a/src/client/Player.hx b/src/client/Player.hx index 59ca11f..9ee3ead 100644 --- a/src/client/Player.hx +++ b/src/client/Player.hx @@ -104,6 +104,10 @@ class Player { player.getVideoData(data, callback); } + public function isRawPlayerLink(url:String):Bool { + return !players.exists(player -> player.isSupportedLink(url)); + } + public function getIframeData(data:VideoDataRequest, callback:(data:VideoData)->Void):Void { iframePlayer.getVideoData(data, callback); } diff --git a/src/client/players/Raw.hx b/src/client/players/Raw.hx index 9a9d52e..fdb5e73 100644 --- a/src/client/players/Raw.hx +++ b/src/client/players/Raw.hx @@ -3,6 +3,7 @@ package client.players; import js.hlsjs.Hls; import haxe.Timer; import js.html.Element; +import js.html.InputElement; import js.html.VideoElement; import js.Browser.document; import client.Main.ge; @@ -34,17 +35,20 @@ class Raw implements IPlayer { public function getVideoData(data:VideoDataRequest, callback:(data:VideoData)->Void):Void { final url = data.url; final decodedUrl = url.urlDecode(); + + final optTitle = cutOptionalTitle(); var title = decodedUrl.substr(decodedUrl.lastIndexOf("/") + 1); final isNameMatched = matchName.match(title); - if (isNameMatched) title = matchName.matched(1); + if (optTitle != "") title = optTitle; + else if (isNameMatched) title = matchName.matched(1); else title = Lang.get("rawVideo"); + var isHls = false; - if (isNameMatched) { - isHls = matchName.matched(2).contains("m3u8"); - if (isHls && !isHlsLoaded) { - loadHlsPlugin(() -> getVideoData(data, callback)); - return; - } + if (isNameMatched) isHls = matchName.matched(2).contains("m3u8"); + else isHls = title.endsWith("m3u8"); + if (isHls && !isHlsLoaded) { + loadHlsPlugin(() -> getVideoData(data, callback)); + return; } final video = document.createVideoElement(); @@ -64,6 +68,13 @@ class Raw implements IPlayer { if (isHls) initHlsSource(video, url); } + function cutOptionalTitle():String { + final titleInput:InputElement = cast ge("#mediatitle"); + final optTitle = titleInput.value.trim(); + titleInput.value = ""; + return optTitle; + } + function loadHlsPlugin(callback:()->Void):Void { final url = "https://cdn.jsdelivr.net/npm/hls.js@latest"; JsApi.addScriptToHead(url, () -> { @@ -81,7 +92,7 @@ class Raw implements IPlayer { public function loadVideo(item:VideoItem):Void { final url = main.tryLocalIp(item.url); - final isHls = item.url.contains("m3u8"); + final isHls = item.url.contains("m3u8") || item.title.endsWith("m3u8"); if (isHls && !isHlsLoaded) { loadHlsPlugin(() -> loadVideo(item)); return; |
