From 04eb44d685ba677a444b73c7cfc2427d2740497f Mon Sep 17 00:00:00 2001 From: Pinapelz Date: Thu, 2 Jul 2026 22:17:17 -0700 Subject: implement better leader, queue, and upload management - Majority vote skip management (Admins and the original video queuer overrides this behavior) - Leader request now requires the current leader to give up the role (via `/giveup `) - Overhauled default CSS and improved mobile view - Caching and uploading files is limited to Admin users only Signed-off-by: Pinapelz --- src/client/Buttons.hx | 6 +++++- src/client/FileUploader.hx | 6 ++++++ src/client/Main.hx | 20 +++++++++++++++++++- src/client/Player.hx | 4 +++- 4 files changed, 33 insertions(+), 3 deletions(-) (limited to 'src/client') diff --git a/src/client/Buttons.hx b/src/client/Buttons.hx index 56f28d5..f3a2474 100644 --- a/src/client/Buttons.hx +++ b/src/client/Buttons.hx @@ -228,7 +228,7 @@ class Buttons { getEl("#voiceoverblock").style.display = (url.length > 0 && isSingle) ? "" : "none"; final isExternal = main.isExternalVideoUrl(url); - final showCache = isSingle && isExternal + final showCache = main.isAdmin() && isSingle && isExternal && main.playersCacheSupport.contains(playerType); checkboxCache.parentElement.style.display = showCache ? "" : "none"; checkboxCache.checked = settings.checkedCache.contains(playerType); @@ -258,6 +258,10 @@ class Buttons { } getEl("#mediaurl-upload").onclick = e -> { + if (!main.isAdmin()) { + main.serverMessage("Only admins may upload files.", true, false); + return; + } Utils.browseJsFile(file -> { final uploader = new FileUploader(main); uploader.uploadFile(file); diff --git a/src/client/FileUploader.hx b/src/client/FileUploader.hx index 60cc1d2..888dda6 100644 --- a/src/client/FileUploader.hx +++ b/src/client/FileUploader.hx @@ -18,6 +18,10 @@ class FileUploader { } public function uploadFile(file:File):Void { + if (!main.isAdmin()) { + main.serverMessage("Only admins may upload files.", true, false); + return; + } var name = ~/[?#%\/\\]/g.replace(file.name, "").trim(); if (name.length == 0) name = "video"; name = (window : Dynamic).encodeURIComponent(name); @@ -39,6 +43,7 @@ class FileUploader { final request = new XMLHttpRequest(); request.open("POST", "/upload", true); request.setRequestHeader("content-name", name); + request.setRequestHeader("x-client-uuid", main.settings.uuid ?? ""); request.upload.onprogress = (event:ProgressEvent) -> { var ratio = 0.0; @@ -81,6 +86,7 @@ class FileUploader { method: "POST", headers: { "content-name": name, + "x-client-uuid": main.settings.uuid ?? "", }, body: lastChunk, }); diff --git a/src/client/Main.hx b/src/client/Main.hx index 42aec3e..bea6b6b 100644 --- a/src/client/Main.hx +++ b/src/client/Main.hx @@ -356,7 +356,8 @@ class Main { final checkboxTemp:InputElement = getEl("#addfromurl .add-temp"); final isTemp = checkboxTemp.checked; final checkboxCache:InputElement = getEl("#cache-on-server"); - final doCache = checkboxCache.checked + final doCache = isAdmin() + && checkboxCache.checked && checkboxCache.parentElement.style.display != "none"; final url = mediaUrl.value; final subs = subsUrl.value; @@ -905,6 +906,13 @@ class Main { final adminMenu = getEl("#adminMenu"); if (isAdmin()) adminMenu.style.display = ""; else adminMenu.style.display = "none"; + + final uploadBtn = getEl("#mediaurl-upload"); + uploadBtn.style.display = isAdmin() ? "" : "none"; + + final checkboxCache:InputElement = getEl("#cache-on-server"); + checkboxCache.checked = isAdmin() && checkboxCache.checked; + checkboxCache.parentElement.style.display = isAdmin() ? "" : "none"; } public function guestLogin(name:String):Void { @@ -1377,6 +1385,16 @@ class Main { case "clear": send({type: ClearChat}); return true; + case "giveup": + mergeRedundantArgs(args, 0, 1); + final name = args[0] ?? ""; + send({ + type: SetLeader, + setLeader: { + clientName: name + } + }); + return true; case "flashback", "fb": send({type: Flashback}); return false; diff --git a/src/client/Player.hx b/src/client/Player.hx index 10c4351..68b1a4a 100644 --- a/src/client/Player.hx +++ b/src/client/Player.hx @@ -415,11 +415,13 @@ class Player { public function addVideoItem(item:VideoItem, atEnd:Bool):Void { final url = item.url.htmlEscape(true); final duration = item.playerType == IframeType ? "" : duration(item.duration); + final author = item.author.htmlEscape(); final itemEl = Utils.nodeFromString( - '
  • + '
  • $duration

    ${item.title.htmlEscape()}

    + ${Lang.get("addedBy")}: $author
    -- cgit v1.2.3