diff options
| author | RblSb <msrblsb@gmail.com> | 2025-01-22 15:13:11 +0300 |
|---|---|---|
| committer | RblSb <msrblsb@gmail.com> | 2025-01-22 15:13:11 +0300 |
| commit | a843ae530b07b92fc7341754b4722cdcb8dfb831 (patch) | |
| tree | c5217245ea33b7342c248844f82539ccc4e41ac8 | |
| parent | 8f54fabd74b6964e3610d3fbbbfd26f29af6f482 (diff) | |
Redesign portrait view with player at top
Also improve autoscroll with column-reverse, so viewport resize / orientation change should not scroll chat to random places
| -rw-r--r-- | res/client.js | 249 | ||||
| -rw-r--r-- | res/css/des.css | 188 | ||||
| -rw-r--r-- | res/index.html | 14 | ||||
| -rw-r--r-- | src/client/Buttons.hx | 64 | ||||
| -rw-r--r-- | src/client/Main.hx | 88 | ||||
| -rw-r--r-- | src/client/Player.hx | 17 | ||||
| -rw-r--r-- | src/client/Utils.hx | 22 | ||||
| -rw-r--r-- | src/client/players/Raw.hx | 2 | ||||
| -rw-r--r-- | src/client/players/RawSubs.hx | 2 | ||||
| -rw-r--r-- | src/client/players/Youtube.hx | 2 |
10 files changed, 393 insertions, 255 deletions
diff --git a/res/client.js b/res/client.js index e641be7..c7651cf 100644 --- a/res/client.js +++ b/res/client.js @@ -558,7 +558,7 @@ client_Buttons.init = function(main) { } client_Buttons.initSplit(); client_Buttons.setSplitSize(client_Buttons.settings.chatSize); - client_Buttons.initChatInput(main); + client_Buttons.initChatInputs(main); var _g = 0; var _g1 = client_Buttons.settings.checkboxes; while(_g < _g1.length) { @@ -596,7 +596,7 @@ client_Buttons.init = function(main) { } var isActive = smilesBtn.classList.toggle("active"); if(isActive) { - wrap.style.display = "block"; + wrap.style.display = ""; var tmp = client_Buttons.outerHeight(list); wrap.style.height = tmp + "px"; } else { @@ -617,26 +617,15 @@ client_Buttons.init = function(main) { child.removeAttribute("data-src"); } }; - var scrollToChatEndBtn = window.document.querySelector("#scroll-to-chat-end"); - var scrollToChatEndBtnAnim = function() { - if(scrollToChatEndBtn.style.opacity == "0") { - return; - } - scrollToChatEndBtn.style.opacity = "0"; - scrollToChatEndBtn.addEventListener("transitionend",function(e) { - return scrollToChatEndBtn.style.display = "none"; - },{ once : true}); - }; - scrollToChatEndBtn.onclick = function(e) { + window.document.querySelector("#scroll-to-chat-end").onclick = function(e) { main.scrollChatToEnd(); - scrollToChatEndBtnAnim(); + main.hideScrollToChatEndBtn(); }; - var msgBuf = window.document.querySelector("#messagebuffer"); - msgBuf.onscroll = function(e) { - if(msgBuf.offsetHeight + msgBuf.scrollTop < msgBuf.scrollHeight - 1) { + window.document.querySelector("#messagebuffer").onscroll = function(e) { + if(!main.isInChatEnd(1)) { return; } - scrollToChatEndBtnAnim(); + main.hideScrollToChatEndBtn(); }; window.document.querySelector("#clearchatbtn").onclick = function(e) { if((main.personal.group & 8) != 0) { @@ -669,7 +658,7 @@ client_Buttons.init = function(main) { var style = window.document.querySelector("#userlist").style; if(isHidden) { icon.setAttribute("name","chevron-down"); - style.display = "block"; + style.display = ""; wrap.style.height = "15vh"; wrap.style.marginBottom = "1rem"; } else { @@ -712,6 +701,7 @@ client_Buttons.init = function(main) { }; window.document.querySelector("#fullscreenbtn").onclick = function(e) { if((client_Utils.isTouch() || main.isVerbose()) && !client_Utils.hasFullscreen()) { + window.scrollTo(0,0); return client_Utils.requestFullscreen(window.document.documentElement); } else { return client_Utils.requestFullscreen(window.document.querySelector("#ytapiplayer")); @@ -807,12 +797,12 @@ client_Buttons.init = function(main) { },isActive ? 0 : 200); }; window.document.querySelector("#exitBtn").onclick = function(e) { + showOptions.onclick(); if((main.personal.group & 2) != 0) { main.send({ type : "Logout"}); } else { window.document.querySelector("#guestname").focus(); } - return client_Buttons.toggleGroup(showOptions); }; window.document.querySelector("#swapLayoutBtn").onclick = function(e) { client_Buttons.swapPlayerAndChat(); @@ -991,7 +981,7 @@ client_Buttons.updateHotkeysBtn = function() { var state = client_Buttons.settings.hotkeysEnabled ? Lang.get("on") : Lang.get("off"); window.document.querySelector("#hotkeysBtn").innerText = "" + text + ": " + state; }; -client_Buttons.initChatInput = function(main) { +client_Buttons.initChatInputs = function(main) { var guestName = window.document.querySelector("#guestname"); guestName.onkeydown = function(e) { if(e.keyCode == 13) { @@ -1011,42 +1001,26 @@ client_Buttons.initChatInput = function(main) { } } }; - if(client_Utils.isIOS()) { - window.document.ontouchmove = function(e) { - return e.preventDefault(); - }; - window.document.body.style.height = "-webkit-fill-available"; - window.document.querySelector("#chat").style.height = "-webkit-fill-available"; - } var chatline = window.document.querySelector("#chatline"); chatline.onfocus = function(e) { if(client_Utils.isIOS()) { - var startY = window.scrollY; + var startY = 0; haxe_Timer.delay(function() { window.scrollBy(0,-(window.scrollY - startY)); window.document.querySelector("#video").scrollTop = 0; main.scrollChatToEnd(); - if(window.visualViewport == null) { - var tmp = "" + Std.string(window.innerHeight); - window.document.querySelector("#chat").style.height = tmp + "px"; - } },100); } else if(client_Utils.isTouch()) { main.scrollChatToEnd(); } }; - if(client_Utils.isIOS() && window.visualViewport != null) { - var viewport = window.visualViewport; + var viewport = window.visualViewport; + if(viewport != null) { viewport.addEventListener("resize",function(e) { - var tmp = "" + Std.string(window.innerHeight); - return window.document.querySelector("#chat").style.height = tmp + "px"; + client_Buttons.onViewportResize(); }); + client_Buttons.onViewportResize(); } - chatline.onblur = function(e) { - if(client_Utils.isIOS() && window.visualViewport == null) { - window.document.querySelector("#chat").style.height = "-webkit-fill-available"; - } - }; new client_InputWithHistory(chatline,null,50,function(value) { if(main.handleCommands(value)) { return true; @@ -1077,6 +1051,19 @@ client_Buttons.initChatInput = function(main) { })(checkbox)); } }; +client_Buttons.onViewportResize = function() { + var tmp = window.visualViewport; + if(tmp == null) { + return; + } + var isPortrait = window.innerHeight > window.innerWidth; + var playerH = window.document.querySelector("#ytapiplayer").offsetHeight; + var h = tmp.height - playerH; + if(!isPortrait) { + h = tmp.height; + } + window.document.querySelector("#chat").style.height = "" + h + "px"; +}; client_Buttons.initPageFullscreen = function() { window.document.onfullscreenchange = function(e) { var el = window.document.documentElement; @@ -1291,6 +1278,7 @@ client_JsApi.fireVideoRemoveEvents = function(item) { var client_Main = function() { this.matchSimpleDate = new EReg("^-?([0-9]+d)?([0-9]+h)?([0-9]+m)?([0-9]+s?)?$",""); this.urlMask = new EReg("\\${([0-9]+)-([0-9]+)}","g"); + this.msgBuf = window.document.querySelector("#messagebuffer"); this.gotFirstPageInteraction = false; this.disabledReconnection = false; this.gotInitialConnection = false; @@ -1334,28 +1322,7 @@ var client_Main = function() { }; client_Main.__name__ = true; client_Main.main = function() { - new client_Main(); -}; -client_Main.serverMessage = function(text,isText,withTimestamp) { - if(withTimestamp == null) { - withTimestamp = true; - } - if(isText == null) { - isText = true; - } - var div = window.document.createElement("div"); - var time = HxOverrides.dateStr(new Date()).split(" ")[1]; - div.className = "server-whisper"; - div.innerHTML = "<div class=\"head\">\n\t\t\t<div class=\"server-whisper\"></div>\n\t\t\t<span class=\"timestamp\">" + (withTimestamp ? time : "") + "</span>\n\t\t</div>"; - var textDiv = div.querySelector(".server-whisper"); - if(isText) { - textDiv.textContent = text; - } else { - textDiv.innerHTML = text; - } - var msgBuf = window.document.querySelector("#messagebuffer"); - msgBuf.appendChild(div); - msgBuf.scrollTop = msgBuf.scrollHeight; + client_Main.instance = new client_Main(); }; client_Main.prototype = { onFirstInteraction: function() { @@ -1589,7 +1556,7 @@ client_Main.prototype = { } this.player.getVideoData({ url : url, atEnd : atEnd},function(data) { if(data.duration == 0) { - client_Main.serverMessage(Lang.get("addVideoError")); + _gthis.serverMessage(Lang.get("addVideoError")); return; } data.title = data.title != null ? data.title : Lang.get("rawVideo"); @@ -1614,7 +1581,7 @@ client_Main.prototype = { var isTemp = window.document.querySelector("#customembed .add-temp").checked; this.player.getIframeData({ url : iframe, atEnd : atEnd},function(data) { if(data.duration == 0) { - client_Main.serverMessage(Lang.get("addVideoError")); + _gthis.serverMessage(Lang.get("addVideoError")); return; } if(title.length > 0) { @@ -1663,7 +1630,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 : 443, 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 : 445, 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) { @@ -1800,7 +1767,7 @@ client_Main.prototype = { break; case "ServerMessage": var id = data.serverMessage.textId; - client_Main.serverMessage(id == "usernameError" ? StringTools.replace(Lang.get(id),"$MAX","" + this.config.maxLoginLength) : Lang.get(id)); + this.serverMessage(id == "usernameError" ? StringTools.replace(Lang.get(id),"$MAX","" + this.config.maxLoginLength) : Lang.get(id)); break; case "SetLeader": ClientTools.setLeader(this.clients,data.setLeader.clientName); @@ -1921,7 +1888,7 @@ client_Main.prototype = { } var hideThisMessage = "<button id=\"hideHintList\">" + Lang.get("hideThisMessage") + "</button>"; text += "</br>" + StringTools.replace(Lang.get("hintListHide"),"$hideThisMessage",hideThisMessage); - client_Main.serverMessage(text,false,false); + this.serverMessage(text,false,false); window.document.querySelector("#addVideosHintButton").onclick = function(e) { var addBtn = window.document.querySelector("#showmediaurl"); addBtn.scrollIntoView(); @@ -1983,7 +1950,7 @@ client_Main.prototype = { } var adminMenu = window.document.querySelector("#adminMenu"); if((this.personal.group & 8) != 0) { - adminMenu.style.display = "block"; + adminMenu.style.display = ""; } else { adminMenu.style.display = "none"; } @@ -2075,7 +2042,7 @@ client_Main.prototype = { this.hideGuestLoginPanel(); } ,showGuestLoginPanel: function() { - window.document.querySelector("#guestlogin").style.display = "flex"; + window.document.querySelector("#guestlogin").style.display = ""; window.document.querySelector("#guestpassword").style.display = "none"; window.document.querySelector("#chatbox").style.display = "none"; window.document.querySelector("#exitBtn").textContent = Lang.get("login"); @@ -2083,13 +2050,13 @@ client_Main.prototype = { ,hideGuestLoginPanel: function() { window.document.querySelector("#guestlogin").style.display = "none"; window.document.querySelector("#guestpassword").style.display = "none"; - window.document.querySelector("#chatbox").style.display = "flex"; + window.document.querySelector("#chatbox").style.display = ""; window.document.querySelector("#exitBtn").textContent = Lang.get("exit"); } ,showGuestPasswordPanel: function() { window.document.querySelector("#guestlogin").style.display = "none"; window.document.querySelector("#chatbox").style.display = "none"; - window.document.querySelector("#guestpassword").style.display = "flex"; + window.document.querySelector("#guestpassword").style.display = ""; window.document.querySelector("#guestpass").type = "password"; window.document.querySelector("#guestpass_icon").setAttribute("name","eye"); } @@ -2106,35 +2073,53 @@ client_Main.prototype = { this.ws.send(JSON.stringify(data)); } ,chatMessageConnected: function() { - var msgBuf = window.document.querySelector("#messagebuffer"); if(this.isLastMessageConnectionStatus()) { - msgBuf.removeChild(msgBuf.lastChild); + this.msgBuf.removeChild(this.msgBuf.lastChild); } var div = window.document.createElement("div"); div.className = "server-msg-reconnect"; div.textContent = Lang.get("msgConnected"); - msgBuf.appendChild(div); + this.addMessageDiv(div); this.scrollChatToEnd(); } ,chatMessageDisconnected: function() { - var msgBuf = window.document.querySelector("#messagebuffer"); if(this.isLastMessageConnectionStatus()) { - msgBuf.removeChild(msgBuf.lastChild); + this.msgBuf.removeChild(this.msgBuf.lastChild); } var div = window.document.createElement("div"); div.className = "server-msg-disconnect"; div.textContent = Lang.get("msgDisconnected"); - msgBuf.appendChild(div); + this.addMessageDiv(div); this.scrollChatToEnd(); } ,isLastMessageConnectionStatus: function() { - var tmp = window.document.querySelector("#messagebuffer").lastElementChild; + var tmp = this.msgBuf.lastElementChild; if(tmp != null) { return StringTools.startsWith(tmp.className,"server-msg"); } else { return null; } } + ,serverMessage: function(text,isText,withTimestamp) { + if(withTimestamp == null) { + withTimestamp = true; + } + if(isText == null) { + isText = true; + } + var div = window.document.createElement("div"); + var time = HxOverrides.dateStr(new Date()).split(" ")[1]; + div.className = "server-whisper"; + div.innerHTML = "<div class=\"head\">\n\t\t\t<div class=\"server-whisper\"></div>\n\t\t\t<span class=\"timestamp\">" + (withTimestamp ? time : "") + "</span>\n\t\t</div>"; + var textDiv = div.querySelector(".server-whisper"); + if(isText) { + textDiv.textContent = text; + } else { + textDiv.innerHTML = text; + } + this.addMessageDiv(div); + this.scrollChatToEnd(); + } ,updateUserList: function() { window.document.querySelector("#usercount").textContent = this.clients.length + " " + Lang.get("online"); window.document.title = this.getPageTitle(); @@ -2161,14 +2146,13 @@ client_Main.prototype = { return "" + this.pageTitle + " (" + this.clients.length + ")"; } ,clearChat: function() { - window.document.querySelector("#messagebuffer").textContent = ""; + this.msgBuf.textContent = ""; } ,getLocalDateFromUtc: function(utcDate) { var date = HxOverrides.strDate(utcDate); return HxOverrides.dateStr(new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000)); } ,addMessage: function(name,text,date) { - var msgBuf = window.document.querySelector("#messagebuffer"); var userDiv = window.document.createElement("div"); userDiv.className = "chat-msg-" + name; var headDiv = window.document.createElement("div"); @@ -2197,8 +2181,8 @@ client_Main.prototype = { text = text.replace(filter.regex.r,filter.replace); } textDiv.innerHTML = text; - var isInChatEnd = msgBuf.scrollTop + msgBuf.clientHeight >= msgBuf.scrollHeight - 50; - if(isInChatEnd) { + var inChatEnd = this.isInChatEnd(); + if(inChatEnd) { var _g = 0; var _g1 = textDiv.getElementsByTagName("img"); while(_g < _g1.length) _g1[_g++].onload = $bind(this,this.onChatImageLoaded); @@ -2210,11 +2194,11 @@ client_Main.prototype = { headDiv.appendChild(nameDiv); headDiv.appendChild(tstamp); userDiv.appendChild(textDiv); - msgBuf.appendChild(userDiv); - if(isInChatEnd) { - while(msgBuf.children.length > 200) msgBuf.removeChild(msgBuf.firstChild); + this.addMessageDiv(userDiv); + if(inChatEnd) { + while(this.msgBuf.children.length > 200) this.msgBuf.removeChild(this.msgBuf.firstChild); } - if(isInChatEnd || name == this.personal.name) { + if(inChatEnd || name == this.personal.name) { this.scrollChatToEnd(); } else { this.showScrollToChatEndBtn(); @@ -2223,13 +2207,30 @@ client_Main.prototype = { this.blinkTabWithTitle("*" + Lang.get("chat") + "*"); } } + ,addMessageDiv: function(userDiv) { + if(this.isMessageBufferReversed()) { + this.msgBuf.prepend(userDiv); + } else { + this.msgBuf.appendChild(userDiv); + } + } ,showScrollToChatEndBtn: function() { var btn = window.document.querySelector("#scroll-to-chat-end"); - btn.style.display = "block"; + btn.style.display = ""; haxe_Timer.delay(function() { btn.style.opacity = "1"; },0); } + ,hideScrollToChatEndBtn: function() { + var btn = window.document.querySelector("#scroll-to-chat-end"); + if(btn.style.opacity == "0") { + return; + } + btn.style.opacity = "0"; + btn.addEventListener("transitionend",function(e) { + return btn.style.display = "none"; + },{ once : true}); + } ,onChatImageLoaded: function(e) { this.scrollChatToEnd(); e.target.onload = null; @@ -2247,9 +2248,32 @@ client_Main.prototype = { this.scrollChatToEnd(); el.onloadedmetadata = null; } + ,isMessageBufferReversed: function() { + return this.msgBuf.style.flexDirection == "column-reverse"; + } + ,isInChatEnd: function(ignoreOffset) { + if(ignoreOffset == null) { + ignoreOffset = 50; + } + var isReverse = this.isMessageBufferReversed(); + var scrollTop = this.msgBuf.scrollTop; + if(isReverse) { + scrollTop = -scrollTop; + } + if(isReverse) { + return scrollTop <= ignoreOffset; + } + return scrollTop + this.msgBuf.clientHeight >= this.msgBuf.scrollHeight - ignoreOffset; + } ,scrollChatToEnd: function() { - var msgBuf = window.document.querySelector("#messagebuffer"); - msgBuf.scrollTop = msgBuf.scrollHeight; + if(this.isMessageBufferReversed()) { + if(client_Utils.isMacSafari) { + this.msgBuf.scrollTop = -1; + } + this.msgBuf.scrollTop = 0; + } else { + this.msgBuf.scrollTop = this.msgBuf.scrollHeight; + } } ,handleCommands: function(command) { if(!StringTools.startsWith(command,"/")) { @@ -2445,6 +2469,7 @@ var client_Player = function(main) { this.playerEl = window.document.querySelector("#ytapiplayer"); this.videoItemsEl = window.document.querySelector("#queue"); this.videoList = new VideoList(); + var _gthis = this; this.main = main; this.youtube = new client_players_Youtube(main,this); this.streamable = new client_players_Streamable(main,this); @@ -2452,6 +2477,22 @@ var client_Player = function(main) { this.iframePlayer = new client_players_Iframe(main,this); this.rawPlayer = new client_players_Raw(main,this); this.initItemButtons(); + var resizeObserver = client_Utils.createResizeObserver(function(entries) { + if(_gthis.isLoaded) { + return; + } + client_Buttons.onViewportResize(); + }); + if(resizeObserver != null) { + resizeObserver.observe(this.playerEl); + } else { + new haxe_Timer(50).run = function() { + if(_gthis.isLoaded) { + return; + } + client_Buttons.onViewportResize(); + }; + } }; client_Player.__name__ = true; client_Player.prototype = { @@ -2582,7 +2623,7 @@ client_Player.prototype = { return _gthis.isAudioTrackLoaded = true; }; this.audioTrack.onerror = function(e) { - haxe_Log.trace(e,{ fileName : "src/client/Player.hx", lineNumber : 191, className : "client.Player", methodName : "setExternalAudioTrack"}); + haxe_Log.trace(e,{ fileName : "src/client/Player.hx", lineNumber : 205, className : "client.Player", methodName : "setExternalAudioTrack"}); _gthis.audioTrack.oncanplay = null; _gthis.audioTrack.onerror = null; _gthis.isAudioTrackLoaded = false; @@ -2651,6 +2692,7 @@ client_Player.prototype = { this.main.send({ type : "VideoLoaded"}); } this.isLoaded = true; + client_Buttons.onViewportResize(); } ,onPlay: function() { var tmp = this.audioTrack; @@ -3035,7 +3077,7 @@ client_Player.prototype = { } }; http.onError = function(msg) { - haxe_Log.trace(msg,{ fileName : "src/client/Player.hx", lineNumber : 577, className : "client.Player", methodName : "skipAd"}); + haxe_Log.trace(msg,{ fileName : "src/client/Player.hx", lineNumber : 592, className : "client.Player", methodName : "skipAd"}); }; http.request(); } @@ -3156,6 +3198,15 @@ client_Utils.isIOS = function() { return true; } }; +client_Utils._isMacSafari = function() { + var isMac = $global.navigator.userAgent.indexOf("Macintosh") != -1; + var isSafari = $global.navigator.userAgent.indexOf("Safari") != -1 && $global.navigator.userAgent.indexOf("Chrom") == -1 && $global.navigator.userAgent.indexOf("Edg") == -1; + if(isMac) { + return isSafari; + } else { + return false; + } +}; client_Utils.isAndroid = function() { return $global.navigator.userAgent.toLowerCase().indexOf("android") > -1; }; @@ -3202,8 +3253,6 @@ client_Utils.requestFullscreen = function(el) { var el2 = el; if(el.requestFullscreen != null) { el.requestFullscreen(); - } else if(el2.mozRequestFullScreen != null) { - el2.mozRequestFullScreen(); } else if(el2.webkitRequestFullscreen != null) { el2.webkitRequestFullscreen(HTMLElement.ALLOW_KEYBOARD_INPUT); } else { @@ -3271,6 +3320,9 @@ client_Utils.saveFile = function(name,mime,data) { window.document.body.removeChild(a); URL.revokeObjectURL(url); }; +client_Utils.createResizeObserver = function(callback) { + return null; +}; var client_players_Iframe = function(main,player) { this.playerEl = window.document.querySelector("#ytapiplayer"); this.main = main; @@ -3500,7 +3552,7 @@ client_players_Raw.prototype = { try { subsUri = new URL(subsUrl); } catch( _g ) { - client_Main.serverMessage("Failed to add subs: bad url (" + subsUrl + ")"); + client_Main.instance.serverMessage("Failed to add subs: bad url (" + subsUrl + ")"); return; } if(subsUri.hostname == this.main.host || subsUri.hostname == this.main.globalIp) { @@ -3782,7 +3834,7 @@ client_players_RawSubs.convertAssTime = function(time) { }; client_players_RawSubs.isProxyError = function(text) { if(StringTools.startsWith(text,"Proxy error:")) { - client_Main.serverMessage("Failed to add subs: proxy error"); + client_Main.instance.serverMessage("Failed to add subs: proxy error"); haxe_Log.trace("Failed to add subs: " + text,{ fileName : "src/client/players/RawSubs.hx", lineNumber : 219, className : "client.players.RawSubs", methodName : "isProxyError"}); return true; } @@ -4161,7 +4213,7 @@ client_players_Youtube.prototype = { loadJson(dataUrl); } ,youtubeApiError: function(error) { - client_Main.serverMessage("Error " + error.code + ": " + error.message,false); + client_Main.instance.serverMessage("Error " + error.code + ": " + error.message,false); } ,getRemoteDataFallback: function(url,callback) { var _gthis = this; @@ -5108,6 +5160,7 @@ client_JsApi.videoChange = []; client_JsApi.videoRemove = []; client_JsApi.onceListeners = []; client_Settings.isSupported = false; +client_Utils.isMacSafari = client_Utils._isMacSafari(); client_players_RawSubs.assTimeStamp = new EReg("([0-9]+):([0-9][0-9]):([0-9][0-9]).([0-9][0-9])",""); haxe_crypto_Base64.CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; haxe_crypto_Base64.BYTES = haxe_io_Bytes.ofString(haxe_crypto_Base64.CHARS); diff --git a/res/css/des.css b/res/css/des.css index a6fd43d..7fb2d26 100644 --- a/res/css/des.css +++ b/res/css/des.css @@ -31,14 +31,37 @@ html { body { font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; - font-size: .875rem; + font-size: 1rem; line-height: 1.4; color: var(--foreground); - background-color: var(--background-chat); + background: var(--background-video); margin: 0; padding: 0; - display: flex; - flex-direction: column; + display: grid; + grid-template-areas: "video gutter chat"; + overflow-y: hidden; + width: 100%; + height: 100vh; +} + +body.swap { + grid-template-areas: "chat gutter video"; +} + + +@media only screen and (orientation: portrait) { + body { + font-size: .875rem; + grid-template-areas: none; + overflow-y: auto; + height: auto; + display: flex; + flex-direction: column; + } + + body.swap { + grid-template-areas: none; + } } h1, @@ -305,7 +328,18 @@ button.danger-bg:focus { display: flex; justify-content: space-between; align-items: center; - flex-wrap: wrap; + flex-wrap: nowrap; +} + +@media only screen and (orientation: portrait) { + .info { + flex-wrap: wrap; + } +} + +#currenttitle { + text-overflow: ellipsis; + overflow: hidden; } .info header { @@ -358,6 +392,44 @@ header h4 { background: var(--background-video); } +@media only screen and (orientation: landscape) { + #video { + grid-area: video; + width: 100%; + height: 100%; + /* Breaks subs after viewport overflow on FF+Linux (SyncTube#28) */ + /* overflow: auto; */ + overflow: scroll; + background: var(--background-video); + } +} + +@media only screen and (orientation: portrait) { + #video { + display: contents; + } + + #player { + display: contents; + } + + #ytapiplayer { + background: var(--background-video); + } + + .info { + order: 2; + } + + #playlist { + order: 3; + } + + #footer { + order: 4; + } +} + /* Embed responsive */ .embed-responsive:empty { @@ -391,11 +463,11 @@ iframe#videoplayer { } .embed-responsive { - max-height: 50vh; + max-height: 30vh; } #videoplayer { - max-height: 50vh; + max-height: 30vh; } } @@ -455,7 +527,7 @@ iframe#videoplayer { #customembed>*>input, #customembed>*>textarea { - display: block; + display: flex; width: 100%; } @@ -509,11 +581,26 @@ footer#footer { display: none; } +@media only screen and (orientation: landscape) { + .gutter { + grid-area: gutter; + display: flex; + cursor: col-resize; + background-color: var(--border); + transition: background-color ease-in-out .15s; + } + + .gutter:hover { + background-color: var(--accent); + } +} + /* * Start chat */ #chat { + background: var(--background-chat); position: relative; display: flex; order: 0; @@ -523,6 +610,13 @@ footer#footer { height: 40vh; } +@media only screen and (orientation: landscape) { + #chat { + grid-area: chat; + height: 100vh; + } +} + #chat header { display: flex; align-items: center; @@ -550,6 +644,8 @@ footer#footer { } #userlist { + display: flex; + flex-direction: column; padding: 1rem; } @@ -611,6 +707,8 @@ footer#footer { } #optionsList div { + display: flex; + flex-direction: column; margin-bottom: .5rem; } @@ -636,6 +734,8 @@ footer#footer { /* Message buffer */ #messagebuffer { + display: flex; + flex-direction: column; flex-grow: 2; flex-shrink: 8; overflow: auto; @@ -655,7 +755,7 @@ footer#footer { } .username { - display: block; + display: flex; } .timestamp { @@ -715,7 +815,7 @@ footer#footer { /* Emotes */ #smiles-wrap { - display: none; + display: flex; height: 0; width: 100%; background: rgba(0, 0, 0, 0.7); @@ -726,6 +826,7 @@ footer#footer { #smiles-list { display: grid; + width: 100%; height: 12rem; padding: 1rem; grid-template-columns: repeat(auto-fit, minmax(4rem, 1fr)); @@ -763,7 +864,7 @@ footer#footer { #guestlogin label, #guestpassword label { - display: block; + display: flex; margin-bottom: 1em; } @@ -814,71 +915,6 @@ html { background: rgba(255, 255, 255, 0.2); } -/* - * Media queries - */ - -@media only screen and (orientation: landscape) { - body { - display: grid; - grid-template-areas: "video gutter chat"; - overflow-y: hidden; - font-size: 1rem; - width: 100%; - height: 100vh; - } - - body.swap { - grid-template-areas: "chat gutter video"; - } - - .info { - flex-wrap: nowrap; - } - - #video { - grid-area: video; - width: 100%; - height: 100%; - /* Breaks subs after viewport overflow on FF+Linux (SyncTube#28) */ - /* overflow: auto; */ - overflow: scroll; - background: var(--background-video); - } - - #header { - display: flex; - flex: 1; - flex-wrap: nowrap; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - font-size: 1.953rem; - } - - #currenttitle { - text-overflow: ellipsis; - overflow: hidden; - } - - .gutter { - grid-area: gutter; - display: block; - cursor: col-resize; - background-color: var(--border); - transition: background-color ease-in-out .15s; - } - - .gutter:hover { - background-color: var(--accent); - } - - #chat { - grid-area: chat; - height: 100vh; - } -} - /* Mobile page fullscreen */ .mobile-view #chatbox { diff --git a/res/index.html b/res/index.html index 0d7c797..fa4acde 100644 --- a/res/index.html +++ b/res/index.html @@ -4,13 +4,13 @@ <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> <title>SyncTube</title> <link rel="icon" type="image/png" href="img/favicon.png" /> <link id="usertheme" href="css/des.css" rel="stylesheet"> <link id="customcss" href="css/custom.css" rel="stylesheet"> - <script type="module" src="https://cdn.jsdelivr.net/npm/ionicons@5.0.0/dist/ionicons/ionicons.esm.js"></script> - <script nomodule="" src="https://cdn.jsdelivr.net/npm/ionicons@5.0.0/dist/ionicons/ionicons.js"></script> + <script type="module" src="https://cdn.jsdelivr.net/npm/ionicons@7.4.0/dist/ionicons/ionicons.esm.js"></script> + <script nomodule="" src="https://cdn.jsdelivr.net/npm/ionicons@7.4.0/dist/ionicons/ionicons.js"></script> </head> <body style="grid-template-columns: 1fr 4px 300px;"> @@ -193,10 +193,10 @@ </div> </ul> <!-- Messages --> - <div id="messagebuffer"></div> + <div id="messagebuffer" style="flex-direction: column-reverse;"></div> <div id="chat-inputs-wrapper"> <button id="scroll-to-chat-end" style="display: none; opacity: 0;" class="active"> - <ion-icon name="arrow-down" role="img" class="md hydrated" aria-label="arrow down"></ion-icon> + <ion-icon name="arrow-down" role="img" class="md hydrated"></ion-icon> </button> <!-- Message input --> <div id="chatbox"> @@ -205,7 +205,7 @@ <ion-icon name="happy"></ion-icon> </button> </div> - <div id="smiles-wrap" class="collapsible"> + <div id="smiles-wrap" class="collapsible" style="display: none;"> <div id="smiles-list"></div> </div> <!-- Guest login --> @@ -225,7 +225,7 @@ </div> </aside> - <script src="https://cdn.jsdelivr.net/npm/split-grid@1.0.9/dist/split-grid.js"></script> + <script src="https://cdn.jsdelivr.net/npm/split-grid@1.0.11/dist/split-grid.min.js"></script> <script src="client.js"></script> <script src="js/custom.js"></script> </body> diff --git a/src/client/Buttons.hx b/src/client/Buttons.hx index dbcf759..36f5729 100644 --- a/src/client/Buttons.hx +++ b/src/client/Buttons.hx @@ -20,7 +20,7 @@ class Buttons { if (settings.isSwapped) swapPlayerAndChat(); initSplit(); setSplitSize(settings.chatSize); - initChatInput(main); + initChatInputs(main); for (item in settings.checkboxes) { if (item.checked == null) continue; @@ -49,7 +49,7 @@ class Buttons { if (list.children.length == 0) return; final isActive = smilesBtn.classList.toggle("active"); if (isActive) { - wrap.style.display = "block"; + wrap.style.display = ""; wrap.style.height = outerHeight(list) + "px"; } else { wrap.style.height = "0"; @@ -65,22 +65,15 @@ class Buttons { } final scrollToChatEndBtn = ge("#scroll-to-chat-end"); - function scrollToChatEndBtnAnim():Void { - if (scrollToChatEndBtn.style.opacity == "0") return; - scrollToChatEndBtn.style.opacity = "0"; - scrollToChatEndBtn.addEventListener("transitionend", e -> { - scrollToChatEndBtn.style.display = "none"; - }, {once: true}); - } scrollToChatEndBtn.onclick = e -> { main.scrollChatToEnd(); - scrollToChatEndBtnAnim(); + main.hideScrollToChatEndBtn(); } // hide scroll button when chat is scrolled to the end final msgBuf = ge("#messagebuffer"); msgBuf.onscroll = e -> { - if (msgBuf.offsetHeight + msgBuf.scrollTop < msgBuf.scrollHeight - 1) return; - scrollToChatEndBtnAnim(); + if (!main.isInChatEnd(1)) return; + main.hideScrollToChatEndBtn(); } ge("#clearchatbtn").onclick = e -> { @@ -114,7 +107,7 @@ class Buttons { final style = ge("#userlist").style; if (isHidden) { icon.setAttribute("name", "chevron-down"); - style.display = "block"; + style.display = ""; final list = wrap.firstElementChild; wrap.style.height = "15vh"; wrap.style.marginBottom = "1rem"; @@ -161,6 +154,7 @@ class Buttons { final fullscreenBtn = ge("#fullscreenbtn"); fullscreenBtn.onclick = e -> { if ((Utils.isTouch() || main.isVerbose()) && !Utils.hasFullscreen()) { + window.scrollTo(0, 0); Utils.requestFullscreen(document.documentElement); } else { Utils.requestFullscreen(ge("#ytapiplayer")); @@ -254,9 +248,9 @@ class Buttons { final exitBtn = ge("#exitBtn"); exitBtn.onclick = e -> { + showOptions.onclick(); if (main.isUser()) main.send({type: Logout}); else ge("#guestname").focus(); - toggleGroup(showOptions); } final swapLayoutBtn = ge("#swapLayoutBtn"); @@ -429,7 +423,7 @@ class Buttons { ge("#hotkeysBtn").innerText = '$text: $state'; } - static function initChatInput(main:Main):Void { + static function initChatInputs(main:Main):Void { final guestName:InputElement = cast ge("#guestname"); guestName.onkeydown = e -> { if (e.keyCode == KeyCode.Return) { @@ -447,38 +441,25 @@ class Buttons { } } - if (Utils.isIOS()) { - document.ontouchmove = e -> { - e.preventDefault(); - } - document.body.style.height = "-webkit-fill-available"; - ge("#chat").style.height = "-webkit-fill-available"; - } final chatline:InputElement = cast ge("#chatline"); chatline.onfocus = e -> { if (Utils.isIOS()) { - final startY = window.scrollY; + // final startY = window.scrollY; + final startY = 0; Timer.delay(() -> { window.scrollBy(0, -(window.scrollY - startY)); ge("#video").scrollTop = 0; main.scrollChatToEnd(); - if (getVisualViewport() == null) { // ios < 13 - ge("#chat").style.height = '${window.innerHeight}px'; - } }, 100); - } else if (Utils.isTouch()) main.scrollChatToEnd(); - } - if (Utils.isIOS() && getVisualViewport() != null) { - final viewport = getVisualViewport(); - viewport.addEventListener("resize", e -> { - ge("#chat").style.height = '${window.innerHeight}px'; - }); - } - chatline.onblur = e -> { - if (Utils.isIOS() && getVisualViewport() == null) { // ios < 13 - ge("#chat").style.height = "-webkit-fill-available"; + } else if (Utils.isTouch()) { + main.scrollChatToEnd(); } } + final viewport = getVisualViewport(); + if (viewport != null) { + viewport.addEventListener("resize", e -> onViewportResize()); + onViewportResize(); + } new InputWithHistory(chatline, 50, value -> { if (main.handleCommands(value)) return true; main.send({ @@ -506,6 +487,15 @@ class Buttons { } } + public static function onViewportResize():Void { + final viewport = getVisualViewport() ?? return; + final isPortrait = window.innerHeight > window.innerWidth; + final playerH = ge("#ytapiplayer").offsetHeight; + var h = viewport.height - playerH; + if (!isPortrait) h = viewport.height; + ge("#chat").style.height = '${h}px'; + } + static inline function getVisualViewport():Null<VisualViewport> { return (window : Dynamic).visualViewport; } diff --git a/src/client/Main.hx b/src/client/Main.hx index 72dbf8e..9a4b426 100644 --- a/src/client/Main.hx +++ b/src/client/Main.hx @@ -26,6 +26,7 @@ import js.html.WebSocket; using ClientTools; class Main { + public static var instance(default, null):Main; static inline var SETTINGS_VERSION = 5; public final settings:ClientSettings; @@ -51,9 +52,10 @@ class Main { var onTimeGet:Timer; var onBlinkTab:Null<Timer>; var gotFirstPageInteraction = false; + var msgBuf = ge("#messagebuffer"); static function main():Void { - new Main(); + instance = new Main(); } function new() { @@ -723,7 +725,7 @@ class Main { button.disabled = true; } final adminMenu = ge("#adminMenu"); - if (isAdmin()) adminMenu.style.display = "block"; + if (isAdmin()) adminMenu.style.display = ""; else adminMenu.style.display = "none"; } @@ -815,7 +817,7 @@ class Main { } function showGuestLoginPanel():Void { - ge("#guestlogin").style.display = "flex"; + ge("#guestlogin").style.display = ""; ge("#guestpassword").style.display = "none"; ge("#chatbox").style.display = "none"; ge("#exitBtn").textContent = Lang.get("login"); @@ -824,14 +826,14 @@ class Main { function hideGuestLoginPanel():Void { ge("#guestlogin").style.display = "none"; ge("#guestpassword").style.display = "none"; - ge("#chatbox").style.display = "flex"; + ge("#chatbox").style.display = ""; ge("#exitBtn").textContent = Lang.get("exit"); } function showGuestPasswordPanel():Void { ge("#guestlogin").style.display = "none"; ge("#chatbox").style.display = "none"; - ge("#guestpassword").style.display = "flex"; + ge("#guestpassword").style.display = ""; (cast ge("#guestpass") : InputElement).type = "password"; ge("#guestpass_icon").setAttribute("name", "eye"); } @@ -850,35 +852,32 @@ class Main { } function chatMessageConnected():Void { - final msgBuf = ge("#messagebuffer"); if (isLastMessageConnectionStatus()) { msgBuf.removeChild(msgBuf.lastChild); } final div = document.createDivElement(); div.className = "server-msg-reconnect"; div.textContent = Lang.get("msgConnected"); - msgBuf.appendChild(div); + addMessageDiv(div); scrollChatToEnd(); } function chatMessageDisconnected():Void { - final msgBuf = ge("#messagebuffer"); if (isLastMessageConnectionStatus()) { msgBuf.removeChild(msgBuf.lastChild); } final div = document.createDivElement(); div.className = "server-msg-disconnect"; div.textContent = Lang.get("msgDisconnected"); - msgBuf.appendChild(div); + addMessageDiv(div); scrollChatToEnd(); } function isLastMessageConnectionStatus():Bool { - final msgBuf = ge("#messagebuffer"); return msgBuf.lastElementChild?.className.startsWith("server-msg"); } - public static function serverMessage(text:String, isText = true, withTimestamp = true):Void { + public function serverMessage(text:String, isText = true, withTimestamp = true):Void { final div = document.createDivElement(); final time = Date.now().toString().split(" ")[1]; div.className = "server-whisper"; @@ -889,12 +888,11 @@ class Main { final textDiv = div.querySelector(".server-whisper"); if (isText) textDiv.textContent = text; else textDiv.innerHTML = text; - final msgBuf = ge("#messagebuffer"); - msgBuf.appendChild(div); - msgBuf.scrollTop = msgBuf.scrollHeight; + addMessageDiv(div); + scrollChatToEnd(); } - public static function serverHtmlMessage(el:Element):Void { + public function serverHtmlMessage(el:Element):Void { final div = document.createDivElement(); final time = Date.now().toString().split(" ")[1]; div.className = "server-whisper"; @@ -903,9 +901,8 @@ class Main { <span class="timestamp">$time</span> </div>'; div.querySelector(".server-whisper").appendChild(el); - final msgBuf = ge("#messagebuffer"); - msgBuf.appendChild(div); - msgBuf.scrollTop = msgBuf.scrollHeight; + addMessageDiv(div); + scrollChatToEnd(); } function updateUserList():Void { @@ -931,7 +928,7 @@ class Main { } function clearChat():Void { - ge("#messagebuffer").textContent = ""; + msgBuf.textContent = ""; } function getLocalDateFromUtc(utcDate:String):String { @@ -941,7 +938,6 @@ class Main { } function addMessage(name:String, text:String, ?date:String):Void { - final msgBuf = ge("#messagebuffer"); final userDiv = document.createDivElement(); userDiv.className = 'chat-msg-$name'; @@ -968,10 +964,9 @@ class Main { text = filter.regex.replace(text, filter.replace); } textDiv.innerHTML = text; - final isInChatEnd = msgBuf.scrollTop - + msgBuf.clientHeight >= msgBuf.scrollHeight - 50; + final inChatEnd = isInChatEnd(); - if (isInChatEnd) { // scroll chat to end after images loaded + if (inChatEnd) { // scroll chat to end after images loaded for (img in textDiv.getElementsByTagName("img")) { img.onload = onChatImageLoaded; } @@ -984,13 +979,14 @@ class Main { headDiv.appendChild(nameDiv); headDiv.appendChild(tstamp); userDiv.appendChild(textDiv); - msgBuf.appendChild(userDiv); - if (isInChatEnd) { + addMessageDiv(userDiv); + + if (inChatEnd) { while (msgBuf.children.length > 200) { msgBuf.removeChild(msgBuf.firstChild); } } - if (isInChatEnd || name == personal.name) { + if (inChatEnd || name == personal.name) { scrollChatToEnd(); } else { showScrollToChatEndBtn(); @@ -998,12 +994,26 @@ class Main { if (onBlinkTab == null) blinkTabWithTitle('*${Lang.get("chat")}*'); } - function showScrollToChatEndBtn() { + function addMessageDiv(userDiv:Element):Void { + if (isMessageBufferReversed()) msgBuf.prepend(userDiv); + else msgBuf.appendChild(userDiv); + } + + public function showScrollToChatEndBtn():Void { final btn = ge("#scroll-to-chat-end"); - btn.style.display = "block"; + btn.style.display = ""; Timer.delay(() -> btn.style.opacity = "1", 0); } + public function hideScrollToChatEndBtn():Void { + final btn = ge("#scroll-to-chat-end"); + if (btn.style.opacity == "0") return; + btn.style.opacity = "0"; + btn.addEventListener("transitionend", e -> { + btn.style.display = "none"; + }, {once: true}); + } + function onChatImageLoaded(e:Event):Void { scrollChatToEnd(); (cast e.target : Element).onload = null; @@ -1028,9 +1038,27 @@ class Main { el.onloadedmetadata = null; } + public function isMessageBufferReversed():Bool { + return msgBuf.style.flexDirection == "column-reverse"; + } + + public function isInChatEnd(ignoreOffset = 50):Bool { + final isReverse = isMessageBufferReversed(); + var scrollTop = msgBuf.scrollTop; + // zero to negative in column-reverse + if (isReverse) scrollTop = -scrollTop; + if (isReverse) return scrollTop <= ignoreOffset; + return scrollTop + msgBuf.clientHeight >= msgBuf.scrollHeight - ignoreOffset; + } + public function scrollChatToEnd():Void { - final msgBuf = ge("#messagebuffer"); - msgBuf.scrollTop = msgBuf.scrollHeight; + final isReverse = isMessageBufferReversed(); + if (isReverse) { + if (Utils.isMacSafari) msgBuf.scrollTop = -1; + msgBuf.scrollTop = 0; + } else { + msgBuf.scrollTop = msgBuf.scrollHeight; + } } /* Returns `true` if text should not be sent to chat */ diff --git a/src/client/Player.hx b/src/client/Player.hx index f51d017..0efa2e3 100644 --- a/src/client/Player.hx +++ b/src/client/Player.hx @@ -24,7 +24,7 @@ class Player { final rawPlayer:IPlayer; final videoList = new VideoList(); final videoItemsEl = ge("#queue"); - final playerEl:Element = ge("#ytapiplayer"); + final playerEl = ge("#ytapiplayer"); var player:Null<IPlayer>; var isLoaded = false; var skipSetTime = false; @@ -49,6 +49,20 @@ class Player { iframePlayer = new Iframe(main, this); rawPlayer = new Raw(main, this); initItemButtons(); + + final resizeObserver = Utils.createResizeObserver(entries -> { + if (isLoaded) return; + Buttons.onViewportResize(); + }); + if (resizeObserver != null) { + resizeObserver.observe(playerEl); + } else { + final timer = new haxe.Timer(50); + timer.run = () -> { + if (isLoaded) return; + Buttons.onViewportResize(); + } + } } function initItemButtons():Void { @@ -239,6 +253,7 @@ class Player { public function onCanBePlayed():Void { if (!isLoaded) main.send({type: VideoLoaded}); isLoaded = true; + Buttons.onViewportResize(); } public function onPlay():Void { diff --git a/src/client/Utils.hx b/src/client/Utils.hx index a0e19f7..155292f 100644 --- a/src/client/Utils.hx +++ b/src/client/Utils.hx @@ -26,6 +26,16 @@ class Utils { || (~/^Mac/.match(navigator.platform) && navigator.maxTouchPoints > 4); } + public static var isMacSafari = _isMacSafari(); + + static function _isMacSafari():Bool { + final isMac = navigator.userAgent.contains("Macintosh"); + final isSafari = navigator.userAgent.contains("Safari") + && !navigator.userAgent.contains("Chrom") + && !navigator.userAgent.contains("Edg"); + return isMac && isSafari; + } + public static function isAndroid():Bool { final ua = navigator.userAgent.toLowerCase(); return ua.indexOf("android") > -1; @@ -66,8 +76,6 @@ class Utils { final el2:Dynamic = el; if (el.requestFullscreen != null) { el.requestFullscreen(); - } else if (el2.mozRequestFullScreen != null) { - el2.mozRequestFullScreen(); } else if (el2.webkitRequestFullscreen != null) { el2.webkitRequestFullscreen(untyped Element.ALLOW_KEYBOARD_INPUT); } else return false; @@ -77,7 +85,6 @@ class Utils { public static function cancelFullscreen(el:Element):Void { final doc:Dynamic = document; if (doc.cancelFullScreen != null) doc.cancelFullScreen(); - else if (doc.mozCancelFullScreen != null) doc.mozCancelFullScreen(); else if (doc.webkitCancelFullScreen != null) doc.webkitCancelFullScreen(); } @@ -159,4 +166,13 @@ class Utils { document.body.removeChild(a); URL.revokeObjectURL(url); } + + public static function createResizeObserver(callback:(entries:Array<Dynamic>) -> Void):Null<{ + observe:(el:Element) -> Void + }> { + return null; + final window = js.Browser.window; + final observer = (window : Dynamic).ResizeObserver ?? return null; + return js.Syntax.code("new ResizeObserver({0})", callback); + } } diff --git a/src/client/players/Raw.hx b/src/client/players/Raw.hx index eb93c84..01752e7 100644 --- a/src/client/players/Raw.hx +++ b/src/client/players/Raw.hx @@ -140,7 +140,7 @@ class Raw implements IPlayer { final subsUri = try { new URL(subsUrl); } catch (e) { - Main.serverMessage('Failed to add subs: bad url ($subsUrl)'); + Main.instance.serverMessage('Failed to add subs: bad url ($subsUrl)'); return; } // make local url as relative path to skip proxy diff --git a/src/client/players/RawSubs.hx b/src/client/players/RawSubs.hx index a4404b0..e9b2203 100644 --- a/src/client/players/RawSubs.hx +++ b/src/client/players/RawSubs.hx @@ -215,7 +215,7 @@ class RawSubs { static function isProxyError(text:String):Bool { if (text.startsWith("Proxy error:")) { - Main.serverMessage("Failed to add subs: proxy error"); + Main.instance.serverMessage("Failed to add subs: proxy error"); trace('Failed to add subs: $text'); return true; } diff --git a/src/client/players/Youtube.hx b/src/client/players/Youtube.hx index 5a8921a..b30dfb3 100644 --- a/src/client/players/Youtube.hx +++ b/src/client/players/Youtube.hx @@ -165,7 +165,7 @@ class Youtube implements IPlayer { function youtubeApiError(error:Dynamic):Void { final code:Int = error.code; final msg:String = error.message; - Main.serverMessage('Error $code: $msg', false); + Main.instance.serverMessage('Error $code: $msg', false); } function getRemoteDataFallback(url:String, callback:(data:VideoData) -> Void):Void { |
