diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/generated/plugin-loader.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/generated/plugin-loader.js
new file mode 100644
index 00000000..aab2aeb9
--- /dev/null
+++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/generated/plugin-loader.js
@@ -0,0 +1,59 @@
+"use strict";
+const pluginGroups = {
+ "digital-modes": ["/ft8.js", "/ft4.js", "/ft2.js", "/wspr.js", "/cw.js", "/background-decode.js", "/sat.js", "/wefax.js"],
+ "map-data": ["/map-core.js", "/ais.js", "/vdes.js", "/aprs.js", "/hf-aprs.js"],
+ map: ["/map-core.js", "/ais.js", "/vdes.js", "/aprs.js", "/hf-aprs.js", "/sat.js", "/sat-scheduler.js"],
+ statistics: ["/map-core.js"],
+ bookmarks: ["/bookmarks.js"],
+ recorder: [],
+ settings: ["/vchan.js", "/scheduler.js"]
+};
+const loaded = /* @__PURE__ */ new Set();
+const loading = /* @__PURE__ */ new Map();
+const modulePlugins = /* @__PURE__ */ new Set(["/ft8.js", "/ft4.js", "/ft2.js", "/wspr.js", "/cw.js"]);
+function loadLegacyScript(path) {
+ return new Promise((resolve, reject) => {
+ const script = document.createElement("script");
+ script.src = path;
+ script.addEventListener("load", () => {
+ resolve();
+ }, { once: true });
+ script.addEventListener("error", () => {
+ reject(new Error(`Failed to load plugin script: ${path}`));
+ }, { once: true });
+ document.body.appendChild(script);
+ });
+}
+async function loadPlugin(path) {
+ if (loaded.has(path)) return;
+ const pending = loading.get(path);
+ if (pending) return pending;
+ const request = (modulePlugins.has(path) ? import(path).then(() => void 0) : loadLegacyScript(path)).then(() => {
+ loaded.add(path);
+ loading.delete(path);
+ }).catch((error) => {
+ loading.delete(path);
+ throw new Error(`Failed to load plugin module: ${path}`, { cause: error });
+ });
+ loading.set(path, request);
+ return request;
+}
+async function loadPlugins(group) {
+ if (!(group in pluginGroups)) return;
+ for (const path of pluginGroups[group]) await loadPlugin(path);
+}
+function requestPlugins(group) {
+ void loadPlugins(group).catch((error) => {
+ console.error(error);
+ });
+}
+const loaderWindow = window;
+loaderWindow.loadEagerPlugins = async () => {
+ await Promise.all(["digital-modes", "map-data", "bookmarks", "settings"].map(loadPlugins));
+};
+loaderWindow.loadPluginsForTab = loadPlugins;
+document.addEventListener("click", (event) => {
+ if (!(event.target instanceof Element)) return;
+ const tab = event.target.closest("[data-tab]")?.dataset.tab;
+ if (tab) requestPlugins(tab);
+});
diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html
index 1ab75cc4..fa2df4cb 100644
--- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html
+++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/index.html
@@ -1640,74 +1640,8 @@ SPDX-License-Identifier: GPL-2.0-or-later
+
-