feat: merge upstream master - version 4.94

Merge upstream PiKVM master branch updates:

- Bump version from 4.93 to 4.94
- HID: improved jiggler pattern for better compatibility
- Streamer: major refactoring for improved performance and maintainability
- Prometheus: tidying GPIO channel name formatting
- Web: added __gpio-label class for custom styling
- HID: customizable /api/hid/print delay configuration
- ATX: independent power/reset regions for better control
- OLED: added --fill option for display testing
- Web: improved keyboard handling in modal dialogs
- Web: enhanced login error messages
- Switch: added heartbeat functionality
- Web: mouse touch code simplification and refactoring
- Configs: use systemd-networkd-wait-online --any by default
- PKGBUILD: use cp -r to install systemd units properly
- Various bug fixes and performance improvements
This commit is contained in:
mofeng-git
2025-08-21 11:21:41 +08:00
205 changed files with 9359 additions and 4653 deletions

View File

@@ -24,6 +24,7 @@
"use strict";
import {ROOT_PREFIX} from "../vars.js";
import {tools, $} from "../tools.js";
import {checkBrowser} from "../bb.js";
import {wm, initWindowManager} from "../wm.js";
@@ -39,68 +40,86 @@ export function main() {
function __loadKvmdInfo() {
tools.httpGet("/api/info", {"fields": "auth,meta,extras"}, function(http) {
if (http.status === 200) {
let info = JSON.parse(http.responseText).result;
tools.httpGet("api/info", {"fields": "auth,meta,extras"}, function(http) {
switch (http.status) {
case 200:
__showKvmdInfo(JSON.parse(http.responseText).result);
break;
let apps = [];
if (info.extras === null) {
wm.error("Not all applications in the menu can be displayed due an error.<br>See KVMD logs for details.");
} else {
apps = Object.values(info.extras).sort(function(a, b) {
if (a.place < b.place) {
return -1;
} else if (a.place > b.place) {
return 1;
} else {
return 0;
}
});
}
case 401:
case 403:
tools.currentOpen("login");
break;
$("apps-box").innerHTML = "<ul id=\"apps\"></ul>";
// Don't use this option, it may be removed in any time
let hide_kvm_button = (
(info.meta !== null && info.meta.web && info.meta.web.hide_kvm_button)
|| tools.config.getBool("index--hide-kvm-button", false)
);
if (!hide_kvm_button) {
$("apps").innerHTML += __makeApp(null, "kvm", "share/svg/kvm.svg", "KVM");
}
for (let app of apps) {
if (app.place >= 0 && (app.enabled || app.started)) {
$("apps").innerHTML += __makeApp(null, app.path, app.icon, app.name);
}
}
if (info.auth.enabled) {
$("apps").innerHTML += __makeApp("logout-button", "#", "share/svg/logout.svg", "Logout");
tools.el.setOnClick($("logout-button"), __logout);
}
if (info.meta !== null && info.meta.server && info.meta.server.host) {
$("kvmd-meta-server-host").innerHTML = info.meta.server.host;
document.title = `One-KVM Index: ${info.meta.server.host}`;
} else {
$("kvmd-meta-server-host").innerHTML = "";
document.title = "One-KVM Index";
}
} else if (http.status === 401 || http.status === 403) {
document.location.href = "/login";
} else {
setTimeout(__loadKvmdInfo, 1000);
default:
setTimeout(__loadKvmdInfo, 1000);
break;
}
});
}
function __showKvmdInfo(info) {
let apps = [];
if (info.extras === null) {
wm.error("Not all applications in the menu can be displayed due an error.<br>See KVMD logs for details.");
} else {
apps = Object.values(info.extras).sort(function(a, b) {
if (a.place < b.place) {
return -1;
} else if (a.place > b.place) {
return 1;
} else {
return 0;
}
});
}
let html = "";
// Don't use this option, it may be removed in any time
let hide_kvm_button = (
(info.meta !== null && info.meta.web && info.meta.web.hide_kvm_button)
|| tools.config.getBool("index--hide-kvm-button", false)
);
if (!hide_kvm_button) {
html += __makeApp(null, "kvm", "share/svg/kvm.svg", "KVM");
}
for (let app of apps) {
if (app.place >= 0 && (app.enabled || app.started)) {
html += __makeApp(null, app.path, app.icon, app.name);
}
}
if (info.auth.enabled) {
html += __makeApp("logout-button", "#", "share/svg/logout.svg", "Logout");
}
$("apps-box").innerHTML = `<ul id="apps">${html}</ul>`;
if (info.auth.enabled) {
tools.el.setOnClick($("logout-button"), __logout);
}
if (info.meta !== null && info.meta.server && info.meta.server.host) {
$("kvmd-meta-server-host").innerText = info.meta.server.host;
document.title = `${info.meta.server.host} | PiKVM Index`;
} else {
$("kvmd-meta-server-host").innerHTML = "<i>Invalid meta</i>";
document.title = "PiKVM Index";
}
}
function __makeApp(id, path, icon, name) {
// Tailing slash in href is added to avoid Nginx 301 redirect
// when the location doesn't have tailing slash: "foo -> foo/".
// Reverse proxy over PiKVM can be misconfigured to handle this.
let e_add_id = (id ? `id="${tools.escape(id)}"` : "");
return `<li>
<div ${id ? "id=\"" + id + "\"" : ""} class="app">
<a href="${path}">
<div ${e_add_id} class="app">
<a href="${tools.escape(ROOT_PREFIX + path)}/">
<div>
<img class="svg-gray" src="${icon}">
<img class="svg-gray" src="${tools.escape(ROOT_PREFIX + icon)}">
${tools.escape(name)}
</div>
</a>
@@ -109,11 +128,17 @@ function __makeApp(id, path, icon, name) {
}
function __logout() {
tools.httpPost("/api/auth/logout", null, function(http) {
if (http.status === 200 || http.status === 401 || http.status === 403) {
document.location.href = "/login";
} else {
wm.error("Logout error", http.responseText);
tools.httpPost("api/auth/logout", null, function(http) {
switch (http.status) {
case 200:
case 401:
case 403:
tools.currentOpen("login");
break;
default:
wm.error("Logout error", http.responseText);
break;
}
});
}