aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--res/client.js44
-rw-r--r--res/css/cytube.css7
-rw-r--r--src/client/Buttons.hx2
-rw-r--r--src/client/Main.hx31
-rw-r--r--src/client/Player.hx9
-rw-r--r--src/client/Utils.hx6
-rw-r--r--src/client/players/Raw.hx2
7 files changed, 80 insertions, 21 deletions
diff --git a/res/client.js b/res/client.js
index 8161f26..715fe24 100644
--- a/res/client.js
+++ b/res/client.js
@@ -530,7 +530,9 @@ client_Buttons.init = function(main) {
client_Buttons.split.setSizes(sizes);
client_Buttons.settings.isExtendedPlayer = isExtended;
client_Buttons.writeSplitSize();
- return window.dispatchEvent(new Event("resize"));
+ window.dispatchEvent(new Event("resize"));
+ main.scrollChatToEnd();
+ return;
};
if(client_Buttons.settings.isExtendedPlayer) {
extendPlayer.onclick();
@@ -749,6 +751,7 @@ client_Buttons.initNavBar = function(main) {
client_Buttons.initSplit();
swapLayoutBtn.blur();
client_Buttons.hideMenus();
+ main.scrollChatToEnd();
return;
};
if(client_Buttons.settings.isSwapped) {
@@ -1389,7 +1392,7 @@ client_Main.prototype = {
while(_g2 < _g3.length) {
var emote = _g3[_g2];
++_g2;
- var tag = StringTools.endsWith(emote.image,"mp4") ? "video autoplay=\"\" loop=\"\"" : "img";
+ var tag = StringTools.endsWith(emote.image,"mp4") ? "video autoplay=\"\" loop=\"\" muted=\"\"" : "img";
this.filters.push({ regex : new EReg("(^| )" + this.escapeRegExp(emote.name) + "(?!\\S)","g"), replace : "$1<" + tag + " class=\"channel-emote\" src=\"" + emote.image + "\" title=\"" + emote.name + "\"/>"});
}
window.document.querySelector("#smilesbtn").classList.remove("active");
@@ -1549,6 +1552,14 @@ client_Main.prototype = {
}
textDiv.innerHTML = text;
var isInChatEnd = msgBuf.scrollTop + msgBuf.clientHeight >= msgBuf.scrollHeight - 1;
+ if(isInChatEnd) {
+ var _g2 = 0;
+ var _g11 = textDiv.getElementsByTagName("img");
+ while(_g2 < _g11.length) _g11[_g2++].onload = $bind(this,this.onChatImageLoaded);
+ var _g21 = 0;
+ var _g3 = textDiv.getElementsByTagName("video");
+ while(_g21 < _g3.length) _g3[_g21++].onloadedmetadata = $bind(this,this.onChatVideoLoaded);
+ }
userDiv.appendChild(tstamp);
userDiv.appendChild(nameDiv);
userDiv.appendChild(textDiv);
@@ -1572,6 +1583,21 @@ client_Main.prototype = {
this.onBlinkTab.run();
}
}
+ ,onChatImageLoaded: function(e) {
+ this.scrollChatToEnd();
+ e.target.onload = null;
+ }
+ ,onChatVideoLoaded: function(e) {
+ var _gthis = this;
+ haxe_Timer.delay(function() {
+ _gthis.scrollChatToEnd();
+ return e.target.onloadedmetadata = null;
+ },100);
+ }
+ ,scrollChatToEnd: function() {
+ var msgBuf = window.document.querySelector("#messagebuffer");
+ msgBuf.scrollTop = msgBuf.scrollHeight;
+ }
,handleCommands: function(text) {
if(text == "clear") {
if((this.personal.group & 4) != 0) {
@@ -1782,7 +1808,7 @@ client_Player.prototype = {
}
,addVideoItem: function(item,atEnd) {
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>");
+ var itemEl = client_Utils.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) {
@@ -1907,11 +1933,6 @@ client_Player.prototype = {
while(_g < _g1.length) time += _g1[_g++].duration;
return this.duration(time);
}
- ,nodeFromString: function(div) {
- var wrapper = window.document.createElement("div");
- wrapper.innerHTML = div;
- return wrapper.firstElementChild;
- }
,isListEmpty: function() {
return this.items.length == 0;
}
@@ -2053,6 +2074,11 @@ client_Utils.__name__ = true;
client_Utils.isTouch = function() {
return 'ontouchstart' in window;
};
+client_Utils.nodeFromString = function(div) {
+ var wrapper = window.document.createElement("div");
+ wrapper.innerHTML = div;
+ return wrapper.firstElementChild;
+};
client_Utils.prepend = function(parent,child) {
if(parent.firstChild == null) {
parent.appendChild(child);
@@ -2235,10 +2261,10 @@ client_players_Raw.prototype = {
}
,restartControlsHider: function() {
var _gthis = this;
+ this.video.controls = true;
if(client_Utils.isTouch()) {
return;
}
- this.video.controls = true;
if(this.controlsHider != null) {
this.controlsHider.stop();
}
diff --git a/res/css/cytube.css b/res/css/cytube.css
index b080f91..55e832c 100644
--- a/res/css/cytube.css
+++ b/res/css/cytube.css
@@ -101,11 +101,16 @@
max-height: 75px;
cursor: pointer;
}
-.channel-emote, .chat-img {
+.channel-emote {
max-width: 150px;
max-height: 150px;
}
+.chat-img {
+ max-width: 200px;
+ max-height: 200px;
+}
video.channel-emote, video.chat-img {
+ background-color: transparent;
/* Fixes default video tag size in chat when tab unloads videos in background */
/* (some browsers optimization i guess) */
height: 150px;
diff --git a/src/client/Buttons.hx b/src/client/Buttons.hx
index a7dd4e1..d4533bf 100644
--- a/src/client/Buttons.hx
+++ b/src/client/Buttons.hx
@@ -90,6 +90,7 @@ class Buttons {
settings.isExtendedPlayer = isExtended;
writeSplitSize();
window.dispatchEvent(new Event("resize"));
+ main.scrollChatToEnd();
}
if (settings.isExtendedPlayer) extendPlayer.onclick();
@@ -281,6 +282,7 @@ class Buttons {
initSplit();
swapLayoutBtn.blur();
hideMenus();
+ main.scrollChatToEnd();
}
if (settings.isSwapped) swapLayoutBtn.onclick();
final removeBtn = ge("#removeVideoBtn");
diff --git a/src/client/Main.hx b/src/client/Main.hx
index 5ee14d6..fda93c7 100644
--- a/src/client/Main.hx
+++ b/src/client/Main.hx
@@ -510,7 +510,7 @@ class Main {
});
}
for (emote in config.emotes) {
- final tag = emote.image.endsWith("mp4") ? 'video autoplay="" loop=""' : "img";
+ final tag = emote.image.endsWith("mp4") ? 'video autoplay="" loop="" muted=""' : "img";
filters.push({
regex: new EReg("(^| )" + escapeRegExp(emote.name) + "(?!\\S)", "g"),
replace: '$1<$tag class="channel-emote" src="${emote.image}" title="${emote.name}"/>'
@@ -656,8 +656,17 @@ class Main {
}
}
textDiv.innerHTML = text;
-
final isInChatEnd = msgBuf.scrollTop + msgBuf.clientHeight >= msgBuf.scrollHeight - 1;
+
+ if (isInChatEnd) { // scroll chat to end after images loaded
+ for (img in textDiv.getElementsByTagName("img")) {
+ img.onload = onChatImageLoaded;
+ }
+ for (video in textDiv.getElementsByTagName("video")) {
+ video.onloadedmetadata = onChatVideoLoaded;
+ }
+ }
+
userDiv.appendChild(tstamp);
userDiv.appendChild(nameDiv);
userDiv.appendChild(textDiv);
@@ -680,6 +689,24 @@ class Main {
}
}
+ function onChatImageLoaded(e:Event):Void {
+ scrollChatToEnd();
+ (cast e.target : Element).onload = null;
+ }
+
+ function onChatVideoLoaded(e:Event):Void {
+ // for some time default video size is 300x150px
+ Timer.delay(() -> {
+ scrollChatToEnd();
+ (cast e.target : Element).onloadedmetadata = null;
+ }, 100);
+ }
+
+ public function scrollChatToEnd():Void {
+ final msgBuf = ge("#messagebuffer");
+ msgBuf.scrollTop = msgBuf.scrollHeight;
+ }
+
final matchNumbers = ~/^-?[0-9]+$/;
function handleCommands(text:String):Void {
diff --git a/src/client/Player.hx b/src/client/Player.hx
index c853464..28b5c09 100644
--- a/src/client/Player.hx
+++ b/src/client/Player.hx
@@ -1,7 +1,6 @@
package client;
import js.html.Element;
-import js.Browser.document;
import client.Main.ge;
import client.players.Raw;
import client.players.Youtube;
@@ -180,7 +179,7 @@ class Player {
public function addVideoItem(item:VideoItem, atEnd:Bool):Void {
final url = item.url.htmlEscape(true);
- final itemEl = nodeFromString(
+ final itemEl = Utils.nodeFromString(
'<li class="queue_entry pluid-0" title="${Lang.get("addedBy")}: ${item.author}">
<a class="qe_title" href="$url" target="_blank">${item.title.htmlEscape()}</a>
<span class="qe_time">${duration(item.duration)}</span>
@@ -297,12 +296,6 @@ class Player {
return duration(time);
}
- function nodeFromString(div:String):Element {
- final wrapper = document.createDivElement();
- wrapper.innerHTML = div;
- return wrapper.firstElementChild;
- }
-
public function isListEmpty():Bool {
return items.length == 0;
}
diff --git a/src/client/Utils.hx b/src/client/Utils.hx
index 3ac9953..e9d5ff8 100644
--- a/src/client/Utils.hx
+++ b/src/client/Utils.hx
@@ -10,6 +10,12 @@ class Utils {
return js.Syntax.code("'ontouchstart' in window");
}
+ public static function nodeFromString(div:String):Element {
+ final wrapper = document.createDivElement();
+ wrapper.innerHTML = div;
+ return wrapper.firstElementChild;
+ }
+
public static function prepend(parent:Element, child:Element):Void {
if (parent.firstChild == null) parent.appendChild(child);
else parent.insertBefore(child, parent.firstChild);
diff --git a/src/client/players/Raw.hx b/src/client/players/Raw.hx
index 4fa000b..266f0a2 100644
--- a/src/client/players/Raw.hx
+++ b/src/client/players/Raw.hx
@@ -71,8 +71,8 @@ class Raw implements IPlayer {
}
function restartControlsHider():Void {
- if (Utils.isTouch()) return;
video.controls = true;
+ if (Utils.isTouch()) return;
if (controlsHider != null) controlsHider.stop();
controlsHider = Timer.delay(() -> {
video.controls = false;
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage