diff options
| -rw-r--r-- | res/client.js | 88 | ||||
| -rw-r--r-- | res/index.html | 14 | ||||
| -rw-r--r-- | res/langs/en.json | 1 | ||||
| -rw-r--r-- | res/langs/ru.json | 1 | ||||
| -rw-r--r-- | src/Types.hx | 3 | ||||
| -rw-r--r-- | src/client/Buttons.hx | 11 | ||||
| -rw-r--r-- | src/client/Main.hx | 40 | ||||
| -rw-r--r-- | src/client/Player.hx | 10 | ||||
| -rw-r--r-- | src/client/players/Iframe.hx | 59 | ||||
| -rw-r--r-- | src/server/Main.hx | 3 |
10 files changed, 197 insertions, 33 deletions
diff --git a/res/client.js b/res/client.js index cc8a891..470c0a8 100644 --- a/res/client.js +++ b/res/client.js @@ -518,11 +518,18 @@ client_Buttons.init = function(main) { } return; }; - window.document.querySelector("#showmediaurl").onclick = function(e12) { - window.document.querySelector("#showmediaurl").classList.toggle("collapsed"); - window.document.querySelector("#showmediaurl").classList.toggle("active"); + var showMediaUrl = window.document.querySelector("#showmediaurl"); + showMediaUrl.onclick = function(e12) { + showMediaUrl.classList.toggle("collapsed"); + showMediaUrl.classList.toggle("active"); return window.document.querySelector("#addfromurl").classList.toggle("collapse"); }; + var showCustomEmbed = window.document.querySelector("#showcustomembed"); + showCustomEmbed.onclick = function(e13) { + showCustomEmbed.classList.toggle("collapsed"); + showCustomEmbed.classList.toggle("active"); + return window.document.querySelector("#customembed").classList.toggle("collapse"); + }; window.onresize = client_Buttons.onVideoResize; client_Buttons.initSplit(); }; @@ -813,7 +820,24 @@ client_Main.prototype = { if(e4.keyCode == 13) { _gthis.addVideoUrl(true); } + return; + }; + window.document.querySelector("#ce_queue_next").onclick = function(e5) { + _gthis.addIframe(false); + return; + }; + window.document.querySelector("#ce_queue_end").onclick = function(e6) { + _gthis.addIframe(true); + return; + }; + window.document.querySelector("#customembed-title").onkeydown = function(e7) { + if(e7.keyCode == 13) { + _gthis.addIframe(true); + e7.preventDefault(); + } + return; }; + window.document.querySelector("#customembed-content").onkeydown = window.document.querySelector("#customembed-title").onkeydown; } ,addVideoUrl: function(atEnd) { var mediaUrl = window.document.querySelector("#mediaurl"); @@ -865,11 +889,24 @@ client_Main.prototype = { if(data.title == null) { data.title = Lang.get("rawVideo"); } - _gthis.send({ type : "AddVideo", addVideo : { item : { url : url, title : data.title, author : _gthis.personal.name, duration : data.duration, isTemp : isTemp}, atEnd : atEnd}}); + _gthis.send({ type : "AddVideo", addVideo : { item : { url : url, title : data.title, author : _gthis.personal.name, duration : data.duration, isTemp : isTemp, isIframe : false}, atEnd : atEnd}}); callback(); return; }); } + ,addIframe: function(atEnd) { + var iframeCode = window.document.querySelector("#customembed-content"); + var iframe = iframeCode.value; + if(iframe.length == 0) { + return; + } + iframeCode.value = ""; + var mediaName = window.document.querySelector("#customembed-title"); + var name = mediaName.value.length == 0 ? "Custom Media" : mediaName.value; + mediaName.value = ""; + var isTemp = window.document.querySelector("#customembed").querySelector(".add-temp").checked; + this.send({ type : "AddVideo", addVideo : { item : { url : iframe, title : name, author : this.personal.name, duration : 356400, isTemp : isTemp, isIframe : true}, atEnd : atEnd}}); + } ,toggleVideoElement: function() { if(this.player.hasVideo()) { this.player.removeVideo(); @@ -898,7 +935,7 @@ client_Main.prototype = { var data = JSON.parse(e.data); var t = data.type; var t1 = t.charAt(0).toLowerCase() + HxOverrides.substr(t,1,null); - haxe_Log.trace("Event: " + data.type,{ fileName : "src/client/Main.hx", lineNumber : 217, className : "client.Main", methodName : "onMessage", customParams : [data[t1]]}); + haxe_Log.trace("Event: " + data.type,{ fileName : "src/client/Main.hx", lineNumber : 253, className : "client.Main", methodName : "onMessage", customParams : [data[t1]]}); switch(data.type) { case "AddVideo": this.player.addVideoItem(data.addVideo.item,data.addVideo.atEnd); @@ -1393,7 +1430,9 @@ client_Player.prototype = { return; } var item = this.items[i]; - if(client_players_Youtube.isYoutube(item.url)) { + if(item.isIframe) { + this.setPlayer(new client_players_Iframe(this.main,this)); + } else if(client_players_Youtube.isYoutube(item.url)) { this.setPlayer(new client_players_Youtube(this.main,this)); } else { this.setPlayer(new client_players_Raw(this.main,this)); @@ -1444,7 +1483,8 @@ client_Player.prototype = { this.main.send({ type : "SetTime", setTime : { time : this.getTime()}}); } ,addVideoItem: function(item,atEnd) { - var itemEl = this.nodeFromString("<li class=\"queue_entry pluid-0\" title=\"" + Lang.get("addedBy") + ": " + item.author + "\">\n\t\t\t\t<a class=\"qe_title\" href=\"" + item.url + "\" target=\"_blank\">" + StringTools.htmlEscape(item.title) + "</a>\n\t\t\t\t<span class=\"qe_time\">" + this.duration(item.duration) + "</span>\n\t\t\t\t<div class=\"qe_clear\"></div>\n\t\t\t\t<div class=\"btn-group\" style=\"display: inline-block;\">\n\t\t\t\t\t<button class=\"btn btn-xs btn-default qbtn-play\">\n\t\t\t\t\t\t<span class=\"glyphicon glyphicon-play\"></span>" + Lang.get("play") + "\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"btn btn-xs btn-default qbtn-next\">\n\t\t\t\t\t\t<span class=\"glyphicon glyphicon-share-alt\"></span>" + Lang.get("setNext") + "\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"btn btn-xs btn-default qbtn-tmp\">\n\t\t\t\t\t\t<span class=\"glyphicon glyphicon-flag\"></span>\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"btn btn-xs btn-default qbtn-delete\">\n\t\t\t\t\t\t<span class=\"glyphicon glyphicon-trash\"></span>" + Lang.get("delete") + "\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</li>"); + var url = StringTools.htmlEscape(item.url,true); + var itemEl = this.nodeFromString("<li class=\"queue_entry pluid-0\" title=\"" + Lang.get("addedBy") + ": " + item.author + "\">\n\t\t\t\t<a class=\"qe_title\" href=\"" + url + "\" target=\"_blank\">" + StringTools.htmlEscape(item.title) + "</a>\n\t\t\t\t<span class=\"qe_time\">" + this.duration(item.duration) + "</span>\n\t\t\t\t<div class=\"qe_clear\"></div>\n\t\t\t\t<div class=\"btn-group\">\n\t\t\t\t\t<button class=\"btn btn-xs btn-default qbtn-play\">\n\t\t\t\t\t\t<span class=\"glyphicon glyphicon-play\"></span>" + Lang.get("play") + "\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"btn btn-xs btn-default qbtn-next\">\n\t\t\t\t\t\t<span class=\"glyphicon glyphicon-share-alt\"></span>" + Lang.get("setNext") + "\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"btn btn-xs btn-default qbtn-tmp\">\n\t\t\t\t\t\t<span class=\"glyphicon glyphicon-flag\"></span>\n\t\t\t\t\t</button>\n\t\t\t\t\t<button class=\"btn btn-xs btn-default qbtn-delete\">\n\t\t\t\t\t\t<span class=\"glyphicon glyphicon-trash\"></span>" + Lang.get("delete") + "\n\t\t\t\t\t</button>\n\t\t\t\t</div>\n\t\t\t</li>"); _$VideoList_VideoList_$Impl_$.addItem(this.items,item,atEnd,this.itemPos); this.setItemElementType(itemEl,item.isTemp); if(atEnd) { @@ -1689,6 +1729,40 @@ client_Utils.copyToClipboard = function(text) { window.document.body.removeChild(textarea); } }; +var client_players_Iframe = function(main,player) { + this.playerEl = window.document.querySelector("#ytapiplayer"); + this.main = main; + this.player = player; +}; +client_players_Iframe.__name__ = true; +client_players_Iframe.prototype = { + loadVideo: function(item) { + this.video = window.document.createElement("div"); + this.video.id = "videoplayer"; + this.video.innerHTML = item.url; + if(this.video.firstChild.nodeName != "IFRAME" && this.video.firstChild.nodeName != "OBJECT") { + this.video = null; + return; + } + this.playerEl.appendChild(this.video); + } + ,removeVideo: function() { + if(this.video == null) { + return; + } + this.playerEl.removeChild(this.video); + this.video = null; + } + ,play: function() { + } + ,pause: function() { + } + ,getTime: function() { + return 0; + } + ,setTime: function(time) { + } +}; var client_players_Raw = function(main,player) { this.playerEl = window.document.querySelector("#ytapiplayer"); this.main = main; diff --git a/res/index.html b/res/index.html index 7fef888..838bce7 100644 --- a/res/index.html +++ b/res/index.html @@ -121,20 +121,6 @@ </div> <div class="col-lg-7 col-md-7" id="rightpane"> <div class="row" id="rightpane-inner"> - <div class="plcontrol-collapse col-lg-12 col-md-12 collapse" id="searchcontrol" aria-expanded="false" style="height: 95px;"> - <div class="vertical-spacer"></div> - <div class="input-group"> - <input class="form-control" id="library_query" type="text" placeholder="${searchQuery}"><span class="input-group-btn"> - <button class="btn btn-default" id="library_search">Library</button></span><span class="input-group-btn"> - <button class="btn btn-default" id="youtube_search">YouTube</button></span> - </div> - <div class="checkbox"> - <label> - <input class="add-temp" type="checkbox" checked="checked">${addAsTemporary} - </label> - </div> - <ul class="videolist col-lg-12 col-md-12" id="library"></ul> - </div> <div class="plcontrol-collapse col-lg-12 col-md-12 collapse" id="addfromurl" aria-expanded="false" style="height: 89px;"> <div class="vertical-spacer"></div> <div class="input-group"><span class="input-group-btn"> diff --git a/res/langs/en.json b/res/langs/en.json index e8845ec..ef70b8c 100644 --- a/res/langs/en.json +++ b/res/langs/en.json @@ -50,7 +50,6 @@ "fullscreenPlayer": "Fullscreen player", "retrievePlaylistLinks": "Retrieve playlist links", "voteForSkip": "Vote for skip", - "searchQuery": "Search query", "addAsTemporary": "Add as temporary", "mediaUrl": "Media URL", "optionalTitle": "Title (optional)", diff --git a/res/langs/ru.json b/res/langs/ru.json index c768be4..112e931 100644 --- a/res/langs/ru.json +++ b/res/langs/ru.json @@ -50,7 +50,6 @@ "fullscreenPlayer": "Полноэкранный режим видео", "retrievePlaylistLinks": "Получить ссылки на видео из плейлиста", "voteForSkip": "Голосовать за пропуск", - "searchQuery": "Что ищем?", "addAsTemporary": "Добавить как временный", "mediaUrl": "Ссылка на видео", "optionalTitle": "Заголовок (необязательно)", diff --git a/src/Types.hx b/src/Types.hx index 50e38c3..5dbc07a 100644 --- a/src/Types.hx +++ b/src/Types.hx @@ -52,7 +52,8 @@ typedef VideoItem = { title:String, author:String, duration:Float, - isTemp:Bool + isTemp:Bool, + isIframe:Bool } typedef WsEvent = { diff --git a/src/client/Buttons.hx b/src/client/Buttons.hx index 31f1e86..dec8f04 100644 --- a/src/client/Buttons.hx +++ b/src/client/Buttons.hx @@ -133,11 +133,18 @@ class Buttons { final showMediaUrl = ge("#showmediaurl"); showMediaUrl.onclick = e -> { - ge("#showmediaurl").classList.toggle("collapsed"); - ge("#showmediaurl").classList.toggle("active"); + showMediaUrl.classList.toggle("collapsed"); + showMediaUrl.classList.toggle("active"); ge("#addfromurl").classList.toggle("collapse"); } + final showCustomEmbed = ge("#showcustomembed"); + showCustomEmbed.onclick = e -> { + showCustomEmbed.classList.toggle("collapsed"); + showCustomEmbed.classList.toggle("active"); + ge("#customembed").classList.toggle("collapse"); + } + window.onresize = onVideoResize; initSplit(); } diff --git a/src/client/Main.hx b/src/client/Main.hx index 9d9b90d..f32a80c 100644 --- a/src/client/Main.hx +++ b/src/client/Main.hx @@ -113,9 +113,20 @@ class Main { ge("#queue_next").onclick = e -> addVideoUrl(false); ge("#queue_end").onclick = e -> addVideoUrl(true); - ge("#mediaurl").onkeydown = function(e:KeyboardEvent) { + ge("#mediaurl").onkeydown = (e:KeyboardEvent) -> { if (e.keyCode == 13) addVideoUrl(true); } + + ge("#ce_queue_next").onclick = e -> addIframe(false); + ge("#ce_queue_end").onclick = e -> addIframe(true); + ge("#customembed-title").onkeydown = (e:KeyboardEvent) -> { + if (e.keyCode == 13) { + addIframe(true); + e.preventDefault(); + } + } + ge("#customembed-content").onkeydown = + ge("#customembed-title").onkeydown; } public inline function isUser():Bool { @@ -178,7 +189,8 @@ class Main { title: data.title, author: personal.name, duration: data.duration, - isTemp: isTemp + isTemp: isTemp, + isIframe: false }, atEnd: atEnd }}); @@ -186,6 +198,30 @@ class Main { }); } + function addIframe(atEnd:Bool):Void { + final iframeCode:InputElement = cast ge("#customembed-content"); + final iframe = iframeCode.value; + if (iframe.length == 0) return; + iframeCode.value = ""; + final mediaName:InputElement = cast ge("#customembed-title"); + final name = mediaName.value.length == 0 ? "Custom Media" : mediaName.value; + mediaName.value = ""; + final checkbox:InputElement = cast ge("#customembed").querySelector(".add-temp"); + final isTemp = checkbox.checked; + send({ + type: AddVideo, addVideo: { + item: { + url: iframe, + title: name, + author: personal.name, + duration: 99 * 60 * 60, + isTemp: isTemp, + isIframe: true + }, + atEnd: atEnd + }}); + } + public function toggleVideoElement():Bool { if (player.hasVideo()) player.removeVideo(); else if (!player.isListEmpty()) { diff --git a/src/client/Player.hx b/src/client/Player.hx index 443c14f..7088580 100644 --- a/src/client/Player.hx +++ b/src/client/Player.hx @@ -5,6 +5,7 @@ import js.Browser.document; import client.Main.ge; import client.players.Raw; import client.players.Youtube; +import client.players.Iframe; import Types.VideoData; import Types.VideoItem; using StringTools; @@ -93,7 +94,9 @@ class Player { public function setVideo(i:Int):Void { if (!main.isSyncActive) return; final item = items[i]; - if (Youtube.isYoutube(item.url)) { + if (item.isIframe) { + setPlayer(new Iframe(main, this)); + } else if (Youtube.isYoutube(item.url)) { setPlayer(new Youtube(main, this)); } else { setPlayer(new Raw(main, this)); @@ -156,12 +159,13 @@ class Player { } public function addVideoItem(item:VideoItem, atEnd:Bool):Void { + final url = item.url.htmlEscape(true); final itemEl = nodeFromString( '<li class="queue_entry pluid-0" title="${Lang.get("addedBy")}: ${item.author}"> - <a class="qe_title" href="${item.url}" target="_blank">${item.title.htmlEscape()}</a> + <a class="qe_title" href="$url" target="_blank">${item.title.htmlEscape()}</a> <span class="qe_time">${duration(item.duration)}</span> <div class="qe_clear"></div> - <div class="btn-group" style="display: inline-block;"> + <div class="btn-group"> <button class="btn btn-xs btn-default qbtn-play"> <span class="glyphicon glyphicon-play"></span>${Lang.get("play")} </button> diff --git a/src/client/players/Iframe.hx b/src/client/players/Iframe.hx new file mode 100644 index 0000000..37d2fe6 --- /dev/null +++ b/src/client/players/Iframe.hx @@ -0,0 +1,59 @@ +package client.players; + +import haxe.Timer; +import js.html.Element; +import js.html.VideoElement; +import js.Browser.document; +import client.Main.ge; +import Types.VideoData; +import Types.VideoItem; + +class Iframe implements IPlayer { + + final main:Main; + final player:Player; + final playerEl:Element = ge("#ytapiplayer"); + var video:Element; + + public function new(main:Main, player:Player) { + this.main = main; + this.player = player; + } + + public function getVideoData(url:String, callback:(data:VideoData)->Void):Void { + callback({ + duration: 99 * 60 * 60, + title: "Custom Media" + }); + } + + public function loadVideo(item:VideoItem):Void { + video = document.createDivElement(); + video.id = "videoplayer"; + video.innerHTML = item.url; + if (video.firstChild.nodeName != "IFRAME" + && video.firstChild.nodeName != "OBJECT") { + // TODO move to getVideoData too + video = null; + return; + } + playerEl.appendChild(video); + } + + public function removeVideo():Void { + if (video == null) return; + playerEl.removeChild(video); + video = null; + } + + public function play():Void {} + + public function pause():Void {} + + public function getTime():Float { + return 0; + } + + public function setTime(time:Float):Void {} + +} diff --git a/src/server/Main.hx b/src/server/Main.hx index c613b5b..6a2ad82 100644 --- a/src/server/Main.hx +++ b/src/server/Main.hx @@ -371,8 +371,7 @@ class Main { if (videoTimer.getTime() > videoList[itemPos].duration) { videoTimer.stop(); onMessage(client, { - type: SkipVideo, - skipVideo: { + type: SkipVideo, skipVideo: { url: videoList[itemPos].url } }); |
