let websocket = null; let pluginUUID = null; let actionUUID = null; let currentSettings = {}; let appList = []; function connectElgatoStreamDeckSocket(inPort, inUUID, inRegisterEvent, inInfo, inActionInfo) { pluginUUID = inUUID; const actionData = JSON.parse(inActionInfo); actionUUID = actionData.action; currentSettings = actionData.payload.settings || {}; if (currentSettings.bringToFront === undefined) { currentSettings.bringToFront = true; } updateInitialDisplay(); websocket = new WebSocket("ws://127.0.0.1:" + inPort); websocket.onopen = function () { websocket.send(JSON.stringify({ event: inRegisterEvent, uuid: inUUID })); sendToPlugin({ event: "getApps" }); }; websocket.onmessage = function (evt) { try { const jsonObj = JSON.parse(evt.data); const payload = jsonObj.payload || jsonObj; if (payload.event === "getAppsResponse") { appList = Array.isArray(payload.apps) ? payload.apps : []; renderDropdown(); } else if (payload.event === "filePickedResponse" && payload.app) { const customApp = payload.app; currentSettings.appPreset = customApp.path; currentSettings.customApp = customApp; if (payload.title) { currentSettings.title = payload.title; } saveSettings(); renderDropdown(); } else if (payload.event === "appSelectedResponse" && payload.title) { currentSettings.title = payload.title; saveSettings(); } } catch (err) { console.error("Error parsing WebSocket message:", err); } }; } function formatIconSrc(icon) { if (!icon) return ""; return icon.startsWith("data:") ? icon : "data:image/png;base64," + icon; } function updateInitialDisplay() { if (currentSettings.customApp && currentSettings.customApp.name) { updateSelectedDisplay(currentSettings.customApp.name, currentSettings.customApp.icon); } else if (currentSettings.appPreset) { const parts = currentSettings.appPreset.split(/[\\/]/); const fileName = parts[parts.length - 1] || currentSettings.appPreset; updateSelectedDisplay(fileName, ""); } else { updateSelectedDisplay("Select an App...", ""); } } function sendToPlugin(payload) { if (websocket && websocket.readyState === WebSocket.OPEN) { websocket.send(JSON.stringify({ action: actionUUID, event: "sendToPlugin", context: pluginUUID, payload: payload })); } } function saveSettings() { if (websocket && websocket.readyState === WebSocket.OPEN) { websocket.send(JSON.stringify({ event: "setSettings", context: pluginUUID, payload: currentSettings })); } } function renderDropdown() { const menu = document.getElementById("optionsMenu"); const display = document.getElementById("selectedDisplay"); if (!menu || !display) return; menu.innerHTML = ""; let foundSelected = false; appList.forEach(app => { const opt = createOptionElement(app.name, app.path, app.icon, app); menu.appendChild(opt); if (currentSettings.appPreset === app.path) { updateSelectedDisplay(app.name, app.icon); foundSelected = true; } }); if (currentSettings.customApp && currentSettings.customApp.path) { const customApp = currentSettings.customApp; const inSystemList = appList.some(a => a.path.toLowerCase() === customApp.path.toLowerCase()); if (!inSystemList) { const customOpt = createOptionElement(customApp.name, customApp.path, customApp.icon, customApp); menu.appendChild(customOpt); if (currentSettings.appPreset === customApp.path) { updateSelectedDisplay(customApp.name, customApp.icon); foundSelected = true; } } } const separator = document.createElement("div"); separator.className = "dropdown-separator"; menu.appendChild(separator); const otherOption = createOptionElement("Other...", "other", "", null); menu.appendChild(otherOption); if (!foundSelected) { if (currentSettings.appPreset === "other" || !currentSettings.appPreset) { updateSelectedDisplay("Select an App...", ""); } } } function createOptionElement(name, value, iconBase64, fullAppObject) { const div = document.createElement("div"); div.className = "option-item"; if (iconBase64) { const img = document.createElement("img"); img.src = formatIconSrc(iconBase64); div.appendChild(img); } else { const placeholder = document.createElement("div"); placeholder.className = "icon-placeholder"; div.appendChild(placeholder); } const text = document.createElement("span"); text.textContent = name; div.appendChild(text); div.addEventListener("click", (e) => { e.stopPropagation(); toggleMenu(false); if (value === "other") { sendToPlugin({ event: "pickFile", settings: currentSettings }); } else { currentSettings.appPreset = value; if (fullAppObject) { currentSettings.customApp = fullAppObject; } updateSelectedDisplay(name, iconBase64); saveSettings(); if (fullAppObject) { sendToPlugin({ event: "appSelected", app: fullAppObject, settings: currentSettings }); } } }); return div; } function updateSelectedDisplay(name, iconBase64) { const display = document.getElementById("selectedDisplay"); if (!display) return; display.innerHTML = ""; if (iconBase64) { const img = document.createElement("img"); img.src = formatIconSrc(iconBase64); display.appendChild(img); } else { const placeholder = document.createElement("div"); placeholder.className = "icon-placeholder"; display.appendChild(placeholder); } const text = document.createElement("span"); text.textContent = name; display.appendChild(text); } function toggleMenu(open) { const menu = document.getElementById("optionsMenu"); if (!menu) return; if (open === undefined) { menu.classList.toggle("open"); } else if (open) { menu.classList.add("open"); } else { menu.classList.remove("open"); } } document.addEventListener("DOMContentLoaded", () => { const trigger = document.getElementById("selectTrigger"); const bringToFrontInput = document.getElementById("bringToFront"); if (trigger) { trigger.addEventListener("click", () => toggleMenu()); } if (bringToFrontInput) { bringToFrontInput.checked = currentSettings.bringToFront !== false; bringToFrontInput.addEventListener("change", (e) => { currentSettings.bringToFront = e.target.checked; saveSettings(); }); } document.addEventListener("click", (e) => { if (!e.target.closest(".sdpi-item-value")) { toggleMenu(false); } }); });