refactor: extract typed decoder registry

This commit is contained in:
sjg
2026-08-01 16:28:39 +02:00
parent 26a167cb82
commit cbca810a30
3 changed files with 164 additions and 110 deletions
@@ -72,61 +72,73 @@
}
}
// src/app.js
// src/core/decoder-registry.ts
var bridge = window;
var readyCallbacks = [];
var decoderRegistry = [];
window.decoderRegistry = decoderRegistry;
var _decoderRegistryReadyCallbacks = [];
window.onDecoderRegistryReady = function(fn) {
if (decoderRegistry.length > 0) fn();
else _decoderRegistryReadyCallbacks.push(fn);
};
(async function fetchDecoderRegistry() {
try {
const resp = await fetch("/decoders");
if (resp.ok) {
decoderRegistry = await resp.json();
window.decoderRegistry = decoderRegistry;
for (const fn of _decoderRegistryReadyCallbacks) fn();
_decoderRegistryReadyCallbacks.length = 0;
hideUnsupportedDecoderTabs();
refreshOperatorLayoutCapabilities();
}
} catch (e) {
console.error("Failed to fetch decoder registry:", e);
}
})();
function hideUnsupportedDecoderTabs() {
const knownIds = new Set(decoderRegistry.map(function(d) {
return d.id;
}));
function onDecoderRegistryReady(callback) {
if (decoderRegistry.length > 0) callback();
else readyCallbacks.push(callback);
}
function hideUnsupportedDecoderUi() {
const knownIds = new Set(decoderRegistry.map(({ id }) => id));
const alwaysShow = /* @__PURE__ */ new Set(["overview", "rds", "sat"]);
document.querySelectorAll("#tab-digital-modes > .sub-tab-bar > .sub-tab[data-subtab]").forEach(function(btn) {
const id = btn.dataset.subtab;
if (alwaysShow.has(id) || knownIds.has(id)) return;
btn.style.display = "none";
var panel = document.getElementById("subtab-" + id);
document.querySelectorAll(
"#tab-digital-modes > .sub-tab-bar > .sub-tab[data-subtab]"
).forEach((button) => {
const id = button.dataset.subtab;
if (!id || alwaysShow.has(id) || knownIds.has(id)) return;
button.style.display = "none";
const panel = document.getElementById(`subtab-${id}`);
if (panel) panel.style.display = "none";
});
document.querySelectorAll('[id^="about-dec-"]').forEach(function(el) {
var id = el.id.replace("about-dec-", "");
if (!alwaysShow.has(id) && !knownIds.has(id)) {
var row = el.closest("tr");
if (row) row.style.display = "none";
}
document.querySelectorAll('[id^="about-dec-"]').forEach((element) => {
const id = element.id.replace("about-dec-", "");
if (alwaysShow.has(id) || knownIds.has(id)) return;
const row = element.closest("tr");
if (row) row.style.display = "none";
});
document.querySelectorAll('[id^="settings-clear-"][id$="-history"]').forEach(function(el) {
var m = el.id.match(/^settings-clear-(.+)-history$/);
if (m && !alwaysShow.has(m[1]) && !knownIds.has(m[1])) {
el.style.display = "none";
}
document.querySelectorAll('[id^="settings-clear-"][id$="-history"]').forEach((element) => {
const match = /^settings-clear-(.+)-history$/.exec(element.id);
const id = match?.[1];
if (id && !alwaysShow.has(id) && !knownIds.has(id)) element.style.display = "none";
});
document.querySelectorAll("#subtab-overview .plugin-item[data-decoder]").forEach(function(el) {
var id = el.dataset.decoder;
if (!alwaysShow.has(id) && !knownIds.has(id)) {
el.style.display = "none";
}
document.querySelectorAll("#subtab-overview .plugin-item[data-decoder]").forEach((element) => {
const id = element.dataset.decoder;
if (id && !alwaysShow.has(id) && !knownIds.has(id)) element.style.display = "none";
});
}
function isDecoderDescriptor(value) {
if (typeof value !== "object" || value === null) return false;
const item = value;
return typeof item.id === "string" && typeof item.label === "string" && typeof item.activation === "string" && Array.isArray(item.active_modes) && item.active_modes.every((mode) => typeof mode === "string") && typeof item.background_decode === "boolean" && typeof item.bookmark_selectable === "boolean";
}
function decodeRegistry(value) {
if (!Array.isArray(value) || !value.every(isDecoderDescriptor)) {
throw new TypeError("The decoder registry response is malformed");
}
return value;
}
async function loadDecoderRegistry(onLoaded) {
try {
const response = await fetch("/decoders");
if (!response.ok) return;
decoderRegistry = decodeRegistry(await response.json());
bridge.decoderRegistry = decoderRegistry;
readyCallbacks.splice(0).forEach((callback) => {
callback();
});
hideUnsupportedDecoderUi();
onLoaded();
} catch (error) {
console.error("Failed to fetch decoder registry:", error);
}
}
bridge.decoderRegistry = decoderRegistry;
bridge.onDecoderRegistryReady = onDecoderRegistryReady;
// src/app.js
void loadDecoderRegistry(refreshOperatorLayoutCapabilities);
var authRole = null;
var authEnabled = true;
async function checkAuthStatus() {