mirror of
https://github.com/radio95-rnt/RadioPlayer.git
synced 2026-07-30 15:59:16 +02:00
some ui stuff plus fix bug
This commit is contained in:
@@ -26,7 +26,8 @@ class Module(ActiveModifier):
|
|||||||
self.skip_indexes = set()
|
self.skip_indexes = set()
|
||||||
def on_new_playlist(self, playlist: list[Track], global_args: dict[str, str]):
|
def on_new_playlist(self, playlist: list[Track], global_args: dict[str, str]):
|
||||||
self.playlist = playlist
|
self.playlist = playlist
|
||||||
self.originals = []
|
self.originals.clear()
|
||||||
|
self.skip_indexes.clear()
|
||||||
self.crossfade = float(global_args.get("crossfade", DEFAULT_CROSSFADE))
|
self.crossfade = float(global_args.get("crossfade", DEFAULT_CROSSFADE))
|
||||||
|
|
||||||
if not self._imc: return
|
if not self._imc: return
|
||||||
|
|||||||
+8
-14
@@ -42,7 +42,7 @@
|
|||||||
.btn.primary:hover { background:linear-gradient(90deg, #3399ee, #5bbaff); }
|
.btn.primary:hover { background:linear-gradient(90deg, #3399ee, #5bbaff); }
|
||||||
|
|
||||||
ul.playlist{list-style:none; padding:6px; margin:0; font-family: "Consolas",monospace; font-size:13px;}
|
ul.playlist{list-style:none; padding:6px; margin:0; font-family: "Consolas",monospace; font-size:13px;}
|
||||||
ul.playlist li{ padding:4px 6px; border-radius:6px; display:flex; justify-content:space-between; gap:8px; transition: background-color 0.2s ease, transform 0.15s ease; }
|
ul.playlist li{ padding:4px 6px; border-radius:6px; display:flex; justify-content:space -between; gap:8px; transition: background-color 0.2s ease, transform 0.15s ease; }
|
||||||
ul.playlist li:hover{ background:rgba(255,255,255,0.04); }
|
ul.playlist li:hover{ background:rgba(255,255,255,0.04); }
|
||||||
ul.playlist li.current{background:rgba(62,166,255,0.08)}
|
ul.playlist li.current{background:rgba(62,166,255,0.08)}
|
||||||
ul.playlist li.selected{background:rgba(62, 165, 255, 0.305)}
|
ul.playlist li.selected{background:rgba(62, 165, 255, 0.305)}
|
||||||
@@ -52,13 +52,11 @@
|
|||||||
|
|
||||||
.listbox{
|
.listbox{
|
||||||
height:100%;
|
height:100%;
|
||||||
min-height:100px;
|
|
||||||
overflow:auto;
|
overflow:auto;
|
||||||
border-radius:6px;
|
border-radius:6px;
|
||||||
background:var(--card);
|
background:var(--card);
|
||||||
padding:8px;
|
padding:8px;
|
||||||
font-size:14px;
|
font-size:14px;
|
||||||
scrollbar-width: none;
|
|
||||||
}
|
}
|
||||||
.listbox::-webkit-scrollbar { display: none; }
|
.listbox::-webkit-scrollbar { display: none; }
|
||||||
|
|
||||||
@@ -66,14 +64,13 @@
|
|||||||
.listbox div.item:hover{background:rgba(255,255,255,0.04); cursor:pointer}
|
.listbox div.item:hover{background:rgba(255,255,255,0.04); cursor:pointer}
|
||||||
.listbox div.item.selected{background:rgba(62, 165, 255, 0.305)}
|
.listbox div.item.selected{background:rgba(62, 165, 255, 0.305)}
|
||||||
|
|
||||||
#section-playlist { flex: 2 1; }
|
#section-playlist { flex: 2 1; overflow: hidden;}
|
||||||
#section-queue { flex: 1; display: flex; flex-direction: column; }
|
#section-queue { flex: 1; display: flex; flex-direction: column; }
|
||||||
#section-queue .collapsible-content { flex-grow: 1; }
|
#section-queue .collapsible-content { flex-grow: 1; }
|
||||||
#section-queue.collapsed .collapsible-content { display: none; }
|
#section-queue.collapsed .collapsible-content { display: none; }
|
||||||
#section-playlist.collapsed + #section-queue { flex: 1 1 auto !important; }
|
#section-playlist.collapsed + #section-queue { flex: 1 1 auto !important; }
|
||||||
|
|
||||||
.small{font-size:12px; color:var(--muted)}
|
.small{font-size:12px; color:var(--muted)}
|
||||||
.muted{color:var(--muted); font-size:13px}
|
|
||||||
.footer{display:flex; justify-content:space-between; gap:5px; align-items:center; margin-top:8px; background:var(--panel); border-radius:10px; padding:8px; box-shadow: 0 8px 18px rgba(2,8,16,0.6);}
|
.footer{display:flex; justify-content:space-between; gap:5px; align-items:center; margin-top:8px; background:var(--panel); border-radius:10px; padding:8px; box-shadow: 0 8px 18px rgba(2,8,16,0.6);}
|
||||||
.directory-grid {
|
.directory-grid {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -114,7 +111,7 @@
|
|||||||
#whep-section .collapsible-content {
|
#whep-section .collapsible-content {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
transition: max-height 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
transition: max-height 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
}
|
}
|
||||||
#whep-section.collapsed .collapsible-content { max-height: 0; }
|
#whep-section.collapsed .collapsible-content { max-height: 0; }
|
||||||
#whep-section.collapsed .frame-title::after { transform: rotate(90deg); }
|
#whep-section.collapsed .frame-title::after { transform: rotate(90deg); }
|
||||||
@@ -164,7 +161,6 @@
|
|||||||
.layout{flex-direction: column; height: auto}
|
.layout{flex-direction: column; height: auto}
|
||||||
.left{min-width:auto}
|
.left{min-width:auto}
|
||||||
.directory-grid {grid-template-columns: 1fr; height: auto; overflow: visible}
|
.directory-grid {grid-template-columns: 1fr; height: auto; overflow: visible}
|
||||||
.listbox {min-height: 200px}
|
|
||||||
button, .btn {padding: 10px 14px}
|
button, .btn {padding: 10px 14px}
|
||||||
.panel.right { height: auto; }
|
.panel.right { height: auto; }
|
||||||
#section-playlist, #section-queue { flex: 1 1 auto; }
|
#section-playlist, #section-queue { flex: 1 1 auto; }
|
||||||
@@ -176,12 +172,13 @@
|
|||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div style="display:flex;align-items:center;justify-content:space-between;">
|
<div style="display:flex;align-items:center;justify-content:space-between;">
|
||||||
|
<div>
|
||||||
<h1>RadioPlayer status</h1>
|
<h1>RadioPlayer status</h1>
|
||||||
<noscript><h1>NO SCRIPTING</h1></noscript>
|
<noscript><h1> - NO SCRIPTING - </h1></noscript>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="layout">
|
<div class="layout">
|
||||||
<!-- Left Panel -->
|
|
||||||
<div class="panel left">
|
<div class="panel left">
|
||||||
<div class="now">
|
<div class="now">
|
||||||
<div class="frame-title-nc" style="cursor: default; pointer-events: none;">Now Playing</div>
|
<div class="frame-title-nc" style="cursor: default; pointer-events: none;">Now Playing</div>
|
||||||
@@ -211,12 +208,10 @@
|
|||||||
<div style="margin-top:12px; display:flex; flex-direction: column; flex-grow: 1; overflow: hidden; gap: 12px;">
|
<div style="margin-top:12px; display:flex; flex-direction: column; flex-grow: 1; overflow: hidden; gap: 12px;">
|
||||||
<div class="box" id="section-playlist">
|
<div class="box" id="section-playlist">
|
||||||
<div class="frame-title" onclick="toggleSection('section-playlist')">Playlist Viewer</div>
|
<div class="frame-title" onclick="toggleSection('section-playlist')">Playlist Viewer</div>
|
||||||
<div class="collapsible-content listbox" style="flex-grow:1">
|
<div class="collapsible-content listbox" id="playlist-box" style="height: 100%; flex-grow:1">
|
||||||
<div class="listbox" id="playlist-box" style="height: 100%;">
|
|
||||||
<ul class="playlist" id="playlist-ul"></ul>
|
<ul class="playlist" id="playlist-ul"></ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="box" id="section-queue">
|
<div class="box" id="section-queue">
|
||||||
<div class="frame-title" id="queue-title"><div>Queue<button id="clear-btn" class="btn">✖ Clear</button></div></div>
|
<div class="frame-title" id="queue-title"><div>Queue<button id="clear-btn" class="btn">✖ Clear</button></div></div>
|
||||||
@@ -266,10 +261,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="footer muted">
|
<div class="footer small">
|
||||||
<div>Server: <span id="server-status">connecting...</span></div>
|
<div>Server: <span id="server-status">connecting...</span></div>
|
||||||
<div class="small" id="keybinds">
|
<div class="small" id="keybinds">
|
||||||
<b>Keys:</b>
|
|
||||||
<span><kbd>S</kbd> skip</span>
|
<span><kbd>S</kbd> skip</span>
|
||||||
<span><kbd>N</kbd> +skip</span>
|
<span><kbd>N</kbd> +skip</span>
|
||||||
<span><kbd>M</kbd> -skip</span>
|
<span><kbd>M</kbd> -skip</span>
|
||||||
|
|||||||
@@ -445,7 +445,7 @@ class MediaMTXWebRTCReader {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const direction = 'recvonly';
|
const direction = 'recvonly';
|
||||||
this.pc.addTransceiver('video', { direction });
|
// this.pc.addTransceiver('video', { direction });
|
||||||
this.pc.addTransceiver('audio', { direction });
|
this.pc.addTransceiver('audio', { direction });
|
||||||
|
|
||||||
// using data channels requires creating a data channel locally
|
// using data channels requires creating a data channel locally
|
||||||
|
|||||||
+36
-19
@@ -10,6 +10,7 @@ let selectedSubFile = null;
|
|||||||
let basePath = "";
|
let basePath = "";
|
||||||
let subbasePath = "";
|
let subbasePath = "";
|
||||||
let skipCount = 0;
|
let skipCount = 0;
|
||||||
|
let skipCountToRender = 0;
|
||||||
let indexDigits = 1;
|
let indexDigits = 1;
|
||||||
let skipped_idx = [];
|
let skipped_idx = [];
|
||||||
|
|
||||||
@@ -17,13 +18,17 @@ function toggleSection(id) {
|
|||||||
document.getElementById(id).classList.toggle('collapsed');
|
document.getElementById(id).classList.toggle('collapsed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function tnet() {
|
||||||
|
return window.location.protocol === "file:" || window.location.hostname.includes("tnet")
|
||||||
|
}
|
||||||
|
|
||||||
function initLayout() {
|
function initLayout() {
|
||||||
if (window.innerWidth <= 800) {
|
if (window.innerWidth <= 800) {
|
||||||
document.getElementById('section-playlist').classList.add('collapsed');
|
document.getElementById('section-playlist').classList.add('collapsed');
|
||||||
document.getElementById('section-dirs').classList.add('collapsed');
|
document.getElementById('section-dirs').classList.add('collapsed');
|
||||||
document.getElementById('section-subdir').classList.add('collapsed');
|
document.getElementById('section-subdir').classList.add('collapsed');
|
||||||
}
|
}
|
||||||
if(window.location.protocol === "file:") document.getElementById("whep-url-input").value = "https://webrtc.terminal.tnet/radio/whep"
|
if(tnet()) document.getElementById("whep-url-input").value = "https://webrtc.terminal.tnet/radio/whep"
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectWs() {
|
function connectWs() {
|
||||||
@@ -31,7 +36,7 @@ function connectWs() {
|
|||||||
statusText.textContent = "connecting...";
|
statusText.textContent = "connecting...";
|
||||||
|
|
||||||
let url = "/ws";
|
let url = "/ws";
|
||||||
if(window.location.protocol === "file:") url = "https://radio95.tnet/ws"
|
if(tnet()) url = "https://radio95.tnet/ws"
|
||||||
ws = new WebSocket(url);
|
ws = new WebSocket(url);
|
||||||
|
|
||||||
ws.addEventListener("open", () => {
|
ws.addEventListener("open", () => {
|
||||||
@@ -59,7 +64,13 @@ function connectWs() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMessage(msg){
|
function RenderPlaylistQueue() {
|
||||||
|
skipCountToRender = skipCount;
|
||||||
|
renderQueue()
|
||||||
|
renderPlaylist()
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMessage(msg) {
|
||||||
if(msg.event === "state"){
|
if(msg.event === "state"){
|
||||||
const d = msg.data || {};
|
const d = msg.data || {};
|
||||||
if(d.dirs) updateDirs(d.dirs);
|
if(d.dirs) updateDirs(d.dirs);
|
||||||
@@ -69,7 +80,7 @@ function handleMessage(msg){
|
|||||||
document.getElementById("rds-text").textContent = rt ?? "";
|
document.getElementById("rds-text").textContent = rt ?? "";
|
||||||
} else if(msg.event === "playlist") {
|
} else if(msg.event === "playlist") {
|
||||||
playlist = msg.data || [];
|
playlist = msg.data || [];
|
||||||
renderPlaylist();
|
RenderPlaylistQueue()
|
||||||
} else if(msg.event === "new_track"){
|
} else if(msg.event === "new_track"){
|
||||||
applyTrackState(msg.data);
|
applyTrackState(msg.data);
|
||||||
ws.send(JSON.stringify({action:"get_toplay"}));
|
ws.send(JSON.stringify({action:"get_toplay"}));
|
||||||
@@ -78,16 +89,15 @@ function handleMessage(msg){
|
|||||||
} else if(msg.event === "progress") applyProgressState(msg.data);
|
} else if(msg.event === "progress") applyProgressState(msg.data);
|
||||||
else if(msg.event === "toplay") {
|
else if(msg.event === "toplay") {
|
||||||
Queue = msg.data.data || [];
|
Queue = msg.data.data || [];
|
||||||
renderQueue();
|
RenderPlaylistQueue();
|
||||||
} else if(msg.event === "request_dir") applySubdir(msg.data || {})
|
} else if(msg.event === "request_dir") applySubdir(msg.data || {})
|
||||||
else if(msg.event === "skipc") {
|
else if(msg.event === "skipc") {
|
||||||
skipCount = msg.data?.data ?? 0;
|
skipCount = msg.data?.data ?? 0;
|
||||||
document.getElementById("skpn-count").textContent = skipCount;
|
document.getElementById("skpn-count").textContent = skipCount;
|
||||||
renderPlaylist();
|
RenderPlaylistQueue();
|
||||||
renderQueue();
|
|
||||||
} else if(msg.event === "skipi") {
|
} else if(msg.event === "skipi") {
|
||||||
skipped_idx = msg.data?.data ?? skipped_idx;
|
skipped_idx = msg.data?.data ?? skipped_idx;
|
||||||
renderPlaylist();
|
RenderPlaylistQueue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,7 +108,7 @@ function applyTrackState(payload) {
|
|||||||
currentTrackIndex = payload.index;
|
currentTrackIndex = payload.index;
|
||||||
document.getElementById("now-track").textContent = `${String(currentTrackIndex).padStart(indexDigits,'0')}: ` + (track.official ? "(official) " : "(unofficial) ") + track.path.replace(basePath, "").slice(1);;
|
document.getElementById("now-track").textContent = `${String(currentTrackIndex).padStart(indexDigits,'0')}: ` + (track.official ? "(official) " : "(unofficial) ") + track.path.replace(basePath, "").slice(1);;
|
||||||
document.getElementById("next-track").textContent = (next.official ? "(official) " : "(unofficial) ") + next.path.replace(basePath, "").slice(1);
|
document.getElementById("next-track").textContent = (next.official ? "(official) " : "(unofficial) ") + next.path.replace(basePath, "").slice(1);
|
||||||
renderPlaylist();
|
RenderPlaylistQueue();
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyProgressState(payload) {
|
function applyProgressState(payload) {
|
||||||
@@ -140,9 +150,12 @@ function applySubdir(payload) {
|
|||||||
} catch(e) { dirsBox.innerHTML = "Error fetching dirs: "+e.message; }
|
} catch(e) { dirsBox.innerHTML = "Error fetching dirs: "+e.message; }
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatTime(s){
|
function formatTime(s) {
|
||||||
s = Number(s||0);
|
s = Number(s || 0);
|
||||||
const h = Math.floor(s/3600), m = Math.floor((s%3600)/60), sec = Math.floor(s%60);
|
const h = Math.floor(s / 3600)
|
||||||
|
const m = Math.floor((s % 3600) / 60)
|
||||||
|
const sec = Math.floor(s % 60);
|
||||||
|
|
||||||
if(h != 0) return [h,m,sec].map(x => String(x).padStart(2,'0')).join(":");
|
if(h != 0) return [h,m,sec].map(x => String(x).padStart(2,'0')).join(":");
|
||||||
else return [m,sec].map(x => String(x).padStart(2,'0')).join(":");
|
else return [m,sec].map(x => String(x).padStart(2,'0')).join(":");
|
||||||
}
|
}
|
||||||
@@ -162,15 +175,17 @@ function renderPlaylist() {
|
|||||||
li.addEventListener("click", () => { selectPlaylistItem(i, li); });
|
li.addEventListener("click", () => { selectPlaylistItem(i, li); });
|
||||||
if (path === currentTrackPath && i === currentTrackIndex) { li.classList.add("current"); currentIndex = i; }
|
if (path === currentTrackPath && i === currentTrackIndex) { li.classList.add("current"); currentIndex = i; }
|
||||||
else if (i === currentTrackIndex) { li.classList.add("pointer"); currentIndex = i - 1; }
|
else if (i === currentTrackIndex) { li.classList.add("pointer"); currentIndex = i - 1; }
|
||||||
if(currentIndex !== null && Queue.length === 0 && i > currentIndex && i <= currentIndex + skipCount) li.style.textDecoration = "line-through";
|
if(skipCountToRender > 0 && i > currentTrackIndex) {
|
||||||
|
li.style.textDecoration = "line-through";
|
||||||
|
skipCountToRender--;
|
||||||
|
}
|
||||||
li.textContent = ` ${String(i).padStart(indexDigits,'0')}: `;
|
li.textContent = ` ${String(i).padStart(indexDigits,'0')}: `;
|
||||||
li.textContent = (i === currentTrackIndex ? "▶ " : " ") + li.textContent + displayPath;
|
li.textContent = (i === currentTrackIndex ? "▶ " : " ") + li.textContent + displayPath;
|
||||||
ul.appendChild(li);
|
ul.appendChild(li);
|
||||||
if(skipped_idx.includes(i)) li.style.textDecoration = "line-through";
|
if(skipped_idx.includes(i)) li.style.textDecoration = "line-through";
|
||||||
});
|
});
|
||||||
if(currentIndex !== null){
|
if(currentIndex !== null){
|
||||||
const el = ul.children[currentIndex];
|
ul.children[currentIndex]?.scrollIntoView({block:'center', behavior: 'smooth'});
|
||||||
if(el) el.scrollIntoView({block:'center', behavior: 'smooth'});
|
|
||||||
} updateControls();
|
} updateControls();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +195,10 @@ function renderQueue() {
|
|||||||
Queue.forEach((element, i) => {
|
Queue.forEach((element, i) => {
|
||||||
const li = document.createElement("li");
|
const li = document.createElement("li");
|
||||||
li.textContent = element.replace(basePath, "").slice(1);
|
li.textContent = element.replace(basePath, "").slice(1);
|
||||||
if(i < skipCount) li.style.textDecoration = "line-through";
|
if(skipCountToRender > 0) {
|
||||||
|
li.style.textDecoration = "line-through";
|
||||||
|
skipCountToRender--;
|
||||||
|
}
|
||||||
ul.appendChild(li);
|
ul.appendChild(li);
|
||||||
});
|
});
|
||||||
updateControls()
|
updateControls()
|
||||||
@@ -357,8 +375,8 @@ function whepSetVol(v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function whepToggle() {
|
function whepToggle() {
|
||||||
if (whepConnected) { whepDisconnect(); return; }
|
if(whepConnected) whepDisconnect();
|
||||||
whepConnect();
|
else whepConnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
function whepDisconnect() {
|
function whepDisconnect() {
|
||||||
@@ -429,6 +447,5 @@ async function whepConnect() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start
|
|
||||||
initLayout();
|
initLayout();
|
||||||
setTimeout(connectWs, 100);
|
setTimeout(connectWs, 100);
|
||||||
Reference in New Issue
Block a user