Dash updates

This commit is contained in:
cpq committed 2026-05-01 13:12:51 +01:00
1 parent c5b74babab
commit 59f9b36ddd
8 files changed
+1114 -824

No files matched your search

+34 -6
View File
@@ -7,7 +7,7 @@
function Rpc(url, onev) {
let ws, id = 1, oncall, q = [];
const pending = new Map();
const realsend = s => { ws.send(s); on('send', s); };
const realsend = s => { ws.send(s); onev && onev('send', s); };
const fail = e => { for (const p of pending.values()) p[1](e || 'disconnected'); pending.clear(); };
const send = x => ws && ws.readyState === 1
? realsend(JSON.stringify(x))
@@ -61,7 +61,7 @@
const isMock = !!window.frameElement || (window !== window.top);
const settings = {data: {}, edits: {}, debug: true};
const userhandlers = {}; // User event handlers
const status = { online: true, username: '', userlevel: 0, lastseen: '' };
const status = { online: true, username: '', userlevel: 0, lastseen: '', initialized: false };
const rpc = isMock ? null : Rpc('api/websocket', function (evname, args) {
if (evname == 'open') status.online = true, rescan();
if (evname == 'close') status.online = false, rescan();
@@ -152,8 +152,15 @@
el.classList.toggle('error', false);
}
if (!el.bound) el.addEventListener("input", ev => edit(el, key, el.type == 'checkbox' ? ev.target.checked : ev.target.value)), el.bound = true;
} else if (el.tagName == 'BUTTON') {
if (!el.bound) {
el.addEventListener("pointerdown", ev => Dashboard.call('set', set({}, key, true)));
el.addEventListener("pointerup", ev => Dashboard.call('set', set({}, key, false)));
el.bound = true;
el.dataset.autosave = 1;
}
} else {
el.innerHTML = v;
el.innerHTML = v;
}
};
@@ -317,19 +324,40 @@
userhandlers[name] = fn;
};
const setbody = visibility => document.body.style.visibility = visibility;
function init(conf) {
apply_and_rescan(settings, conf);
if (rpc) {
rpc.handle((method, args) => {
if (method == 'change') apply_and_rescan(settings.data, args);
if (method == 'change') {
// "initialized" means that the device has sent us all initial
// data change notifications, and our settings.data contain
// actual refreshed device data - not the UI mock
if (!args) {
setbody('visible');
status.initialized = true;
}
if (args) apply_and_rescan(settings.data, args);
}
if (method != 'change') console.log('UNKNOWN REQUEST', method, args);
if (userhandlers[method]) userhandlers[method](args);
});
// After init, fetch all device data
rpc.call('get').then(r => apply_and_rescan(settings.data, r));
//rpc.call('get').then(r => apply_and_rescan(settings.data, r));
} else {
setTimeout(function() {
status.initialized = true;
setbody('visible');
}, 500);
}
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", () => setbody('hidden'), { once: true });
} else {
setbody('hidden');
}
global.Dashboard = { init, call, on, status };
})(window);
+17 -5
View File
@@ -28,10 +28,17 @@ if (watchTargets.length === 0 || command.length === 0) {
let child = null;
let restartTimeout = null;
let ignoreEventsUntil = 0;
let lastStartAt = 0;
const MIN_RESTART_MS = 250;
function start() {
// Prevent restart loops caused by the command touching watched paths.
ignoreEventsUntil = Date.now() + 200;
lastStartAt = Date.now();
if (child) {
child.kill();
child.kill('SIGTERM');
}
console.log(`Starting: ${command.join(' ')}`);
child = spawn(command[0], command.slice(1), { stdio: 'inherit', shell: true });
@@ -45,20 +52,25 @@ function start() {
function watch(target) {
const stats = fs.statSync(target);
if (stats.isFile()) {
fs.watchFile(target, (curr, prev) => {
if (curr.mtime !== prev.mtime) {
// fs.watchFile is polling-based; use a small interval to react quickly.
fs.watchFile(target, { interval: 100 }, (curr, prev) => {
if (Date.now() < ignoreEventsUntil) return;
if (curr.mtimeMs !== prev.mtimeMs) {
console.log(`File changed: ${target}`);
clearTimeout(restartTimeout);
restartTimeout = setTimeout(start, 100);
const delay = Math.max(25, MIN_RESTART_MS - (Date.now() - lastStartAt));
restartTimeout = setTimeout(start, delay);
}
});
} else {
const dir = target;
fs.watch(dir, { recursive: true }, (eventType, filename) => {
if (Date.now() < ignoreEventsUntil) return;
if (filename) {
console.log(`File changed: ${filename}`);
clearTimeout(restartTimeout);
restartTimeout = setTimeout(start, 100);
const delay = Math.max(25, MIN_RESTART_MS - (Date.now() - lastStartAt));
restartTimeout = setTimeout(start, delay);
}
});
}