commit d46e916

uint  ·  2026-01-31 20:27:40 +0000 UTC
parent 0a3c07f
remove webui
3 files changed,  +0, -311
+0, -39
 1@@ -1,39 +0,0 @@
 2-<!doctype html>
 3-<html>
 4-	<head>
 5-		<meta charset="utf-8">
 6-		<meta name="viewport" content="width=device-width, initial-scale=1">
 7-		<title>parados</title>
 8-		<link rel="stylesheet" href="style.css">
 9-	</head>
10-	<body>
11-		<header>
12-			<h1>parados</h1>
13-
14-			<form id="cfg" autocomplete="off">
15-				<input id="base" type="text" value="http://127.0.0.1:8088">
16-				<button id="load" type="submit">load</button>
17-				<span id="status"></span>
18-			</form>
19-		</header>
20-
21-		<main>
22-			<section id="left">
23-				<input id="filter" type="text" placeholder="filter...">
24-				<ul id="list"></ul>
25-			</section>
26-
27-			<section id="right">
28-				<div id="now"></div>
29-
30-				<audio id="aud" controls preload="metadata"></audio>
31-				<video id="vid" controls preload="metadata"></video>
32-
33-				<pre id="meta"></pre>
34-			</section>
35-		</main>
36-
37-		<script src="parados.js"></script>
38-	</body>
39-</html>
40-
+0, -258
  1@@ -1,258 +0,0 @@
  2-"use strict";
  3-
  4-let items = [];
  5-let active_id = null;
  6-
  7-function $(id)
  8-{
  9-	return document.getElementById(id);
 10-}
 11-
 12-function status_set(s)
 13-{
 14-	const e = $("status");
 15-	if (e)
 16-		e.textContent = s;
 17-}
 18-
 19-function base_url()
 20-{
 21-	const e = $("base");
 22-	const s = e ? (e.value || "") : "";
 23-	return s.replace(/\/+$/, "");
 24-}
 25-
 26-function human_size(n)
 27-{
 28-	if (typeof n !== "number" || !isFinite(n))
 29-		return "" + n;
 30-
 31-	const u = ["B","KB","MB","GB","TB"];
 32-	let i = 0;
 33-	while (n >= 1024 && i < u.length - 1) {
 34-		n /= 1024;
 35-		i++;
 36-	}
 37-	return (i === 0 ? n.toFixed(0) : n.toFixed(1)) + " " + u[i];
 38-}
 39-
 40-function is_video(type, path)
 41-{
 42-	if (type && type.startsWith("video/"))
 43-		return true;
 44-
 45-	return /\.(mp4|mkv|webm|mov)$/i.test(path || "");
 46-}
 47-
 48-function is_audio(type, path)
 49-{
 50-	if (type && type.startsWith("audio/"))
 51-		return true;
 52-
 53-	return /\.(mp3|m4a|aac|flac|wav|ogg|opus)$/i.test(path || "");
 54-}
 55-
 56-function clear_players()
 57-{
 58-	const a = $("aud");
 59-	const v = $("vid");
 60-
 61-	if (a) {
 62-		a.pause();
 63-		a.removeAttribute("src");
 64-		a.style.display = "none";
 65-	}
 66-	if (v) {
 67-		v.pause();
 68-		v.removeAttribute("src");
 69-		v.style.display = "none";
 70-	}
 71-}
 72-
 73-async function api_json(url)
 74-{
 75-	const r = await fetch(url, { method: "GET" });
 76-	if (!r.ok) {
 77-		let t = "";
 78-		try {
 79-			t = await r.text();
 80-		}
 81-		catch (e) {
 82-			t = "";
 83-		}
 84-		t = (t || "").trim();
 85-		throw new Error("http " + r.status + (t ? (": " + t) : ""));
 86-	}
 87-
 88-	return await r.json();
 89-}
 90-
 91-function render_list()
 92-{
 93-	const list = $("list");
 94-	const f = $("filter");
 95-
 96-	if (!list)
 97-		return;
 98-
 99-	const q = (f ? (f.value || "") : "").toLowerCase();
100-
101-	list.innerHTML = "";
102-	for (const it of items) {
103-		if (q && !(it.path || "").toLowerCase().includes(q))
104-			continue;
105-
106-		const li = document.createElement("li");
107-		li.dataset.id = it.id;
108-		li.textContent = it.path || it.id;
109-
110-		if (it.id === active_id)
111-			li.classList.add("active");
112-
113-		li.addEventListener("click", () => select_item(it.id));
114-
115-		list.appendChild(li);
116-	}
117-}
118-
119-function set_active_class()
120-{
121-	const list = $("list");
122-	if (!list)
123-		return;
124-
125-	const lis = list.querySelectorAll("li");
126-	for (const li of lis) {
127-		if (li.dataset.id === active_id)
128-			li.classList.add("active");
129-		else
130-			li.classList.remove("active");
131-	}
132-}
133-
134-async function load_library()
135-{
136-	status_set("loading...");
137-	clear_players();
138-
139-	const now = $("now");
140-	const meta = $("meta");
141-
142-	if (now)
143-		now.textContent = "";
144-	if (meta)
145-		meta.textContent = "";
146-
147-	const base = base_url();
148-	const j = await api_json(base + "/library");
149-
150-	if (!j || !Array.isArray(j.items))
151-		throw new Error("bad /library json");
152-
153-	items = j.items.slice();
154-	active_id = null;
155-
156-	status_set("ok (" + items.length + " items)");
157-	render_list();
158-}
159-
160-async function select_item(id)
161-{
162-	active_id = id;
163-	set_active_class();
164-	clear_players();
165-
166-	const base = base_url();
167-
168-	const it = items.find(x => x.id === id);
169-	const path = it ? (it.path || "") : "";
170-
171-	const now = $("now");
172-	const meta = $("meta");
173-	const a = $("aud");
174-	const v = $("vid");
175-
176-	if (now)
177-		now.textContent = path ? path : ("id " + id);
178-	if (meta)
179-		meta.textContent = "loading meta...";
180-
181-	let m = null;
182-	try {
183-		m = await api_json(base + "/meta/" + id);
184-	}
185-	catch (e) {
186-		if (meta)
187-			meta.textContent = "" + e;
188-		return;
189-	}
190-
191-	const type = m.type || "";
192-	const size = Number(m.size);
193-
194-	if (meta) {
195-		meta.textContent =
196-			"id:   " + (m.id || id) + "\n" +
197-			"path: " + (m.path || path) + "\n" +
198-			"type: " + type + "\n" +
199-			"size: " + (isFinite(size) ? human_size(size) : (m.size || "")) + "\n";
200-	}
201-
202-	const stream = base + "/stream/" + id;
203-
204-	if (v && is_video(type, m.path || path)) {
205-		v.src = stream;
206-		v.style.display = "block";
207-		v.load();
208-		return;
209-	}
210-
211-	if (a && is_audio(type, m.path || path)) {
212-		a.src = stream;
213-		a.style.display = "block";
214-		a.load();
215-		return;
216-	}
217-
218-	if (meta)
219-		meta.textContent += "\n(no player for this type)\n";
220-}
221-
222-async function main()
223-{
224-	const cfg = $("cfg");
225-	const load = $("load");
226-	const filter = $("filter");
227-
228-	if (cfg) {
229-		cfg.addEventListener("submit", async (ev) => {
230-			ev.preventDefault();
231-			if (load)
232-				load.disabled = true;
233-
234-			try {
235-				await load_library();
236-			}
237-			catch (e) {
238-				status_set("error: " + (e.message || e));
239-			}
240-			finally {
241-				if (load)
242-					load.disabled = false;
243-			}
244-		});
245-	}
246-
247-	if (filter)
248-		filter.addEventListener("input", render_list);
249-
250-	try {
251-		await load_library();
252-	}
253-	catch (e) {
254-		status_set("error: " + (e.message || e));
255-	}
256-}
257-
258-main();
259-
+0, -14
 1@@ -1,14 +0,0 @@
 2-body {
 3-	color: #eeeeee;
 4-	background-color: #1e1f21;
 5-	font-family: serif;
 6-	margin: 20px;
 7-}
 8-
 9-video {
10-	width: 100%;
11-	max-width: 400px;
12-	background: #000;
13-	display: block;
14-}
15-