const button = document.getElementById("ptt"); const config = document.getElementById("config"); const configForm = document.getElementById("config-form"); const configError = document.getElementById("config-error"); const authKey = document.getElementById("authKey"); const authToggle = document.getElementById("auth-toggle"); const configHeight = 680; let savedSize = null; let configLoading = false; let sizeToken = 0; function api() { if (!window.go || !window.go.main || !window.go.main.App) { return null; } return window.go.main.App; } function line(state) { if (state.detail && state.detail !== "Idle") { return state.detail; } if (state.talker) { return state.talker; } return "Idle"; } function runtime() { return window.runtime || null; } function growWindow() { const rt = runtime(); if (!rt || !rt.WindowGetSize || !rt.WindowSetSize) { return; } const token = ++sizeToken; rt.WindowGetSize().then(function (size) { if (token !== sizeToken || config.hidden) { return; } savedSize = size; rt.WindowSetSize(Math.max(size.w, 420), configHeight); }); } function restoreWindow() { sizeToken++; const rt = runtime(); if (!savedSize || !rt || !rt.WindowSetSize) { savedSize = null; return; } rt.WindowSetSize(savedSize.w, savedSize.h); savedSize = null; } function showError(message) { configError.hidden = !message; configError.textContent = message || ""; } function fillForm(form) { document.getElementById("host").value = form.host || ""; document.getElementById("port").value = String(form.port || 0); document.getElementById("callsign-field").value = form.callsign || ""; authKey.value = form.authKey || ""; document.getElementById("talkGroup").value = String(form.talkGroup || 0); document.getElementById("certificateDir").value = form.certificateDir || ""; document.getElementById("enableLogging").checked = !!form.enableLogging; document.getElementById("logFile").value = form.logFile || ""; authKey.type = "password"; authToggle.textContent = "Show"; } function readForm() { return { host: document.getElementById("host").value, port: numberValue("port"), callsign: document.getElementById("callsign-field").value, authKey: authKey.value, talkGroup: numberValue("talkGroup"), certificateDir: document.getElementById("certificateDir").value, enableLogging: document.getElementById("enableLogging").checked, logFile: document.getElementById("logFile").value }; } function numberValue(id) { const text = document.getElementById(id).value.trim(); if (text === "") { return 0; } const n = Number(text); if (!Number.isInteger(n)) { return 0; } return n; } function showConfig() { const app = api(); if (!app || configLoading) { return; } configLoading = true; app.Config().then(function (cfg) { if (!cfg.open) { return; } fillForm(cfg.form || {}); showError(cfg.error); config.hidden = false; growWindow(); }).catch(function () {}).then(function () { configLoading = false; }); } function hideConfig() { config.hidden = true; showError(""); restoreWindow(); } function render(state) { document.getElementById("connection").textContent = state.connection; document.getElementById("callsign").textContent = state.callsign; document.getElementById("talkgroup").textContent = String(state.talkGroup); const protocol = document.getElementById("protocol"); protocol.textContent = state.protocol ? "Protocol " + state.protocol : ""; document.getElementById("detail").textContent = line(state); button.classList.toggle("down", !!state.transmitting); button.disabled = !!state.configOpen; if (state.configOpen && config.hidden) { showConfig(); } else if (!state.configOpen && !config.hidden) { hideConfig(); } } function refresh() { const app = api(); if (!app) { return; } app.State().then(render).catch(function () {}); } function cancelConfig() { const app = api(); if (app) { app.CancelConfig(); } } document.getElementById("gear").addEventListener("click", function () { const app = api(); if (app) { app.OpenConfig(); } }); configForm.addEventListener("submit", function (event) { event.preventDefault(); const app = api(); if (!app) { return; } app.Save(readForm()).then(function () { refresh(); }).catch(function () { app.Config().then(function (cfg) { showError(cfg.error); }).catch(function () {}); }); }); document.getElementById("cancel").addEventListener("click", cancelConfig); authToggle.addEventListener("click", function () { const show = authKey.type === "password"; authKey.type = show ? "text" : "password"; authToggle.textContent = show ? "Hide" : "Show"; }); button.addEventListener("pointerdown", function (event) { if (button.disabled) { return; } event.preventDefault(); button.setPointerCapture(event.pointerId); const app = api(); if (app) { app.HoldButton(); } }); function releaseButton() { const app = api(); if (app) { app.ReleaseButton(); } } button.addEventListener("pointerup", releaseButton); button.addEventListener("pointercancel", releaseButton); let spaceHeld = false; window.addEventListener("keydown", function (event) { if (event.code === "Escape") { if (!config.hidden) { event.preventDefault(); cancelConfig(); } return; } if (event.code !== "Space") { return; } event.preventDefault(); if (!config.hidden || button.disabled || event.repeat || spaceHeld) { return; } spaceHeld = true; const app = api(); if (app) { app.HoldSpace(); } }); window.addEventListener("keyup", function (event) { if (event.code !== "Space") { return; } event.preventDefault(); if (!spaceHeld) { return; } spaceHeld = false; const app = api(); if (app) { app.ReleaseSpace(); } }); setInterval(refresh, 100); refresh();