aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build/server.js127
-rw-r--r--res/client.js6
-rw-r--r--src/Types.hx6
-rw-r--r--src/VideoList.hx4
-rw-r--r--src/client/Main.hx6
-rw-r--r--src/client/Player.hx19
-rw-r--r--src/server/HttpServer.hx7
-rw-r--r--src/server/Main.hx79
8 files changed, 183 insertions, 71 deletions
diff --git a/build/server.js b/build/server.js
index b5b2902..c4fd7c8 100644
--- a/build/server.js
+++ b/build/server.js
@@ -3784,7 +3784,7 @@ server_HttpServer.serveMedia = function(req,res,filePath) {
return true;
};
server_HttpServer.isMediaExtension = function(ext) {
- if(!(ext == "mp4" || ext == "mp3")) {
+ if(!(ext == "mp4" || ext == "webm" || ext == "mp3")) {
return ext == "wav";
} else {
return true;
@@ -3968,7 +3968,7 @@ server_Logger.prototype = {
,__class__: server_Logger
};
var server_Main = function(opts) {
- this.flashbackTime = 0.0;
+ this.flashbackTimes = [];
this.loadedClientsCount = 0;
this.matchGuestName = new EReg("guest [0-9]+","");
this.matchHtmlChars = new EReg("[&^<>'\"]","");
@@ -4030,7 +4030,7 @@ var server_Main = function(opts) {
preparePort = function() {
server_Utils.isPortFree(_gthis.port,function(isFree) {
if(!isFree && attempts > 0) {
- haxe_Log.trace("Warning: port " + _gthis.port + " is already in use. Changed to " + (_gthis.port + 1),{ fileName : "src/server/Main.hx", lineNumber : 111, className : "server.Main", methodName : "new"});
+ haxe_Log.trace("Warning: port " + _gthis.port + " is already in use. Changed to " + (_gthis.port + 1),{ fileName : "src/server/Main.hx", lineNumber : 113, className : "server.Main", methodName : "new"});
attempts -= 1;
_gthis.port++;
preparePort();
@@ -4048,13 +4048,13 @@ server_Main.main = function() {
server_Main.prototype = {
runServer: function() {
var _gthis = this;
- haxe_Log.trace("Local: http://" + this.localIp + ":" + this.port,{ fileName : "src/server/Main.hx", lineNumber : 124, className : "server.Main", methodName : "runServer"});
+ haxe_Log.trace("Local: http://" + this.localIp + ":" + this.port,{ fileName : "src/server/Main.hx", lineNumber : 126, className : "server.Main", methodName : "runServer"});
if(this.config.localNetworkOnly) {
- haxe_Log.trace("Global network is disabled in config",{ fileName : "src/server/Main.hx", lineNumber : 126, className : "server.Main", methodName : "runServer"});
+ haxe_Log.trace("Global network is disabled in config",{ fileName : "src/server/Main.hx", lineNumber : 128, className : "server.Main", methodName : "runServer"});
} else if(!this.isNoState) {
server_Utils.getGlobalIp(function(ip) {
_gthis.globalIp = ip;
- haxe_Log.trace("Global: http://" + _gthis.globalIp + ":" + _gthis.port,{ fileName : "src/server/Main.hx", lineNumber : 130, className : "server.Main", methodName : "runServer"});
+ haxe_Log.trace("Global: http://" + _gthis.globalIp + ":" + _gthis.port,{ fileName : "src/server/Main.hx", lineNumber : 132, className : "server.Main", methodName : "runServer"});
});
}
var dir = "" + this.rootDir + "/res";
@@ -4139,7 +4139,7 @@ server_Main.prototype = {
var field = _g1[_g];
++_g;
if(Reflect.field(config,field) == null) {
- haxe_Log.trace("Warning: config field \"" + field + "\" is unknown",{ fileName : "src/server/Main.hx", lineNumber : 199, className : "server.Main", methodName : "getUserConfig"});
+ haxe_Log.trace("Warning: config field \"" + field + "\" is unknown",{ fileName : "src/server/Main.hx", lineNumber : 201, className : "server.Main", methodName : "getUserConfig"});
}
config[field] = Reflect.field(customConfig,field);
}
@@ -4150,14 +4150,14 @@ server_Main.prototype = {
var emote = _g1[_g];
++_g;
if(emoteCopies_h[emote.name]) {
- haxe_Log.trace("Warning: emote name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 205, className : "server.Main", methodName : "getUserConfig"});
+ haxe_Log.trace("Warning: emote name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 207, className : "server.Main", methodName : "getUserConfig"});
}
emoteCopies_h[emote.name] = true;
if(!this.verbose) {
continue;
}
if(emoteCopies_h[emote.image]) {
- haxe_Log.trace("Warning: emote url of name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 209, className : "server.Main", methodName : "getUserConfig"});
+ haxe_Log.trace("Warning: emote url of name \"" + emote.name + "\" has copy",{ fileName : "src/server/Main.hx", lineNumber : 211, className : "server.Main", methodName : "getUserConfig"});
}
emoteCopies_h[emote.image] = true;
}
@@ -4195,7 +4195,7 @@ server_Main.prototype = {
js_node_Fs.writeFileSync("" + folder + "/users.json",JSON.stringify({ admins : users1, bans : _g, salt : users.salt},null,"\t"));
}
,saveState: function() {
- haxe_Log.trace("Saving state...",{ fileName : "src/server/Main.hx", lineNumber : 248, className : "server.Main", methodName : "saveState"});
+ haxe_Log.trace("Saving state...",{ fileName : "src/server/Main.hx", lineNumber : 250, className : "server.Main", methodName : "saveState"});
var json = JSON.stringify(this.getCurrentState(),null,"\t");
js_node_Fs.writeFileSync(this.statePath,json);
this.writeUsers(this.userList);
@@ -4210,7 +4210,7 @@ server_Main.prototype = {
if(!sys_FileSystem.exists(this.statePath)) {
return;
}
- haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 270, className : "server.Main", methodName : "loadState"});
+ haxe_Log.trace("Loading state...",{ fileName : "src/server/Main.hx", lineNumber : 272, className : "server.Main", methodName : "loadState"});
var data = JSON.parse(js_node_Fs.readFileSync(this.statePath,{ encoding : "utf8"}));
this.videoList.setItems(data.videoList);
this.messages.length = 0;
@@ -4224,7 +4224,7 @@ server_Main.prototype = {
this.videoTimer.pause();
}
,logError: function(type,data) {
- haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 285, className : "server.Main", methodName : "logError", customParams : [data]});
+ haxe_Log.trace(type,{ fileName : "src/server/Main.hx", lineNumber : 287, className : "server.Main", methodName : "logError", customParams : [data]});
var crashesFolder = "" + this.rootDir + "/user/crashes";
server_Utils.ensureDir(crashesFolder);
var name = DateTools.format(new Date(),"%Y-%m-%d_%H_%M_%S") + "-" + type;
@@ -4242,7 +4242,7 @@ server_Main.prototype = {
if(_gthis.clients.length == 0) {
return;
}
- haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 302, className : "server.Main", methodName : "initIntergationHandlers"});
+ haxe_Log.trace("Ping " + url,{ fileName : "src/server/Main.hx", lineNumber : 304, className : "server.Main", methodName : "initIntergationHandlers"});
js_node_Http.get(url,null,function(r) {
});
};
@@ -4262,13 +4262,13 @@ server_Main.prototype = {
password += this.config.salt;
var hash = haxe_crypto_Sha256.encode(password);
this.userList.admins.push({ name : name, hash : hash});
- haxe_Log.trace("Admin " + name + " added.",{ fileName : "src/server/Main.hx", lineNumber : 325, className : "server.Main", methodName : "addAdmin"});
+ haxe_Log.trace("Admin " + name + " added.",{ fileName : "src/server/Main.hx", lineNumber : 327, className : "server.Main", methodName : "addAdmin"});
}
,removeAdmin: function(name) {
HxOverrides.remove(this.userList.admins,Lambda.find(this.userList.admins,function(item) {
return item.name == name;
}));
- haxe_Log.trace("Admin " + name + " removed.",{ fileName : "src/server/Main.hx", lineNumber : 332, className : "server.Main", methodName : "removeAdmin"});
+ haxe_Log.trace("Admin " + name + " removed.",{ fileName : "src/server/Main.hx", lineNumber : 334, className : "server.Main", methodName : "removeAdmin"});
}
,replayLog: function(events) {
var _gthis = this;
@@ -4312,7 +4312,7 @@ server_Main.prototype = {
var ip = this.clientIp(req);
var id = this.freeIds.length > 0 ? this.freeIds.shift() : this.clients.length;
var name = "Guest " + (id + 1);
- haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 370, className : "server.Main", methodName : "onConnect", customParams : ["" + name + " connected (" + ip + ")"]});
+ haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 372, className : "server.Main", methodName : "onConnect", customParams : ["" + name + " connected (" + ip + ")"]});
var isAdmin = this.config.localAdmins && req.socket.localAddress == ip;
var client = new Client(ws,req,id,name,0);
client.setGroupFlag(ClientGroup.Admin,isAdmin);
@@ -4325,7 +4325,7 @@ server_Main.prototype = {
var obj = _gthis.wsEventParser.fromJson(data.toString());
if(_gthis.wsEventParser.errors.length > 0 || _gthis.noTypeObj(obj)) {
var errors = "" + ("Wrong request for type \"" + obj.type + "\":") + "\n" + json2object_ErrorUtils.convertErrorArray(_gthis.wsEventParser.errors);
- haxe_Log.trace(errors,{ fileName : "src/server/Main.hx", lineNumber : 386, className : "server.Main", methodName : "onConnect"});
+ haxe_Log.trace(errors,{ fileName : "src/server/Main.hx", lineNumber : 388, className : "server.Main", methodName : "onConnect"});
_gthis.serverMessage(client,errors);
return;
}
@@ -4443,6 +4443,10 @@ server_Main.prototype = {
if(!this.checkPermission(client,"removeVideo")) {
return;
}
+ if(this.videoTimer.getTime() > 30) {
+ var _this = this.videoList;
+ this.saveFlashbackTime(_this.items[_this.pos]);
+ }
this.videoTimer.stop();
var _this = this.videoList;
_this.items.length = 0;
@@ -4466,7 +4470,7 @@ server_Main.prototype = {
if(!internal) {
return;
}
- haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 446, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " disconnected"]});
+ haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 448, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " disconnected"]});
server_Utils.sortedPush(this.freeIds,client.id);
HxOverrides.remove(this.clients,client);
this.sendClientList();
@@ -4514,7 +4518,8 @@ server_Main.prototype = {
if(this.videoList.items.length == 0) {
return;
}
- this.loadFlashbackTime();
+ var _this = this.videoList;
+ this.loadFlashbackTime(_this.items[_this.pos]);
this.broadcast({ type : "Rewind", rewind : { time : this.videoTimer.getTime()}});
break;
case "GetTime":
@@ -4590,7 +4595,7 @@ server_Main.prototype = {
this.send(client,{ type : "LoginError"});
return;
}
- haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 533, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " logged as " + name]});
+ haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 535, className : "server.Main", methodName : "onMessage", customParams : ["Client " + client.name + " logged as " + name]});
client.name = name;
client.setGroupFlag(ClientGroup.User,true);
this.checkBan(client);
@@ -4603,7 +4608,7 @@ server_Main.prototype = {
var oldName = client.name;
client.name = "Guest " + (this.clients.indexOf(client) + 1);
client.setGroupFlag(ClientGroup.User,false);
- haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 554, className : "server.Main", methodName : "onMessage", customParams : ["Client " + oldName + " logout to " + client.name]});
+ haxe_Log.trace(HxOverrides.dateStr(new Date()),{ fileName : "src/server/Main.hx", lineNumber : 556, className : "server.Main", methodName : "onMessage", customParams : ["Client " + oldName + " logout to " + client.name]});
this.send(client,{ type : data.type, logout : { oldClientName : oldName, clientName : client.name, clients : this.clientList()}});
this.sendClientListExcept(client);
break;
@@ -4638,7 +4643,8 @@ server_Main.prototype = {
return;
}
if(Math.abs(data.pause.time - this.videoTimer.getTime()) > 30) {
- this.saveFlashbackTime();
+ var _this = this.videoList;
+ this.saveFlashbackTime(_this.items[_this.pos]);
}
this.videoTimer.setTime(data.pause.time);
this.videoTimer.pause();
@@ -4652,7 +4658,8 @@ server_Main.prototype = {
return;
}
if(Math.abs(data.play.time - this.videoTimer.getTime()) > 30) {
- this.saveFlashbackTime();
+ var _this = this.videoList;
+ this.saveFlashbackTime(_this.items[_this.pos]);
}
this.videoTimer.setTime(data.play.time);
this.videoTimer.play();
@@ -4662,6 +4669,10 @@ server_Main.prototype = {
if(!this.checkPermission(client,"changeOrder")) {
return;
}
+ if(this.videoTimer.getTime() > 30) {
+ var _this = this.videoList;
+ this.saveFlashbackTime(_this.items[_this.pos]);
+ }
this.videoList.setPos(data.playItem.pos);
data.playItem.pos = this.videoList.pos;
this.restartWaitTimer();
@@ -4686,6 +4697,10 @@ server_Main.prototype = {
}
var _this = this.videoList;
var isCurrent = _this.items[_this.pos].url == url;
+ if(isCurrent && this.videoTimer.getTime() > 30) {
+ var _this = this.videoList;
+ this.saveFlashbackTime(_this.items[_this.pos]);
+ }
this.videoList.removeItem(index);
if(isCurrent && this.videoList.items.length > 0) {
this.broadcast(data);
@@ -4705,7 +4720,8 @@ server_Main.prototype = {
if(data.rewind.time < 0) {
data.rewind.time = 0;
}
- this.saveFlashbackTime();
+ var _this = this.videoList;
+ this.saveFlashbackTime(_this.items[_this.pos]);
this.videoTimer.setTime(data.rewind.time);
this.broadcast({ type : data.type, rewind : data.rewind});
break;
@@ -4767,7 +4783,8 @@ server_Main.prototype = {
return;
}
if(Math.abs(data.setTime.time - this.videoTimer.getTime()) > 30) {
- this.saveFlashbackTime();
+ var _this = this.videoList;
+ this.saveFlashbackTime(_this.items[_this.pos]);
}
this.videoTimer.setTime(data.setTime.time);
this.broadcastExcept(client,{ type : data.type, setTime : data.setTime});
@@ -4865,6 +4882,12 @@ server_Main.prototype = {
if(_this.items[_this.pos].url != data.skipVideo.url) {
return;
}
+ var _this = this.videoList;
+ var dur = _this.items[_this.pos].duration;
+ if(this.videoTimer.getTime() > 30 && this.videoTimer.getTime() < dur - 30) {
+ var _this = this.videoList;
+ this.saveFlashbackTime(_this.items[_this.pos]);
+ }
this.videoList.skipItem();
if(this.videoList.items.length > 0) {
this.restartWaitTimer();
@@ -4900,7 +4923,7 @@ server_Main.prototype = {
client.setGroupFlag(ClientGroup.Banned,!isOutdated);
if(isOutdated) {
HxOverrides.remove(this.userList.bans,ban);
- haxe_Log.trace("" + client.name + " ban removed",{ fileName : "src/server/Main.hx", lineNumber : 939, className : "server.Main", methodName : "checkBan"});
+ haxe_Log.trace("" + client.name + " ban removed",{ fileName : "src/server/Main.hx", lineNumber : 955, className : "server.Main", methodName : "checkBan"});
this.sendClientList();
}
break;
@@ -4927,9 +4950,6 @@ server_Main.prototype = {
return false;
}
,restartWaitTimer: function() {
- if(this.videoTimer.getTime() > 30) {
- this.saveFlashbackTime();
- }
this.videoTimer.stop();
if(this.waitVideoStart != null) {
this.waitVideoStart.stop();
@@ -4956,17 +4976,49 @@ server_Main.prototype = {
this.broadcast({ type : "VideoLoaded"});
this.videoTimer.start();
}
- ,saveFlashbackTime: function() {
+ ,saveFlashbackTime: function(item) {
+ var url = item.url;
+ var duration = item.duration;
var time = this.videoTimer.getTime();
- if(Math.abs(this.flashbackTime - time) < 30) {
+ if(Math.abs(this.findFlashbackTime(url,duration) - time) < 30) {
return;
}
- this.flashbackTime = time;
+ this.addRecentFlashback(url,duration,time);
}
- ,loadFlashbackTime: function() {
+ ,loadFlashbackTime: function(item) {
+ var url = item.url;
+ var duration = item.duration;
var time = this.videoTimer.getTime();
- this.videoTimer.setTime(this.flashbackTime);
- this.flashbackTime = time;
+ var flashbackTime = this.findFlashbackTime(url,duration);
+ this.videoTimer.setTime(flashbackTime);
+ this.addRecentFlashback(url,duration,time);
+ }
+ ,findFlashbackTime: function(url,duration) {
+ var tmp = this.findFlashbackItem(url,duration);
+ var tmp1 = tmp != null ? tmp.time : null;
+ if(tmp1 != null) {
+ return tmp1;
+ } else {
+ return 0.0;
+ }
+ }
+ ,findFlashbackItem: function(url,duration) {
+ var item = Lambda.find(this.flashbackTimes,function(item) {
+ return item.url == url;
+ });
+ if(duration != null && item == null) {
+ item = Lambda.find(this.flashbackTimes,function(item) {
+ return item.duration == duration;
+ });
+ }
+ return item;
+ }
+ ,addRecentFlashback: function(url,duration,time) {
+ HxOverrides.remove(this.flashbackTimes,this.findFlashbackItem(url));
+ this.flashbackTimes.unshift({ url : url, duration : duration, time : time});
+ if(Lambda.count(this.flashbackTimes) > 10) {
+ this.flashbackTimes.pop();
+ }
}
,isPlaylistLockedFor: function(client) {
if(!this.videoList.isOpen) {
@@ -5244,13 +5296,16 @@ server_HttpServer.mimeTypes = (function($this) {
_g.h["css"] = "text/css";
_g.h["json"] = "application/json";
_g.h["png"] = "image/png";
- _g.h["jpg"] = "image/jpg";
+ _g.h["jpg"] = "image/jpeg";
+ _g.h["jpeg"] = "image/jpeg";
_g.h["gif"] = "image/gif";
+ _g.h["webp"] = "image/webp";
_g.h["svg"] = "image/svg+xml";
_g.h["ico"] = "image/x-icon";
_g.h["wav"] = "audio/wav";
_g.h["mp3"] = "audio/mpeg";
_g.h["mp4"] = "video/mp4";
+ _g.h["webm"] = "video/webm";
_g.h["woff"] = "application/font-woff";
_g.h["ttf"] = "application/font-ttf";
_g.h["eot"] = "application/vnd.ms-fontobject";
diff --git a/res/client.js b/res/client.js
index 432ac20..beb88e3 100644
--- a/res/client.js
+++ b/res/client.js
@@ -1884,7 +1884,7 @@ client_Main.prototype = {
while(_g < _g1.length) {
var emote = _g1[_g];
++_g;
- var tag = StringTools.endsWith(emote.image,"mp4") ? "video autoplay=\"\" loop=\"\" muted=\"\"" : "img";
+ var tag = StringTools.endsWith(emote.image,"mp4") || StringTools.endsWith(emote.image,"webm") ? "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");
@@ -1905,7 +1905,7 @@ client_Main.prototype = {
while(_g < _g1.length) {
var emote = _g1[_g];
++_g;
- var tag = StringTools.endsWith(emote.image,"mp4") ? "video" : "img";
+ var tag = StringTools.endsWith(emote.image,"mp4") || StringTools.endsWith(emote.image,"webm") ? "video" : "img";
var el = window.document.createElement(tag);
el.className = "smile-preview";
el.dataset.src = emote.image;
@@ -2737,7 +2737,7 @@ client_Player.prototype = {
}
};
http.onError = function(msg) {
- haxe_Log.trace(msg,{ fileName : "src/client/Player.hx", lineNumber : 479, className : "client.Player", methodName : "skipAd"});
+ haxe_Log.trace(msg,{ fileName : "src/client/Player.hx", lineNumber : 478, className : "client.Player", methodName : "skipAd"});
};
http.request();
}
diff --git a/src/Types.hx b/src/Types.hx
index fe0e6b2..4ef233b 100644
--- a/src/Types.hx
+++ b/src/Types.hx
@@ -107,6 +107,12 @@ typedef VideoItem = {
isIframe:Bool
}
+typedef FlashbackItem = {
+ url:String,
+ duration:Float,
+ time:Float
+}
+
typedef WsEvent = {
type:WsEventType,
?connected:{
diff --git a/src/VideoList.hx b/src/VideoList.hx
index 2ed1d8f..094d2ab 100644
--- a/src/VideoList.hx
+++ b/src/VideoList.hx
@@ -17,7 +17,9 @@ class VideoList {
return items.length;
}
- public inline function getCurrentItem():VideoItem {
+ public var currentItem(get, never):VideoItem;
+
+ inline function get_currentItem():Null<VideoItem> {
return items[pos];
}
diff --git a/src/client/Main.hx b/src/client/Main.hx
index 69450d9..b1e0eb6 100644
--- a/src/client/Main.hx
+++ b/src/client/Main.hx
@@ -720,7 +720,8 @@ class Main {
});
}
for (emote in config.emotes) {
- final tag = emote.image.endsWith("mp4") ? 'video autoplay="" loop="" muted=""' : "img";
+ final isVideoExt = emote.image.endsWith("mp4") || emote.image.endsWith("webm");
+ final tag = isVideoExt ? '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}"/>'
@@ -739,7 +740,8 @@ class Main {
}
smilesList.textContent = "";
for (emote in config.emotes) {
- final tag = emote.image.endsWith("mp4") ? "video" : "img";
+ final isVideoExt = emote.image.endsWith("mp4") || emote.image.endsWith("webm");
+ final tag = isVideoExt ? "video" : "img";
final el = document.createElement(tag);
el.className = "smile-preview";
el.dataset.src = emote.image;
diff --git a/src/client/Player.hx b/src/client/Player.hx
index 6113c07..75b44b5 100644
--- a/src/client/Player.hx
+++ b/src/client/Player.hx
@@ -92,7 +92,7 @@ class Player {
function setPlayer(newPlayer:IPlayer):Void {
if (player != newPlayer) {
if (player != null) {
- JsApi.fireVideoRemoveEvents(videoList.getCurrentItem());
+ JsApi.fireVideoRemoveEvents(videoList.currentItem);
player.removeVideo();
}
main.blinkTabWithTitle("*Video*");
@@ -139,7 +139,7 @@ class Player {
public function changeVideoSrc(src:String):Void {
if (!main.isVideoEnabled) return;
if (player == null) return;
- final item = videoList.getCurrentItem() ?? return;
+ final item = videoList.currentItem ?? return;
player.loadVideo({
url: src,
title: item.title,
@@ -152,7 +152,7 @@ class Player {
}
public function removeVideo():Void {
- JsApi.fireVideoRemoveEvents(videoList.getCurrentItem());
+ JsApi.fireVideoRemoveEvents(videoList.currentItem);
player.removeVideo();
ge("#currenttitle").textContent = Lang.get("nothingPlaying");
setPauseIndicator(true);
@@ -278,7 +278,7 @@ class Player {
var index = videoList.findIndex(item -> item.url == url);
if (index == -1) return;
- final isCurrent = videoList.getCurrentItem().url == url;
+ final isCurrent = videoList.currentItem.url == url;
videoList.removeItem(index);
updateCounters();
@@ -301,7 +301,7 @@ class Player {
if (pos == -1) return;
removeActiveLabel(videoList.pos);
videoList.setPos(pos);
- if (videoList.getCurrentItem().isTemp) removeElementItem(url);
+ if (videoList.currentItem.isTemp) removeElementItem(url);
videoList.skipItem();
updateCounters();
if (videoList.length == 0) return;
@@ -332,15 +332,14 @@ class Player {
}
public function setItems(list:Array<VideoItem>, ?pos:Int):Void {
- final currentUrl = videoList.pos >= videoList.length ? "" : videoList.getCurrentItem()
- .url;
+ final currentUrl = videoList.pos >= videoList.length ? "" : videoList.currentItem.url;
clearItems();
if (list.length == 0) return;
for (video in list) {
addVideoItem(video, true);
}
if (pos != null) videoList.setPos(pos);
- if (currentUrl != videoList.getCurrentItem().url) setVideo(videoList.pos);
+ if (currentUrl != videoList.currentItem.url) setVideo(videoList.pos);
else addActiveLabel(videoList.pos);
}
@@ -401,7 +400,7 @@ class Player {
public function getDuration():Float {
if (videoList.pos >= videoList.length) return 0;
- return videoList.getCurrentItem().duration;
+ return videoList.currentItem.duration;
}
public function isVideoLoaded():Bool {
@@ -451,7 +450,7 @@ class Player {
}
public function skipAd():Void {
- final item = videoList.getCurrentItem() ?? return;
+ final item = videoList.currentItem ?? return;
if (!youtube.isSupportedLink(item.url)) return;
final id = youtube.extractVideoId(item.url);
final url = 'https://sponsor.ajay.app/api/skipSegments?videoID=$id';
diff --git a/src/server/HttpServer.hx b/src/server/HttpServer.hx
index 4bf16c4..acb8955 100644
--- a/src/server/HttpServer.hx
+++ b/src/server/HttpServer.hx
@@ -21,13 +21,16 @@ class HttpServer {
"css" => "text/css",
"json" => "application/json",
"png" => "image/png",
- "jpg" => "image/jpg",
+ "jpg" => "image/jpeg",
+ "jpeg" => "image/jpeg",
"gif" => "image/gif",
+ "webp" => "image/webp",
"svg" => "image/svg+xml",
"ico" => "image/x-icon",
"wav" => "audio/wav",
"mp3" => "audio/mpeg",
"mp4" => "video/mp4",
+ "webm" => "video/webm",
"woff" => "application/font-woff",
"ttf" => "application/font-ttf",
"eot" => "application/vnd.ms-fontobject",
@@ -152,7 +155,7 @@ class HttpServer {
}
static function isMediaExtension(ext:String):Bool {
- return ext == "mp4" || ext == "mp3" || ext == "wav";
+ return ext == "mp4" || ext == "webm" || ext == "mp3" || ext == "wav";
}
static final matchLang = ~/^[A-z]+/;
diff --git a/src/server/Main.hx b/src/server/Main.hx
index ab48592..0da88e7 100644
--- a/src/server/Main.hx
+++ b/src/server/Main.hx
@@ -2,9 +2,11 @@ package server;
import Client.ClientData;
import Types.Config;
+import Types.FlashbackItem;
import Types.Message;
import Types.Permission;
import Types.UserList;
+import Types.VideoItem;
import Types.WsEvent;
import haxe.Json;
import haxe.Timer;
@@ -618,10 +620,13 @@ class Main {
if (!checkPermission(client, RemoveVideoPerm)) return;
if (videoList.length == 0) return;
final url = data.removeVideo.url;
- var index = videoList.findIndex(item -> item.url == url);
+ final index = videoList.findIndex(item -> item.url == url);
if (index == -1) return;
- final isCurrent = videoList.getCurrentItem().url == url;
+ final isCurrent = videoList.currentItem.url == url;
+ if (isCurrent && videoTimer.getTime() > FLASHBACK_DIST) {
+ saveFlashbackTime(videoList.currentItem);
+ }
videoList.removeItem(index);
if (isCurrent && videoList.length > 0) {
broadcast(data);
@@ -638,7 +643,7 @@ class Main {
if (videoList.length == 0) return;
if (!client.isLeader) return;
if (Math.abs(data.pause.time - videoTimer.getTime()) > FLASHBACK_DIST) {
- saveFlashbackTime();
+ saveFlashbackTime(videoList.currentItem);
}
videoTimer.setTime(data.pause.time);
videoTimer.pause();
@@ -651,7 +656,7 @@ class Main {
if (videoList.length == 0) return;
if (!client.isLeader) return;
if (Math.abs(data.play.time - videoTimer.getTime()) > FLASHBACK_DIST) {
- saveFlashbackTime();
+ saveFlashbackTime(videoList.currentItem);
}
videoTimer.setTime(data.play.time);
videoTimer.play();
@@ -662,11 +667,11 @@ class Main {
case GetTime:
if (videoList.length == 0) return;
- final maxTime = videoList.getCurrentItem().duration - 0.01;
+ final maxTime = videoList.currentItem.duration - 0.01;
if (videoTimer.getTime() > maxTime) {
videoTimer.pause();
videoTimer.setTime(maxTime);
- final skipUrl = videoList.getCurrentItem().url;
+ final skipUrl = videoList.currentItem.url;
Timer.delay(() -> {
skipVideo({
type: SkipVideo,
@@ -694,7 +699,7 @@ class Main {
if (videoList.length == 0) return;
if (!client.isLeader) return;
if (Math.abs(data.setTime.time - videoTimer.getTime()) > FLASHBACK_DIST) {
- saveFlashbackTime();
+ saveFlashbackTime(videoList.currentItem);
}
videoTimer.setTime(data.setTime.time);
broadcastExcept(client, {
@@ -716,7 +721,7 @@ class Main {
if (videoList.length == 0) return;
data.rewind.time += videoTimer.getTime();
if (data.rewind.time < 0) data.rewind.time = 0;
- saveFlashbackTime();
+ saveFlashbackTime(videoList.currentItem);
videoTimer.setTime(data.rewind.time);
broadcast({
type: data.type,
@@ -726,7 +731,7 @@ class Main {
case Flashback:
if (!checkPermission(client, RewindPerm)) return;
if (videoList.length == 0) return;
- loadFlashbackTime();
+ loadFlashbackTime(videoList.currentItem);
broadcast({
type: Rewind,
rewind: {
@@ -762,6 +767,9 @@ class Main {
case PlayItem:
if (!checkPermission(client, ChangeOrderPerm)) return;
+ if (videoTimer.getTime() > FLASHBACK_DIST) {
+ saveFlashbackTime(videoList.currentItem);
+ }
videoList.setPos(data.playItem.pos);
data.playItem.pos = videoList.pos;
restartWaitTimer();
@@ -790,6 +798,9 @@ class Main {
case ClearPlaylist:
if (isPlaylistLockedFor(client)) return;
if (!checkPermission(client, RemoveVideoPerm)) return;
+ if (videoTimer.getTime() > FLASHBACK_DIST) {
+ saveFlashbackTime(videoList.currentItem);
+ }
videoTimer.stop();
videoList.clear();
broadcast(data);
@@ -902,8 +913,13 @@ class Main {
function skipVideo(data:WsEvent):Void {
if (videoList.length == 0) return;
- final item = videoList.getCurrentItem();
+ final item = videoList.currentItem;
if (item.url != data.skipVideo.url) return;
+ final dur = videoList.currentItem.duration;
+ if (videoTimer.getTime() > FLASHBACK_DIST
+ && videoTimer.getTime() < dur - FLASHBACK_DIST) {
+ saveFlashbackTime(videoList.currentItem);
+ }
videoList.skipItem();
if (videoList.length > 0) restartWaitTimer();
broadcast(data);
@@ -959,7 +975,6 @@ class Main {
var loadedClientsCount = 0;
function restartWaitTimer():Void {
- if (videoTimer.getTime() > FLASHBACK_DIST) saveFlashbackTime();
videoTimer.stop();
if (waitVideoStart != null) waitVideoStart.stop();
waitVideoStart = Timer.delay(startVideoPlayback, VIDEO_START_MAX_DELAY);
@@ -979,18 +994,48 @@ class Main {
videoTimer.start();
}
- var flashbackTime = 0.0;
-
- function saveFlashbackTime() {
+ function saveFlashbackTime(item:VideoItem):Void {
+ final url = item.url;
+ final duration = item.duration;
final time = videoTimer.getTime();
+ final flashbackTime = findFlashbackTime(url, duration);
if (Math.abs(flashbackTime - time) < FLASHBACK_DIST) return;
- flashbackTime = time;
+ addRecentFlashback(url, duration, time);
}
- function loadFlashbackTime() {
+ function loadFlashbackTime(item:VideoItem):Void {
+ final url = item.url;
+ final duration = item.duration;
final time = videoTimer.getTime();
+ final flashbackTime = findFlashbackTime(url, duration);
videoTimer.setTime(flashbackTime);
- flashbackTime = time;
+ addRecentFlashback(url, duration, time);
+ }
+
+ function findFlashbackTime(url:String, duration:Float):Float {
+ return findFlashbackItem(url, duration)?.time ?? 0.0;
+ }
+
+ final flashbackTimes:Array<FlashbackItem> = [];
+
+ function findFlashbackItem(url:String, ?duration:Float):Null<FlashbackItem> {
+ var item = flashbackTimes.find(item -> item.url == url);
+ // if there is no url match, find recent flashback item with same duration
+ if (duration != null && item == null) {
+ item = flashbackTimes.find(item -> item.duration == duration);
+ }
+ return item;
+ }
+
+ function addRecentFlashback(url:String, duration:Float, time:Float):Void {
+ flashbackTimes.remove(findFlashbackItem(url));
+ flashbackTimes.unshift({
+ url: url,
+ duration: duration,
+ time: time
+ });
+ final length = flashbackTimes.count();
+ if (length > 10) flashbackTimes.pop();
}
function isPlaylistLockedFor(client:Client):Bool {
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage