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 {wm} from "../wm.js";
@@ -226,7 +227,7 @@ export function Msd() {
if (el.__names_json !== names_json) {
el.innerHTML = names.map(name => `
<div class="text">
<div id="__msd-storage-${tools.makeIdByText(name)}-progress" class="progress">
<div id="__msd-storage-${tools.makeTextId(name)}-progress" class="progress">
<span class="progress-value"></span>
</div>
</div>
@@ -241,7 +242,7 @@ export function Msd() {
? `${names.length === 1 ? "Storage: %s" : "Internal storage: %s"}` // eslint-disable-line
: `Storage [${name}${part.writable ? "]" : ", read-only]"}: %s` // eslint-disable-line
);
let id = `__msd-storage-${tools.makeIdByText(name)}-progress`;
let id = `__msd-storage-${tools.makeTextId(name)}-progress`;
tools.progress.setSizeOf($(id), title, part.size, part.free);
}
};
@@ -291,15 +292,15 @@ export function Msd() {
};
var __clickDownloadButton = function() {
let image = encodeURIComponent($("msd-image-selector").value);
window.open(`/api/msd/read?image=${image}`);
let e_image = encodeURIComponent($("msd-image-selector").value);
tools.windowOpen(`api/msd/read?image=${e_image}`);
};
var __clickRemoveButton = function() {
let name = $("msd-image-selector").value;
wm.confirm("Are you sure you want to remove this image?", name).then(function(ok) {
if (ok) {
tools.httpPost("/api/msd/remove", {"image": name}, function(http) {
tools.httpPost("api/msd/remove", {"image": name}, function(http) {
if (http.status !== 200) {
wm.error("Can't remove image", http.responseText);
}
@@ -309,7 +310,7 @@ export function Msd() {
};
var __sendParam = function(name, value) {
tools.httpPost("/api/msd/set_params", {[name]: value}, function(http) {
tools.httpPost("api/msd/set_params", {[name]: value}, function(http) {
if (http.status !== 200) {
wm.error("Can't configure Mass Storage", http.responseText);
}
@@ -335,11 +336,11 @@ export function Msd() {
prefix = __state.storage.filespath;
}
if (file) {
let image = encodeURIComponent(file.name);
__http.open("POST", `/api/msd/write?prefix=${prefix}&image=${image}&remove_incomplete=1`, true);
let e_image = encodeURIComponent(file.name);
__http.open("POST", `${ROOT_PREFIX}api/msd/write?prefix=${e_prefix}&image=${e_image}&remove_incomplete=1`, true);
} else {
let url = encodeURIComponent($("msd-new-url").value);
__http.open("POST", `/api/msd/write_remote?prefix=${prefix}&url=${url}&remove_incomplete=1`, true);
let e_url = encodeURIComponent($("msd-new-url").value);
__http.open("POST", `${ROOT_PREFIX}api/msd/write_remote?prefix=${e_prefix}&url=${e_url}&remove_incomplete=1`, true);
}
__http.upload.timeout = 7 * 24 * 3600;
__http.onreadystatechange = __uploadStateChange;
@@ -395,7 +396,7 @@ export function Msd() {
};
var __clickConnectButton = function(connected) {
tools.httpPost("/api/msd/set_connected", {"connected": connected}, function(http) {
tools.httpPost("api/msd/set_connected", {"connected": connected}, function(http) {
if (http.status !== 200) {
wm.error("Can't switch Mass Storage", http.responseText);
}
@@ -423,7 +424,7 @@ export function Msd() {
var __clickResetButton = function() {
wm.confirm("Are you sure you want to reset Mass Storage?").then(function(ok) {
if (ok) {
tools.httpPost("/api/msd/reset", null, function(http) {
tools.httpPost("api/msd/reset", null, function(http) {
if (http.status !== 200) {
wm.error("Mass Storage reset error", http.responseText);
}
@@ -451,7 +452,8 @@ export function Msd() {
if (__state && __state.storage && __state.storage.parts) {
let part = __state.storage.parts[$("msd-new-part-selector").value];
if (part && (file.size > part.size)) {
wm.error(`The new image is too big for the Mass Storage partition.<br>Maximum: ${tools.formatSize(part.size)}`);
let e_size = tools.escape(tools.formatSize(part.size));
wm.error(`The new image is too big for the Mass Storage partition.<br>Maximum: ${e_size}`);
el.value = "";
}
}