mirror of
https://github.com/radio95-rnt/RadioPlayer.git
synced 2026-07-31 00:09:16 +02:00
some ui changes
This commit is contained in:
+1
-1
@@ -71,7 +71,7 @@ async def ws_handler(websocket: ServerConnection, shared_data: dict, imc_q: mult
|
|||||||
await broadcast({"data": result, "event": "toplay"})
|
await broadcast({"data": result, "event": "toplay"})
|
||||||
elif action == "remove_toplay" or action == "toggle_official_toplay":
|
elif action == "remove_toplay" or action == "toggle_official_toplay":
|
||||||
idx = msg.get("indexes")
|
idx = msg.get("indexes")
|
||||||
if not isinstance(songs, list): await websocket.send(json.dumps({"error": "songs must be a list"}))
|
if not isinstance(idx, list): await websocket.send(json.dumps({"error": "indexes must be a list"}))
|
||||||
else:
|
else:
|
||||||
imc_q.put({"name": "activemod", "data": {"action": action, "indexes": idx}})
|
imc_q.put({"name": "activemod", "data": {"action": action, "indexes": idx}})
|
||||||
result = await get_imc("activemod", {"action": "get_toplay"})
|
result = await get_imc("activemod", {"action": "get_toplay"})
|
||||||
|
|||||||
@@ -193,7 +193,6 @@
|
|||||||
<button id="skpn-inc" class="btn" style="padding:4px 10px;border:none">+</button>
|
<button id="skpn-inc" class="btn" style="padding:4px 10px;border:none">+</button>
|
||||||
</div>
|
</div>
|
||||||
<button id="jingle-btn" class="btn">🕭 Jingle</button>
|
<button id="jingle-btn" class="btn">🕭 Jingle</button>
|
||||||
<button id="skipidx-btn" class="btn">⏭+ Skip in playlist</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -251,10 +250,6 @@
|
|||||||
<div class="collapsible-content listbox" id="subdir-box"></div>
|
<div class="collapsible-content listbox" id="subdir-box"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin-top:8px; display: flex; gap: 8px;">
|
|
||||||
<button id="add-to-queue-btn" class="btn primary" style="flex: 1;">Add to Bottom ▼</button>
|
|
||||||
<button id="add-to-queue2-btn" class="btn primary" style="flex: 1;">Add to Top ▲</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
+18
-107
@@ -4,10 +4,8 @@ let playlist = [];
|
|||||||
let queue = [];
|
let queue = [];
|
||||||
let currentTrackPath = "";
|
let currentTrackPath = "";
|
||||||
let currentTrackIndex = 0;
|
let currentTrackIndex = 0;
|
||||||
let selectedPlaylistPath = null;
|
|
||||||
let selectedPlaylistIndex = null;
|
let selectedPlaylistIndex = null;
|
||||||
let selectedDir = null;
|
let selectedDir = null;
|
||||||
let selectedSubFile = null;
|
|
||||||
let basePath = "";
|
let basePath = "";
|
||||||
let subBasePath = "";
|
let subBasePath = "";
|
||||||
let skipCount = 0;
|
let skipCount = 0;
|
||||||
@@ -260,34 +258,26 @@ function updateDirs(payload) {
|
|||||||
box.innerHTML = "";
|
box.innerHTML = "";
|
||||||
basePath = payload.base || "";
|
basePath = payload.base || "";
|
||||||
|
|
||||||
const addItem = (name, onClick) => {
|
const addItem = (name, onClick, onContext) => {
|
||||||
const node = document.createElement("div");
|
const node = document.createElement("div");
|
||||||
node.className = "item";
|
node.className = "item";
|
||||||
node.textContent = name;
|
node.textContent = name;
|
||||||
node.addEventListener("click", () => onClick(node));
|
node.addEventListener("click", (e) => onClick(node, e));
|
||||||
|
if(onContext !== undefined) node.addEventListener("contextmenu", () => onContext(node, e));
|
||||||
box.appendChild(node);
|
box.appendChild(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
(payload.dirs || []).sort().forEach(name => {
|
(payload.dirs || []).sort().forEach(name => {
|
||||||
if (!name.startsWith(".")) addItem(name, node => onDirClicked(name, node));
|
if (!name.startsWith(".")) addItem(name, (node, e) => onDirClicked(name, node));
|
||||||
});
|
});
|
||||||
|
|
||||||
(payload.files || []).sort().forEach(name => {
|
(payload.files || []).sort().forEach(name => {
|
||||||
if (!name.startsWith(".")) {
|
if (!name.startsWith(".")) {
|
||||||
addItem(name, node => {
|
addItem(name, () => {
|
||||||
if (node.classList.contains("selected")) {
|
wsSend({ action: "add_to_toplay", songs: [basePath.replace(/\/$/, "") + "/" + name], top: false })
|
||||||
node.classList.remove("selected");
|
}, (node, e) => {
|
||||||
selectedDir = null;
|
e.preventDefault()
|
||||||
selectedSubFile = null;
|
wsSend({ action: "add_to_toplay", songs: [basePath.replace(/\/$/, "") + "/" + name], top: true })
|
||||||
return;
|
|
||||||
}
|
|
||||||
clearListSelections("playlist-ul", "subdir-box");
|
|
||||||
Array.from(box.children).forEach(c => c.classList.remove("selected"));
|
|
||||||
node.classList.add("selected");
|
|
||||||
node.dataset.type = "file";
|
|
||||||
selectedDir = null;
|
|
||||||
selectedSubFile = null;
|
|
||||||
document.getElementById("subdir-box").innerHTML = "";
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -297,14 +287,12 @@ function onDirClicked(name, node) {
|
|||||||
if (node.classList.contains("selected")) {
|
if (node.classList.contains("selected")) {
|
||||||
node.classList.remove("selected");
|
node.classList.remove("selected");
|
||||||
selectedDir = null;
|
selectedDir = null;
|
||||||
selectedSubFile = null;
|
|
||||||
document.getElementById("subdir-box").innerHTML = "";
|
document.getElementById("subdir-box").innerHTML = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clearListSelections("dirs-box", "playlist-ul");
|
clearListSelections("dirs-box", "playlist-ul");
|
||||||
node.classList.add("selected");
|
node.classList.add("selected");
|
||||||
selectedDir = name;
|
selectedDir = name;
|
||||||
selectedSubFile = null;
|
|
||||||
wsSend({ action: "request_dir", what: selectedDir });
|
wsSend({ action: "request_dir", what: selectedDir });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,91 +307,26 @@ function applySubdir(payload) {
|
|||||||
node.className = "item";
|
node.className = "item";
|
||||||
node.textContent = f;
|
node.textContent = f;
|
||||||
node.addEventListener("click", () => {
|
node.addEventListener("click", () => {
|
||||||
if (node.classList.contains("selected")) {
|
wsSend({ action: "add_to_toplay", songs: [subBasePath.replace(/\/$/, "") + "/" + f], top: false });
|
||||||
node.classList.remove("selected");
|
});
|
||||||
selectedSubFile = null;
|
node.addEventListener("contextmenu", (e) => {
|
||||||
return;
|
e.preventDefault()
|
||||||
}
|
wsSend({ action: "add_to_toplay", songs: [subBasePath.replace(/\/$/, "") + "/" + f], top: true });
|
||||||
clearListSelections("subdir-box", "playlist-ul");
|
|
||||||
Array.from(document.getElementById("dirs-box").children).forEach(c => c.classList.remove("selected"));
|
|
||||||
|
|
||||||
// Re-select the parent dir node
|
|
||||||
Array.from(document.getElementById("dirs-box").children).forEach(c => {
|
|
||||||
if (c.textContent === selectedDir) c.classList.add("selected");
|
|
||||||
});
|
|
||||||
|
|
||||||
node.classList.add("selected");
|
|
||||||
selectedSubFile = f;
|
|
||||||
});
|
});
|
||||||
box.appendChild(node);
|
box.appendChild(node);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectPlaylistItem(i, el) {
|
function selectPlaylistItem(i, el) {
|
||||||
const path = el.dataset.path;
|
const action = skippedIndices.includes(i)
|
||||||
if (el.classList.contains("selected")) {
|
? { action: "skipi", remove: i }
|
||||||
el.classList.remove("selected");
|
: { action: "skipi", add: i };
|
||||||
selectedPlaylistPath = null;
|
wsSend(action);
|
||||||
updateControls();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
clearListSelections("playlist-ul", "dirs-box", "subdir-box");
|
|
||||||
el.classList.add("selected");
|
|
||||||
selectedPlaylistPath = path;
|
|
||||||
selectedPlaylistIndex = i;
|
|
||||||
updateControls();
|
updateControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSelectedFileToQueue(top) {
|
|
||||||
let fullPath = null;
|
|
||||||
|
|
||||||
if (selectedPlaylistPath != null) {
|
|
||||||
const selected = playlist.find(t => t.path === selectedPlaylistPath);
|
|
||||||
if (!selected) return false;
|
|
||||||
const path = (selected.official ? "" : "!") + selected.path;
|
|
||||||
wsSend({ action: "add_to_toplay", songs: [path], top });
|
|
||||||
clearListSelections("playlist-ul");
|
|
||||||
selectedPlaylistPath = null;
|
|
||||||
selectedPlaylistIndex = null;
|
|
||||||
updateControls();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (selectedSubFile && selectedDir) {
|
|
||||||
fullPath = subBasePath.replace(/\/$/, "") + "/" + selectedSubFile;
|
|
||||||
} else {
|
|
||||||
const selectedFileEl = Array.from(document.getElementById("dirs-box").children).find(el => el.classList.contains("selected") && el.dataset.type === "file");
|
|
||||||
if (selectedFileEl) {
|
|
||||||
fullPath = basePath.replace(/\/$/, "") + "/" + selectedFileEl.textContent;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fullPath) {
|
|
||||||
wsSend({ action: "add_to_toplay", songs: [fullPath], top });
|
|
||||||
// Dir/subdir selections are intentionally preserved here
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateControls() {
|
function updateControls() {
|
||||||
document.getElementById("clear-btn").disabled = queue.length === 0;
|
document.getElementById("clear-btn").disabled = queue.length === 0;
|
||||||
|
|
||||||
const btn = document.getElementById("skipidx-btn");
|
|
||||||
if (selectedPlaylistIndex == null) {
|
|
||||||
btn.textContent = "⏭+ Skip in playlist";
|
|
||||||
btn.disabled = true;
|
|
||||||
btn.classList.remove("activated");
|
|
||||||
} else if (skippedIndices.includes(selectedPlaylistIndex)) {
|
|
||||||
btn.textContent = "✓ Unskip in playlist";
|
|
||||||
btn.disabled = false;
|
|
||||||
btn.classList.add("activated");
|
|
||||||
} else {
|
|
||||||
btn.textContent = "⏭+ Skip in playlist";
|
|
||||||
btn.disabled = false;
|
|
||||||
btn.classList.remove("activated");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById("skip-btn").addEventListener("click", () => wsSend({ action: "skip" }));
|
document.getElementById("skip-btn").addEventListener("click", () => wsSend({ action: "skip" }));
|
||||||
@@ -416,26 +339,14 @@ document.getElementById("jingle-btn").addEventListener("contextmenu", e => {
|
|||||||
wsSend({ action: "jingle", top: true });
|
wsSend({ action: "jingle", top: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("skipidx-btn").addEventListener("click", () => {
|
|
||||||
if (selectedPlaylistIndex == null) return;
|
|
||||||
const action = skippedIndices.includes(selectedPlaylistIndex)
|
|
||||||
? { action: "skipi", remove: selectedPlaylistIndex }
|
|
||||||
: { action: "skipi", add: selectedPlaylistIndex };
|
|
||||||
wsSend(action);
|
|
||||||
});
|
|
||||||
|
|
||||||
document.getElementById("queue-title").addEventListener("click", () => toggleSection("section-queue"));
|
document.getElementById("queue-title").addEventListener("click", () => toggleSection("section-queue"));
|
||||||
document.getElementById("clear-btn").addEventListener("click", e => {
|
document.getElementById("clear-btn").addEventListener("click", e => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
wsSend({ action: "clear_toplay" });
|
wsSend({ action: "clear_toplay" });
|
||||||
});
|
});
|
||||||
|
|
||||||
document.getElementById("add-to-queue-btn").addEventListener("click", () => addSelectedFileToQueue(false));
|
|
||||||
document.getElementById("add-to-queue2-btn").addEventListener("click", () => addSelectedFileToQueue(true));
|
|
||||||
|
|
||||||
document.addEventListener("keydown", e => {
|
document.addEventListener("keydown", e => {
|
||||||
if (e.target.tagName === "INPUT") return;
|
if (e.target.tagName === "INPUT") return;
|
||||||
if (e.key === "Enter" && addSelectedFileToQueue(e.shiftKey)) e.preventDefault();
|
|
||||||
else if (e.key === "s") wsSend({ action: "skip" });
|
else if (e.key === "s") wsSend({ action: "skip" });
|
||||||
else if (e.key === "n") wsSend({ action: "skipc", add: 1 });
|
else if (e.key === "n") wsSend({ action: "skipc", add: 1 });
|
||||||
else if (e.key === "m") wsSend({ action: "skipc", remove: -1 });
|
else if (e.key === "m") wsSend({ action: "skipc", remove: -1 });
|
||||||
|
|||||||
Reference in New Issue
Block a user