const { ipcRenderer } = require('electron'); const DEVICE = require('./device.js'); const PLUGINS = require('./plugins.js'); const { saveAll } = require('./saveSlots.js'); const pinnedDevices = []; module.exports.pinnedDevices = pinnedDevices; let activeDevice = false; module.exports.init = function init() { populatePluginLists(); }; function drawDeviceFrame(id) { const $deviceDrawArea = document.getElementById(`device-${id}-draw-area`); const $devicePinned = document.getElementById(`device-${id}-pinned`); if ($deviceDrawArea == null) { return true; } const d = DEVICE.all[id]; if (d.frameDrawn) { return true; } const str = ` ${generateBodyHTML(d)} `; $deviceDrawArea.setAttribute('class', `${d.type} draw-area`); $deviceDrawArea.contentWindow.document.open(); $deviceDrawArea.contentWindow.document.write(str); $deviceDrawArea.contentWindow.document.close(); $deviceDrawArea.contentWindow.document.onclick = function (e) { switchDevice(d.id); }; if (d.pinIndex) { $devicePinned.style.display = 'block'; } else { $devicePinned.style.display = 'none'; } d.frameDrawn = true; return true; } function generateBodyHTML(d) { if (d.status === 'ok') { try { return PLUGINS.all[d.type].template({ templates: d.templates, data: d.data, listName: d.displayName || d.defaultName, }); } catch (err) { console.log(err); return '

Plugin Template Error

'; } } else { return `

${d.displayName || d.defaultName}

${d.type} is not responding to requests for data.

IP ${d.addresses[0]}

Port ${d.port}


${PLUGINS.all[d.type].info()}
`; } } module.exports.draw = function draw(device) { const d = device; const $deviceDrawArea = document.getElementById(`device-${d.id}-draw-area`); if ($deviceDrawArea) { const scriptEl = $deviceDrawArea.contentWindow.document.createRange().createContextualFragment(generateBodyHTML(d)); $deviceDrawArea.contentWindow.document.body.replaceChildren(scriptEl); } else { drawDeviceFrame(d.id); } d.drawn = true; }; module.exports.update = function update(device, type, data) { const doc = document.getElementById(`device-${device.id}-draw-area`); if (doc) { PLUGINS.all[device.type].update(device, doc.contentWindow.document, type, data); } }; module.exports.addDeviceToList = function addDeviceToList(device) { const d = device; let html = ''; if (d.status === 'ok') { html += "
done
"; } else if (d.status === 'refresh') { html += "
refresh
"; } else { html += "
clear
"; } html += `
${d.displayName || d.defaultName}
`; const elem = document.getElementById(d.id); if (elem == null) { document .getElementById('device-list') .insertAdjacentHTML('beforeend', `${html}`); } else { elem.innerHTML = html; } }; module.exports.removeDeviceFromList = function removeDeviceFromList(device) { const d = device; document.getElementById(d.id).remove(); }; function switchDevice(id) { if (activeDevice && activeDevice.pinIndex === false && activeDevice.id !== id) { document.getElementById(`device-${activeDevice.id}`).remove(); activeDevice.frameDrawn = false; activeDevice = false; } activeDevice = DEVICE.all[id]; let cols = 1; if (pinnedDevices.length > 0) { cols += pinnedDevices.length; } if (pinnedDevices.includes(activeDevice) || id === undefined) { cols--; } document.getElementById('all-devices').style.gridTemplateColumns = `repeat(${cols}, 1fr)`; if (id === undefined) { document.getElementById('refresh-device-button').disabled = true; document.getElementById('device-settings-table').style.display = 'none'; const $activeDevice = document.querySelector('.active-device'); if ($activeDevice) { $activeDevice.classList.remove('active-device'); } return; } document.getElementById('refresh-device-button').disabled = false; const i = DEVICE.all[id].id; const $deviceWrapper = document.getElementById(`device-${i}`); if (!$deviceWrapper) { let html = `
`; html += ``; html += ``; html += `
`; document.getElementById('all-devices').insertAdjacentHTML('afterbegin', html); } window.switchClass(document.getElementById(id), 'active-device'); drawDeviceFrame(id); window.switchClass(document.getElementById(`device-${id}`), 'active-device-outline'); document.getElementById('device-settings-table').style.display = 'block'; document.getElementById('device-settings-plugin-dropdown').value = activeDevice.type; document.getElementById('device-settings-name').value = activeDevice.displayName || activeDevice.defaultName || ''; document.getElementById('device-settings-ip').value = activeDevice.addresses[0] || ''; document.getElementById('device-settings-port').value = activeDevice.remotePort || ''; document.getElementById('device-settings-pin').checked = activeDevice.pinIndex; if (activeDevice.plugin.config.mayChangePorts) { document.getElementById('device-settings-port').disabled = false; document.getElementById('device-settings-rx-port').disabled = false; } else { document.getElementById('device-settings-port').disabled = true; document.getElementById('device-settings-rx-port').disabled = true; } if (activeDevice.plugin.config.mayChangeLocalPort === false) { document.getElementById('device-settings-rx-port').disabled = true; } else { document.getElementById('device-settings-rx-port').disabled = false; } if (activeDevice.plugin.config.localPort) { // document.getElementById('device-settings-port-label').textContent = 'Remote\nPort:'; document.getElementById('device-settings-rx-port-row').style.display = 'table-row'; document.getElementById('device-settings-rx-port').value = activeDevice.localPort || ''; } else { document.getElementById('device-settings-port-label').textContent = 'Port:'; document.getElementById('device-settings-rx-port-row').style.display = 'none'; } updateFields(); ipcRenderer.send('enableDeviceDropdown', ''); ipcRenderer.send('setDevicePin', !DEVICE.all[id].pinIndex === false); } module.exports.switchDevice = switchDevice; function updateFields() { document.getElementById('device-settings-fields').innerHTML = ''; if (activeDevice && activeDevice.plugin.config.fields) { const fields = activeDevice.plugin.config.fields; fields.forEach((field) => { // generic input setup const $elem = document.createElement('input'); $elem.value = activeDevice.fields[field.key]; $elem.name = field.key; $elem.onchange = function onchange(e) { activeDevice.fields[field.key] = $elem.value; field.action(activeDevice); saveAll(); }; // type specific setup if (field.type === 'textinput') { $elem.type = 'text'; const rowHTML = `${field.label}:`; document.getElementById('device-settings-fields').insertAdjacentHTML('beforeend', rowHTML); document.getElementById(field.key).appendChild($elem); } }); } } module.exports.updateFields = updateFields; module.exports.getActiveDevice = function getActiveDevice() { return activeDevice; }; module.exports.pinActiveDevice = function pinActiveDevice() { if (activeDevice === undefined) { return; } if (!pinnedDevices.includes(DEVICE.all[activeDevice.id])) { pinnedDevices.push(DEVICE.all[activeDevice.id]); } DEVICE.changeActivePinIndex(true); }; module.exports.unpinActiveDevice = function unpinActiveDevice() { if (activeDevice === undefined) { return; } pinnedDevices.splice(pinnedDevices.indexOf(DEVICE.all[activeDevice.id]), 1); DEVICE.changeActivePinIndex(false); }; module.exports.pinDevice = function pinDevice(device) { pinnedDevices.push(device); DEVICE.changePinIndex(device, true); }; module.exports.unpinDevice = function unpinDevice(device) { pinnedDevices.push(device); DEVICE.changePinIndex(device, false); }; module.exports.resetPinned = function resetPinned() { pinnedDevices.length = 0; activeDevice = false; try { document.querySelector('#device-list .active-device').classList.remove('active-device'); } catch (err) { // } document.getElementById('all-devices').innerHTML = ''; }; module.exports.getPinnedDevices = function getPinnedDevices() { return pinnedDevices; }; module.exports.toggleSlotButtons = function toggleSlotButtons(slotIndex) { // remove all currently active classes const currentActiveSlots = document.getElementsByClassName('active'); for (let i = 0; i < currentActiveSlots.length; i++) { const slotButton = currentActiveSlots[i]; slotButton.classList.remove('active'); } // add the active class to the newly selected slot document.getElementById(`save-slot-${slotIndex}`).classList.add('active'); }; module.exports.selectPreviousDevice = function selectPreviousDevice() { if (activeDevice === undefined) { return; } const keys = Object.keys(DEVICE.all); const prevIndex = Math.max(0, keys.indexOf(activeDevice.id) - 1); switchDevice(keys[prevIndex]); }; module.exports.selectNextDevice = function selectNextDevice() { if (activeDevice === undefined) { return; } const keys = Object.keys(DEVICE.all); const prevIndex = Math.min(keys.length - 1, keys.indexOf(activeDevice.id) + 1); switchDevice(keys[prevIndex]); }; module.exports.trafficSignal = function trafficSignal(device) { const $signal = document.querySelector(`#device-${device.id} .device-traffic-signal`); if ($signal) { $signal.style.opacity = 1; setTimeout(() => { $signal.style.opacity = 0.3; }, 50); } }; function populatePluginLists() { let typeSelect = ''; let addSelect = ''; Object.keys(PLUGINS.all).forEach((pluginType) => { const plugin = PLUGINS.all[pluginType]; addSelect += ``; typeSelect += ``; }); document.getElementById('device-settings-plugin-dropdown').innerHTML = typeSelect; document.getElementById('add-device-button').innerHTML = addSelect; }