diff options
| author | RblSb <msrblsb@gmail.com> | 2020-06-07 18:45:22 +0300 |
|---|---|---|
| committer | RblSb <msrblsb@gmail.com> | 2020-06-07 18:45:22 +0300 |
| commit | d31f0b30481f6180e7907aee27413e5d208539aa (patch) | |
| tree | ad1281ef9f5100bd05108dc42b8f5107f585444a | |
| parent | f2567959538d7a7b26aa405353c2dbea4e6cc945 (diff) | |
Playlists "at next" order
| -rw-r--r-- | res/client.js | 75 | ||||
| -rw-r--r-- | src/Types.hx | 5 | ||||
| -rw-r--r-- | src/client/IPlayer.hx | 3 | ||||
| -rw-r--r-- | src/client/Main.hx | 30 | ||||
| -rw-r--r-- | src/client/Player.hx | 11 | ||||
| -rw-r--r-- | src/client/players/Iframe.hx | 7 | ||||
| -rw-r--r-- | src/client/players/Raw.hx | 9 | ||||
| -rw-r--r-- | src/client/players/Youtube.hx | 32 |
8 files changed, 106 insertions, 66 deletions
diff --git a/res/client.js b/res/client.js index 2c2a507..9bc4a2c 100644 --- a/res/client.js +++ b/res/client.js @@ -1080,17 +1080,23 @@ client_Main.prototype = { var links = url.replace(_this_r,"|$1").split("|"); this.handleUrlMasks(links); if(!atEnd) { - var first = null; - if(this.player.isListEmpty()) { - first = links.shift(); - } - links.reverse(); - if(this.player.isListEmpty()) { - links.unshift(first); - } + this.sortItemsForQueueNext(links); } this.addVideoArray(links,atEnd,isTemp); } + ,sortItemsForQueueNext: function(items) { + if(items.length == 0) { + return; + } + var first = null; + if(this.player.isListEmpty()) { + first = items.shift(); + } + items.reverse(); + if(this.player.isListEmpty()) { + items.unshift(first); + } + } ,addVideoArray: function(links,atEnd,isTemp) { var _gthis = this; if(links.length == 0) { @@ -1109,7 +1115,7 @@ client_Main.prototype = { if(!StringTools.startsWith(url,"http")) { url = "" + protocol + "//" + url; } - this.player.getVideoData(url,function(data) { + this.player.getVideoData({ url : url, atEnd : atEnd},function(data) { if(data.duration == 0) { _gthis.serverMessage(4,Lang.get("addVideoError")); return; @@ -1136,7 +1142,7 @@ client_Main.prototype = { var title = mediaTitle.value; mediaTitle.value = ""; var isTemp = window.document.querySelector("#customembed").querySelector(".add-temp").checked; - this.player.getIframeData(iframe,function(data) { + this.player.getIframeData({ url : iframe, atEnd : atEnd},function(data) { if(data.duration == 0) { _gthis.serverMessage(4,Lang.get("addVideoError")); return; @@ -1184,7 +1190,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 : 330, 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 : 342, 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) { @@ -1768,17 +1774,17 @@ client_Player.prototype = { } this.player = newPlayer; } - ,getVideoData: function(url,callback) { + ,getVideoData: function(data,callback) { var player = Lambda.find(this.players,function(player) { - return player.isSupportedLink(url); + return player.isSupportedLink(data.url); }); if(player == null) { player = this.rawPlayer; } - player.getVideoData(url,callback); + player.getVideoData(data,callback); } - ,getIframeData: function(iframe,callback) { - this.iframePlayer.getVideoData(iframe,callback); + ,getIframeData: function(data,callback) { + this.iframePlayer.getVideoData(data,callback); } ,setVideo: function(i) { if(!this.main.isSyncActive) { @@ -2227,7 +2233,7 @@ client_players_Iframe.prototype = { } ,getVideoData: function(data,callback) { var iframe = window.document.createElement("div"); - iframe.innerHTML = data; + iframe.innerHTML = data.url; if(this.isValidIframe(iframe)) { callback({ duration : 356400}); } else { @@ -2296,8 +2302,9 @@ client_players_Raw.prototype = { isSupportedLink: function(url) { return true; } - ,getVideoData: function(url,callback) { + ,getVideoData: function(data,callback) { var _gthis = this; + var url = data.url; var decodedUrl = decodeURIComponent(url.split("+").join(" ")); var title = HxOverrides.substr(decodedUrl,decodedUrl.lastIndexOf("/") + 1,null); var isNameMatched = this.matchName.match(title); @@ -2311,7 +2318,7 @@ client_players_Raw.prototype = { isHls = this.matchName.matched(2).indexOf("m3u8") != -1; if(isHls && !this.isHlsLoaded) { this.loadHlsPlugin(function() { - _gthis.getVideoData(url,callback); + _gthis.getVideoData(data,callback); }); return; } @@ -2509,19 +2516,20 @@ client_players_Youtube.prototype = { } return total; } - ,getVideoData: function(url,callback) { + ,getVideoData: function(data,callback) { var _gthis = this; + var url = data.url; if(this.apiKey == null) { this.apiKey = this.main.getYoutubeApiKey(); } var id = this.extractVideoId(url); if(id == "") { - this.getPlaylistVideoData(url,callback); + this.getPlaylistVideoData(data,callback); return; } var http = new haxe_http_HttpJs("" + this.videosUrl + this.urlTitleDuration + "&id=" + id + "&key=" + this.apiKey); - http.onData = function(data) { - var json = JSON.parse(data); + http.onData = function(text) { + var json = JSON.parse(text); if(json.error != null) { _gthis.youtubeApiError(json.error); _gthis.getRemoteDataFallback(url,callback); @@ -2539,8 +2547,8 @@ client_players_Youtube.prototype = { var title = item.snippet.title; var duration = _gthis.convertTime(item.contentDetails.duration); if(duration == 0) { - callback({ duration : 356400, title : title, url : "<iframe src=\"https://www.youtube.com/embed/" + id + "\" frameborder=\"0\"\n\t\t\t\t\t\t\t\tallow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\"\n\t\t\t\t\t\t\t\tallowfullscreen></iframe>", isIframe : true}); - return; + callback({ duration : 356400, title : title, url : "<iframe src=\"https://www.youtube.com/embed/" + id + "\" frameborder=\"0\"\n\t\t\t\t\t\t\tallow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\"\n\t\t\t\t\t\t\tallowfullscreen></iframe>", isIframe : true}); + continue; } callback({ duration : duration, title : title, url : url}); } @@ -2550,12 +2558,12 @@ client_players_Youtube.prototype = { }; http.request(); } - ,getPlaylistVideoData: function(url,callback) { + ,getPlaylistVideoData: function(data,callback) { var _gthis = this; - var id = this.extractPlaylistId(url); + var id = this.extractPlaylistId(data.url); var http = new haxe_http_HttpJs("" + this.playlistUrl + this.urlVideoId + "&maxResults=50&playlistId=" + id + "&key=" + this.apiKey); - http.onData = function(data) { - var json = JSON.parse(data); + http.onData = function(text) { + var json = JSON.parse(text); if(json.error != null) { _gthis.youtubeApiError(json.error); callback({ duration : 0}); @@ -2566,10 +2574,13 @@ client_players_Youtube.prototype = { callback({ duration : 0}); return; } + if(!data.atEnd) { + _gthis.main.sortItemsForQueueNext(items); + } var loadNextItem = null; loadNextItem = function() { - var id = items.shift().snippet.resourceId.videoId; - _gthis.getVideoData("youtu.be/" + id,function(data) { + var obj = { url : "https://youtu.be/" + items.shift().snippet.resourceId.videoId, atEnd : data.atEnd}; + _gthis.getVideoData(obj,function(data) { callback(data); if(items.length > 0) { loadNextItem(); @@ -2603,7 +2614,7 @@ client_players_Youtube.prototype = { } callback({ duration : _gthis.tempYoutube.getDuration()}); }, onError : function(e) { - haxe_Log.trace("Error " + e.data,{ fileName : "src/client/players/Youtube.hx", lineNumber : 183, className : "client.players.Youtube", methodName : "getRemoteDataFallback"}); + haxe_Log.trace("Error " + e.data,{ fileName : "src/client/players/Youtube.hx", lineNumber : 191, className : "client.players.Youtube", methodName : "getRemoteDataFallback"}); if(_gthis.playerEl.contains(video)) { _gthis.playerEl.removeChild(video); } diff --git a/src/Types.hx b/src/Types.hx index eb137da..f9bc104 100644 --- a/src/Types.hx +++ b/src/Types.hx @@ -2,6 +2,11 @@ package; import Client.ClientData; +typedef VideoDataRequest = { + url:String, + atEnd:Bool +} + typedef VideoData = { duration:Float, ?title:String, diff --git a/src/client/IPlayer.hx b/src/client/IPlayer.hx index 4cdcb0b..7f626b1 100644 --- a/src/client/IPlayer.hx +++ b/src/client/IPlayer.hx @@ -1,11 +1,12 @@ package client; +import Types.VideoDataRequest; import Types.VideoData; import Types.VideoItem; interface IPlayer { function isSupportedLink(url:String):Bool; - function getVideoData(url:String, callback:(data:VideoData)->Void):Void; + function getVideoData(data:VideoDataRequest, callback:(data:VideoData)->Void):Void; function loadVideo(item:VideoItem):Void; function removeVideo():Void; function isVideoLoaded():Bool; diff --git a/src/client/Main.hx b/src/client/Main.hx index 1cf4b04..c8750ca 100644 --- a/src/client/Main.hx +++ b/src/client/Main.hx @@ -14,6 +14,7 @@ import js.Browser; import js.Browser.document; import js.Browser.window; import Client.ClientData; +import Types.VideoDataRequest; import Types.VideoData; import Types.Config; import Types.WsEvent; @@ -213,16 +214,19 @@ class Main { final links = url.split("|"); handleUrlMasks(links); // if videos added as next, we need to load them in reverse order - if (!atEnd) { - // except first item when list empty - var first:Null<String> = null; - if (player.isListEmpty()) first = links.shift(); - links.reverse(); - if (player.isListEmpty()) links.unshift(first); - } + if (!atEnd) sortItemsForQueueNext(links); addVideoArray(links, atEnd, isTemp); } + public function sortItemsForQueueNext<T>(items:Array<T>):Void { + if (items.length == 0) return; + // except first item when list empty + var first:Null<T> = null; + if (player.isListEmpty()) first = items.shift(); + items.reverse(); + if (player.isListEmpty()) items.unshift(first); + } + function addVideoArray(links:Array<String>, atEnd:Bool, isTemp:Bool):Void { if (links.length == 0) return; final link = links.shift(); @@ -238,7 +242,11 @@ class Main { } if (!url.startsWith("http")) url = '$protocol//$url'; - player.getVideoData(url, (data:VideoData) -> { + final obj:VideoDataRequest = { + url: url, + atEnd: atEnd + }; + player.getVideoData(obj, (data:VideoData) -> { if (data.duration == 0) { serverMessage(4, Lang.get("addVideoError")); return; @@ -271,7 +279,11 @@ class Main { mediaTitle.value = ""; final checkbox:InputElement = cast ge("#customembed").querySelector(".add-temp"); final isTemp = checkbox.checked; - player.getIframeData(iframe, (data:VideoData) -> { + final obj:VideoDataRequest = { + url: iframe, + atEnd: atEnd + }; + player.getIframeData(obj, (data:VideoData) -> { if (data.duration == 0) { serverMessage(4, Lang.get("addVideoError")); return; diff --git a/src/client/Player.hx b/src/client/Player.hx index dd49ab4..7de6d36 100644 --- a/src/client/Player.hx +++ b/src/client/Player.hx @@ -5,6 +5,7 @@ import client.Main.ge; import client.players.Raw; import client.players.Youtube; import client.players.Iframe; +import Types.VideoDataRequest; import Types.VideoData; import Types.VideoItem; using StringTools; @@ -97,14 +98,14 @@ class Player { player = newPlayer; } - public function getVideoData(url:String, callback:(data:VideoData)->Void):Void { - var player = players.find(player -> player.isSupportedLink(url)); + public function getVideoData(data:VideoDataRequest, callback:(data:VideoData)->Void):Void { + var player = players.find(player -> player.isSupportedLink(data.url)); if (player == null) player = rawPlayer; - player.getVideoData(url, callback); + player.getVideoData(data, callback); } - public function getIframeData(iframe:String, callback:(data:VideoData)->Void):Void { - iframePlayer.getVideoData(iframe, callback); + public function getIframeData(data:VideoDataRequest, callback:(data:VideoData)->Void):Void { + iframePlayer.getVideoData(data, callback); } public function setVideo(i:Int):Void { diff --git a/src/client/players/Iframe.hx b/src/client/players/Iframe.hx index 2f875fb..ae37c94 100644 --- a/src/client/players/Iframe.hx +++ b/src/client/players/Iframe.hx @@ -1,10 +1,9 @@ package client.players; -import haxe.Timer; import js.html.Element; -import js.html.VideoElement; import js.Browser.document; import client.Main.ge; +import Types.VideoDataRequest; import Types.VideoData; import Types.VideoItem; @@ -24,9 +23,9 @@ class Iframe implements IPlayer { return true; } - public function getVideoData(data:String, callback:(data:VideoData)->Void):Void { + public function getVideoData(data:VideoDataRequest, callback:(data:VideoData)->Void):Void { final iframe = document.createDivElement(); - iframe.innerHTML = data; + iframe.innerHTML = data.url; if (isValidIframe(iframe)) { callback({duration: 99 * 60 * 60}); } else { diff --git a/src/client/players/Raw.hx b/src/client/players/Raw.hx index 57dd9b3..9a9d52e 100644 --- a/src/client/players/Raw.hx +++ b/src/client/players/Raw.hx @@ -6,6 +6,7 @@ import js.html.Element; import js.html.VideoElement; import js.Browser.document; import client.Main.ge; +import Types.VideoDataRequest; import Types.VideoData; import Types.VideoItem; using StringTools; @@ -30,7 +31,8 @@ class Raw implements IPlayer { return true; } - public function getVideoData(url:String, callback:(data:VideoData)->Void):Void { + public function getVideoData(data:VideoDataRequest, callback:(data:VideoData)->Void):Void { + final url = data.url; final decodedUrl = url.urlDecode(); var title = decodedUrl.substr(decodedUrl.lastIndexOf("/") + 1); final isNameMatched = matchName.match(title); @@ -40,7 +42,7 @@ class Raw implements IPlayer { if (isNameMatched) { isHls = matchName.matched(2).contains("m3u8"); if (isHls && !isHlsLoaded) { - loadHlsPlugin(() -> getVideoData(url, callback)); + loadHlsPlugin(() -> getVideoData(data, callback)); return; } } @@ -63,7 +65,8 @@ class Raw implements IPlayer { } function loadHlsPlugin(callback:()->Void):Void { - JsApi.addScriptToHead("https://cdn.jsdelivr.net/npm/hls.js@latest", () -> { + final url = "https://cdn.jsdelivr.net/npm/hls.js@latest"; + JsApi.addScriptToHead(url, () -> { isHlsLoaded = true; callback(); }); diff --git a/src/client/players/Youtube.hx b/src/client/players/Youtube.hx index f5f12a0..45f74dd 100644 --- a/src/client/players/Youtube.hx +++ b/src/client/players/Youtube.hx @@ -7,6 +7,7 @@ import js.Browser.document; import client.Main.ge; import js.youtube.Youtube as YtInit; import js.youtube.YoutubePlayer; +import Types.VideoDataRequest; import Types.VideoData; import Types.VideoItem; using StringTools; @@ -72,17 +73,18 @@ class Youtube implements IPlayer { return total; } - public function getVideoData(url:String, callback:(data:VideoData)->Void):Void { + public function getVideoData(data:VideoDataRequest, callback:(data:VideoData)->Void):Void { + final url = data.url; if (apiKey == null) apiKey = main.getYoutubeApiKey(); - var id = extractVideoId(url); + final id = extractVideoId(url); if (id == "") { - getPlaylistVideoData(url, callback); + getPlaylistVideoData(data, callback); return; } final dataUrl = '$videosUrl$urlTitleDuration&id=$id&key=$apiKey'; final http = new Http(dataUrl); - http.onData = data -> { - final json = Json.parse(data); + http.onData = text -> { + final json = Json.parse(text); if (json.error != null) { youtubeApiError(json.error); getRemoteDataFallback(url, callback); @@ -103,11 +105,11 @@ class Youtube implements IPlayer { duration: 99 * 60 * 60, title: title, url: '<iframe src="https://www.youtube.com/embed/$id" frameborder="0" - allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" - allowfullscreen></iframe>', + allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" + allowfullscreen></iframe>', isIframe: true }); - return; + continue; } callback({ duration: duration, @@ -120,12 +122,13 @@ class Youtube implements IPlayer { http.request(); } - function getPlaylistVideoData(url:String, callback:(data:VideoData)->Void):Void { + function getPlaylistVideoData(data:VideoDataRequest, callback:(data:VideoData)->Void):Void { + final url = data.url; final id = extractPlaylistId(url); final dataUrl = '$playlistUrl$urlVideoId&maxResults=50&playlistId=$id&key=$apiKey'; final http = new Http(dataUrl); - http.onData = data -> { - final json = Json.parse(data); + http.onData = text -> { + final json = Json.parse(text); if (json.error != null) { youtubeApiError(json.error); callback({duration: 0}); @@ -136,10 +139,15 @@ class Youtube implements IPlayer { callback({duration: 0}); return; } + if (!data.atEnd) main.sortItemsForQueueNext(items); function loadNextItem():Void { final item = items.shift(); final id:String = item.snippet.resourceId.videoId; - getVideoData('youtu.be/$id', data -> { + final obj = { + url: 'https://youtu.be/$id', + atEnd: data.atEnd + }; + getVideoData(obj, data -> { callback(data); if (items.length > 0) loadNextItem(); }); |
