From f205dd41f9f90555111a77df9c74b6f207b11cb6 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Sat, 23 May 2026 17:17:44 +0200 Subject: [PATCH] toggle official and remove are index addressed --- modules/active_modifier.py | 21 +++++++++++++++++---- modules/web.py | 12 +++++++++--- modules/web/web.js | 10 ++++++++-- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/modules/active_modifier.py b/modules/active_modifier.py index 84a99ec..5cf025c 100644 --- a/modules/active_modifier.py +++ b/modules/active_modifier.py @@ -157,11 +157,24 @@ class Module(ActiveModifier): with open(TOPLAY, "w") as f: f.write("") return {"status": "ok", "data": []} elif data.get("action") == "remove_toplay": - targets = data.get("songs", []) + targets = data.get("indexes", []) with self.file_lock: - with open(TOPLAY, "r") as f: - lines = [l.strip() for l in f.readlines() if l.strip()] - lines = [l for l in lines if l not in targets and l not in targets] + with open(TOPLAY, "r") as f: lines = [l.strip() for l in f.readlines() if l.strip()] + if isinstance(targets, list): + target_set = set(targets) + lines = [l for i, l in enumerate(lines) if i not in target_set] + with open(TOPLAY, "w") as f: f.write('\n'.join(lines) + "\n") + return {"status": "ok", "data": lines} + elif data.get("action") == "toggle_official_toplay": + targets = data.get("indexes", []) + with self.file_lock: + with open(TOPLAY, "r") as f: lines = [l.strip() for l in f.readlines() if l.strip()] + if isinstance(targets, list): + target_set = set(targets) + for i in target_set: + if 0 <= i < len(lines): + if lines[i].startswith("!"): lines[i] = lines[i][1:] + else: lines[i] = "!" + lines[i] with open(TOPLAY, "w") as f: f.write('\n'.join(lines) + "\n") return {"status": "ok", "data": lines} elif data.get("action") == "skipc": diff --git a/modules/web.py b/modules/web.py index f3f005a..ab89a75 100644 --- a/modules/web.py +++ b/modules/web.py @@ -60,7 +60,7 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult if action == "skip": imc_q.put({"name": "procman", "data": {"op": 2}}) await websocket.send(json.dumps({"event": "skip"})) - elif action == "add_to_toplay" or action == "remove_toplay": + elif action == "add_to_toplay": songs = msg.get("songs") at_top = msg.get("top", False) if not isinstance(songs, list): await websocket.send(json.dumps({"error": "songs must be a list"})) @@ -69,6 +69,14 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult result = await get_imc("activemod", {"action": "get_toplay"}) if result is not None: await broadcast({"data": result, "event": "toplay"}) + elif action == "remove_toplay" or action == "toggle_official_toplay": + idx = msg.get("indexes") + if not isinstance(songs, list): await websocket.send(json.dumps({"error": "songs must be a list"})) + else: + imc_q.put({"name": "activemod", "data": {"action": action, "indexes": idx}}) + result = await get_imc("activemod", {"action": "get_toplay"}) + if result is not None: + await broadcast({"data": result, "event": "toplay"}) elif action == "get_toplay": result = await get_imc("activemod", {"action": "get_toplay"}) if result is None: await websocket.send(json.dumps({"error": "timeout", "code": 504})) @@ -142,7 +150,6 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult else: locks[lid] = websocket await broadcast({"event": "lock", "id": lid, "data": True}) - elif action == "unlock": lid = msg.get("id") if lid is None: @@ -153,7 +160,6 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult else: locks[lid] = None await broadcast({"event": "lock", "id": lid, "data": False}) - else: await websocket.send(json.dumps({"event": "error", "error": "unknown action"})) finally: # release every lock this client held on disconnect diff --git a/modules/web/web.js b/modules/web/web.js index 891010a..42d7837 100644 --- a/modules/web/web.js +++ b/modules/web/web.js @@ -227,9 +227,10 @@ function renderPlaylist() { function renderQueue() { const ul = document.getElementById("queue-ul"); ul.innerHTML = ""; + var i = 0; queue.forEach(path => { const li = document.createElement("li"); - li.dataset.line = path; + li.dataset.idx = i++; var c = path.replace(basePath, ""); if(c.startsWith("!")) c = "(unofficial) " + c.slice(2) @@ -241,9 +242,14 @@ function renderQueue() { } li.addEventListener("click", () => { - wsSend({ action: "remove_toplay", songs: [li.dataset.line] }); + wsSend({ action: "remove_toplay", indexes: [li.dataset.idx] }); renderAll(); }); + li.addEventListener("contextmenu", e => { + e.preventDefault(); + wsSend({ action: "toggle_official_toplay", indexes: [li.dataset.idx] }); + renderAll(); + }) ul.appendChild(li); }); updateControls();