SpeedyLoader/renderer.js

670 lines
22 KiB
JavaScript
Raw Normal View History

2023-01-11 14:26:21 -08:00
const serialport = require('@serialport/bindings-cpp')
2021-01-12 03:04:10 -08:00
const usb = require('usb')
2019-01-01 15:47:54 -08:00
const {ipcRenderer} = require("electron")
const { shell } = require('electron')
2018-12-31 05:59:18 -08:00
2019-07-16 23:51:27 -07:00
var basetuneList = [];
2021-01-12 03:04:10 -08:00
function getTeensyVersion(id)
{
var idString = ""
switch(id) {
case 0x273:
idString = "LC"
break;
case 0x274:
idString = "3.0"
break;
case 0x275:
idString = "3.2"
break;
case 0x276:
idString = "3.5"
break;
case 0x277:
idString = "3.6"
break;
case 0x279:
idString = "4.0"
break;
case 0x280:
idString = "4.1"
break;
}
return idString;
}
2018-12-31 05:59:18 -08:00
function refreshSerialPorts()
{
2023-01-11 14:26:21 -08:00
serialport.autoDetect().list().then(ports => {
2021-01-12 15:06:57 -08:00
console.log('Serial ports found: ', ports);
if (ports.length === 0) {
document.getElementById('serialDetectError').textContent = 'No ports discovered'
}
2023-01-13 12:16:51 -08:00
const select = document.getElementById('portsSelect');
2021-01-12 03:04:10 -08:00
2021-01-12 15:06:57 -08:00
//Clear the current options
while (select.options.length)
2021-01-12 15:06:57 -08:00
{
select.remove(0); //Always 0 index (As each time an item is removed, everything shuffles up 1 place)
}
2018-12-31 05:59:18 -08:00
2021-01-12 15:06:57 -08:00
//Load the current serial values
for(var i = 0; i < ports.length; i++)
{
var newOption = document.createElement('option');
newOption.value = ports[i].path;
newOption.innerHTML = ports[i].path;
if(ports[i].vendorId == "2341")
2018-12-31 05:59:18 -08:00
{
2021-01-12 15:06:57 -08:00
//Arduino device
if(ports[i].productId == "0010" || ports[i].productId == "0042")
{
//Mega2560 with 16u2
2021-01-12 15:06:57 -08:00
newOption.innerHTML = newOption.innerHTML + " (Arduino Mega)";
newOption.setAttribute("board", "ATMEGA2560");
}
2018-12-31 05:59:18 -08:00
}
2021-01-12 15:06:57 -08:00
else if(ports[i].vendorId == "16c0" || ports[i].vendorId == "16C0")
2018-12-31 05:59:18 -08:00
{
2021-01-12 15:06:57 -08:00
//Teensy
var teensyDevices = usb.getDeviceList().filter( function(d) { return d.deviceDescriptor.idVendor===0x16C0; });
var teensyVersion = getTeensyVersion(teensyDevices[0].deviceDescriptor.bcdDevice);
newOption.innerHTML = newOption.innerHTML + " (Teensy " + teensyVersion + ")";
2021-01-12 03:04:10 -08:00
2021-01-12 15:06:57 -08:00
//Get the short copy of the teensy version
2021-01-12 03:04:10 -08:00
teensyVersion = teensyVersion.replace(".", "");
newOption.setAttribute("board", "TEENSY"+teensyVersion);
}
else if(ports[i].vendorId == "1a86" || ports[i].vendorId == "1A86")
{
//CH340
newOption.innerHTML = newOption.innerHTML + " (Arduino Mega CH340)";
newOption.setAttribute("board", "ATMEGA2560");
}
else
{
//Unknown device, assume it's a mega2560
newOption.setAttribute("board", "ATMEGA2560");
}
2021-01-12 15:06:57 -08:00
select.add(newOption);
}
//Look for any unintialised Teensy boards (ie boards in HID rather than serial mode)
var uninitialisedTeensyDevices = usb.getDeviceList().filter( function(d) {
return d.deviceDescriptor.idVendor===0x16C0 && d.configDescriptor.interfaces[0][0].bInterfaceClass == 3; //Interface class 3 is HID
});
uninitialisedTeensyDevices.forEach((device, index) => {
console.log("Uninit Teensy found: ", getTeensyVersion(device.deviceDescriptor.bcdDevice))
var newOption = document.createElement('option');
newOption.value = "TeensyHID";
var teensyVersion = getTeensyVersion(device.deviceDescriptor.bcdDevice);
newOption.innerHTML = "Uninitialised Teensy " + teensyVersion;
teensyVersion = teensyVersion.replace(".", "");
newOption.setAttribute("board", "TEENSY"+teensyVersion);
select.add(newOption);
})
var button = document.getElementById("btnInstall")
if(ports.length > 0)
{
select.selectedIndex = 0;
button.disabled = false;
}
else { button.disabled = true; }
})
2018-12-31 05:59:18 -08:00
}
2019-01-01 19:47:18 -08:00
function refreshDetails()
2019-01-01 15:47:54 -08:00
{
var selectElement = document.getElementById('versionsSelect');
var version = selectElement.options[selectElement.selectedIndex].value;
var url = "https://api.github.com/repos/noisymime/speeduino/releases/tags/" + version;
2023-01-13 12:16:51 -08:00
document.getElementById('detailsText').innerHTML = "";
document.getElementById('detailsHeading').innerHTML = version;
2019-01-01 15:47:54 -08:00
2023-01-13 12:16:51 -08:00
fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
2019-01-01 19:47:18 -08:00
}
2023-01-13 12:16:51 -08:00
return Promise.reject(response);
})
.then((result) => {
console.log(result);
2019-01-01 19:47:18 -08:00
2023-01-13 12:16:51 -08:00
//Need to convert the Markdown that comes from Github to HTML
var myMarked = require('marked');
document.getElementById('detailsText').innerHTML = myMarked.parse(result.body);
document.getElementById('detailsHeading').innerHTML = version + " - " + result.name;
})
.catch((error) => {
console.log('Could not download details.', error);
2019-01-01 19:47:18 -08:00
});
2019-01-01 15:47:54 -08:00
}
function refreshAvailableFirmwares()
{
//Disable the buttons. These are only re-enabled if the retrieve is successful
var DetailsButton = document.getElementById("btnDetails");
var ChoosePortButton = document.getElementById("btnChoosePort");
2019-07-16 23:51:27 -07:00
var basetuneButton = document.getElementById("btnBasetune");
DetailsButton.disabled = true;
ChoosePortButton.disabled = true;
2019-07-16 23:51:27 -07:00
basetuneButton.disabled = true;
2023-01-13 12:16:51 -08:00
const select = document.getElementById('versionsSelect');
2023-01-13 12:16:51 -08:00
fetch('https://speeduino.com/fw/versions', { signal: AbortSignal.timeout(5000) } )
.then((response) => {
if (response.ok) {
return response.text();
2019-01-01 15:47:54 -08:00
}
2023-01-13 12:16:51 -08:00
return Promise.reject(response);
})
.then((result) => {
var lines = result.split('\n');
// Continue with your processing here.
for(var i = 0;i < lines.length;i++)
{
var newOption = document.createElement('option');
2023-01-13 12:16:51 -08:00
newOption.value = lines[i];
newOption.innerHTML = lines[i];
select.appendChild(newOption);
2023-01-13 12:16:51 -08:00
}
select.selectedIndex = 0;
//Remove the loading spinner
loadingSpinner = document.getElementById("fwVersionsSpinner");
loadingSpinner.style.display = "none";
refreshBasetunes();
//Re-enable the buttons
DetailsButton.disabled = false;
ChoosePortButton.disabled = false;
basetuneButton.disabled = false;
})
.catch((error) => {
console.log("Error retrieving available firmwares. ", error);
2021-07-26 22:29:11 -07:00
2023-01-13 12:16:51 -08:00
var newOption = document.createElement('option');
if(error.code === 'ETIMEDOUT')
{
newOption.value = "Connection timed out";
newOption.innerHTML = "Connection timed out";
}
2023-01-13 12:16:51 -08:00
else
{
2023-01-13 12:16:51 -08:00
newOption.value = "Cannot retrieve firmware list";
newOption.innerHTML = "Cannot retrieve firmware list. Check internet connection and restart";
}
2023-01-13 12:16:51 -08:00
select.appendChild(newOption);
//Remove the loading spinner
loadingSpinner = document.getElementById("fwVersionsSpinner");
loadingSpinner.style.display = "none";
});
2019-01-01 15:47:54 -08:00
}
2019-07-16 23:51:27 -07:00
function refreshBasetunes()
{
//Check whether the base tunes list has been populated yet
if(basetuneList === undefined || basetuneList.length == 0)
{
console.log("No tunes loaded. Retrieving from server");
//Load the json
2021-07-19 23:31:54 -07:00
//var url = "https://speeduino.com/fw/basetunes.json";
var url = "https://github.com/speeduino/Tunes/raw/main/index.json";
2019-07-16 23:51:27 -07:00
2023-01-13 13:15:48 -08:00
fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
2019-07-16 23:51:27 -07:00
}
2023-01-13 13:15:48 -08:00
return Promise.reject(response);
})
.then((result) => {
2019-07-16 23:51:27 -07:00
2023-01-13 13:15:48 -08:00
basetuneList = result;
2023-01-13 13:15:48 -08:00
//Remove the loading spinner
loadingSpinner = document.getElementById("baseTuneSpinner");
loadingSpinner.style.display = "none";
2023-01-13 13:15:48 -08:00
refreshBasetunes();
})
.catch((error) => {
console.log('Could not download base tune list.', error);
2019-07-16 23:51:27 -07:00
});
2023-01-13 13:15:48 -08:00
2019-07-16 23:51:27 -07:00
}
else
{
//JSON list of base tunes has been downloaded
2021-07-19 23:31:54 -07:00
console.log("Tune list downloaded. Populating filters");
//Grab the select elements
authorSelect = document.getElementById('basetunesAuthor');
makeSelect = document.getElementById('basetunesMake');
typeSelect = document.getElementById('basetunesType');
//Clear the current values (There shouldn't be any, but safety first)
while(authorSelect.options.length) { authorSelect.remove(0); }
while(makeSelect.options.length) { makeSelect.remove(0); }
while(typeSelect.options.length) { typeSelect.remove(0); }
//Manually add the 'All' entries
var newOption1 = document.createElement('option');
newOption1.innerHTML = "All";
var newOption2 = document.createElement('option');
newOption2.innerHTML = "All";
var newOption3 = document.createElement('option');
newOption3.innerHTML = "All";
authorSelect.appendChild(newOption1);
makeSelect.appendChild(newOption2);
typeSelect.appendChild(newOption3);
//The Types list only has 2 valid values "Stock" or "Modified", so these can be added manually
var stockOption = document.createElement('option');
var modifiedOption = document.createElement('option');
stockOption.innerHTML = "Stock";
modifiedOption.innerHTML = "Modified";
typeSelect.appendChild(stockOption);
typeSelect.appendChild(modifiedOption);
//Create unique sets with all the options
var authorsSet = new Set();
var makesSet = new Set();
for (var tune in basetuneList)
2019-07-16 23:51:27 -07:00
{
2021-07-19 23:31:54 -07:00
authorsSet.add(basetuneList[tune].provider);
makesSet.add(basetuneList[tune].make);
2019-07-16 23:51:27 -07:00
}
2021-07-19 23:31:54 -07:00
//Add the options for authors
for(let item of authorsSet.values())
2019-07-16 23:51:27 -07:00
{
2021-07-19 23:31:54 -07:00
var tempOption = document.createElement('option');
tempOption.innerHTML = item;
authorSelect.appendChild(tempOption);
}
//Add the options for makes
for(let item of makesSet.values())
{
var tempOption = document.createElement('option');
tempOption.innerHTML = item;
makeSelect.appendChild(tempOption);
2019-07-16 23:51:27 -07:00
}
2021-07-19 23:31:54 -07:00
authorSelect.selectedIndex = 0;
makeSelect.selectedIndex = 0;
typeSelect.selectedIndex = 0;
//Apply the filters to the main list
refreshBasetunesFilters()
2019-07-16 23:51:27 -07:00
}
}
2021-07-19 23:31:54 -07:00
function refreshBasetunesFilters()
{
//Get the display list object
2023-01-13 12:16:51 -08:00
const select = document.getElementById('basetunesSelect');
2021-07-19 23:31:54 -07:00
//Get the currently selected Author
selectElement = document.getElementById('basetunesAuthor');
if(selectElement.selectedIndex == -1) { return; } //Check for no value being selected
var selectedAuthor = selectElement.options[selectElement.selectedIndex].value;
//Get the currently selected Make
selectElement = document.getElementById('basetunesMake');
if(selectElement.selectedIndex == -1) { return; } //Check for no value being selected
var selectedMake = selectElement.options[selectElement.selectedIndex].value;
//Get the currently selected Type
selectElement = document.getElementById('basetunesType');
if(selectElement.selectedIndex == -1) { return; } //Check for no value being selected
var selectedType = selectElement.options[selectElement.selectedIndex].value;
//Clear the current options from the list
while(select.options.length)
{
select.remove(0);
}
var validTunes = 0;
for (var tune in basetuneList)
{
//Check whether the current tune meets filters
var AuthorBool = selectedAuthor == "All" || basetuneList[tune].provider == selectedAuthor;
var MakeBool = selectedMake == "All" || basetuneList[tune].make == selectedMake;
var TypeBool = selectedType == "All" || basetuneList[tune].type == selectedType;
if(AuthorBool && MakeBool && TypeBool)
{
//var url = basetuneList[tune].baseURL.replace("$VERSION", selectedFW) + basetuneList[tune].filename;
//console.log("Tune url: " + url);
//console.log("Found a valid tune: " + basetuneList[tune].displayName);
var newOption = document.createElement('option');
newOption.dataset.filename = basetuneList[tune].filename;
newOption.dataset.make = basetuneList[tune].make;
newOption.dataset.description = basetuneList[tune].description;
newOption.dataset.board = basetuneList[tune].board;
2021-07-19 23:31:54 -07:00
newOption.innerHTML = basetuneList[tune].displayName + " - " + basetuneList[tune].type;
select.appendChild(newOption);
validTunes++;
}
}
select.selectedIndex = 0;
refreshBasetunesDescription()
2021-07-19 23:31:54 -07:00
console.log("Tunes that met filters: " + validTunes);
}
function refreshBasetunesDescription()
{
descriptionElement = document.getElementById('tuneDetailsText');
//Get the currently selected Tune
selectElement = document.getElementById('basetunesSelect');
if(selectElement.selectedIndex == -1) { return; } //Check for no value being selected
descriptionElement.innerHTML = selectElement.options[selectElement.selectedIndex].dataset.description;
}
function downloadHex(board)
2018-12-31 05:59:18 -08:00
{
2018-12-31 05:59:18 -08:00
var e = document.getElementById('versionsSelect');
2020-10-20 19:05:17 -07:00
var DLurl;
switch(board) {
case "TEENSY35":
DLurl = "http://speeduino.com/fw/teensy35/" + e.options[e.selectedIndex].value + "-teensy35.hex";
console.log("Downloading Teensy 35 firmware: " + DLurl);
break;
case "TEENSY36":
DLurl = "http://speeduino.com/fw/teensy36/" + e.options[e.selectedIndex].value + "-teensy36.hex";
console.log("Downloading Teensy 36 firmware: " + DLurl);
break;
case "TEENSY41":
DLurl = "http://speeduino.com/fw/teensy41/" + e.options[e.selectedIndex].value + "-teensy41.hex";
console.log("Downloading Teensy 41 firmware: " + DLurl);
break;
case "ATMEGA2560":
DLurl = "http://speeduino.com/fw/bin/" + e.options[e.selectedIndex].value + ".hex";
console.log("Downloading AVR firmware: " + DLurl);
break;
2021-07-19 23:31:54 -07:00
default:
DLurl = "http://speeduino.com/fw/bin/" + e.options[e.selectedIndex].value + ".hex";
console.log("Downloading AVR firmware: " + DLurl);
break;
2020-10-20 19:05:17 -07:00
}
2018-12-31 05:59:18 -08:00
//Download the Hex file
ipcRenderer.send("download", {
url: DLurl,
properties: {directory: "downloads"}
});
}
function downloadIni()
{
var e = document.getElementById('versionsSelect');
2019-07-16 23:51:27 -07:00
var DLurl = "https://speeduino.com/fw/" + e.options[e.selectedIndex].value + ".ini";
console.log("Downloading: " + DLurl);
//Download the ini file
2018-12-31 05:59:18 -08:00
ipcRenderer.send("download", {
url: DLurl,
properties: {directory: "downloads"}
});
2018-12-31 05:59:18 -08:00
}
2019-07-16 23:51:27 -07:00
function downloadBasetune()
{
console.log("downloading");
2021-07-26 21:58:26 -07:00
var basetuneSelect = document.getElementById('basetunesSelect');
var basetuneOption = basetuneSelect.options[basetuneSelect.selectedIndex];
//var version = document.getElementById('versionsSelect');
//var DLurl = "https://github.com/noisymime/speeduino/raw/" + version + "/reference/Base%20Tunes/" + e.options[e.selectedIndex].value;
var DLurl = "https://github.com/speeduino/Tunes/raw/main/" + basetuneOption.dataset.make + "/" + basetuneOption.dataset.filename;
console.log("Downloading: " + DLurl);
//Download the ini file
ipcRenderer.send("download", {
url: DLurl,
properties: {directory: "downloads"}
});
2023-01-13 10:42:13 -08:00
const baseTuneLink = document.querySelectorAll('a[href="#basetunes"]');
baseTuneLink[0].click();
2019-07-16 23:51:27 -07:00
}
//Installing the Windows drivers
function installDrivers()
{
ipcRenderer.send("installWinDrivers", {
});
2019-07-08 21:56:05 -07:00
}
2019-01-01 15:47:54 -08:00
function uploadFW()
2018-12-31 05:59:18 -08:00
{
2019-01-03 23:54:39 -08:00
//Start the spinner
var spinner = document.getElementById('progressSpinner');
//Disable the Re-burn/re-install button
var reinstallButton = document.getElementById("btnReinstall")
reinstallButton.disabled = true;
2019-01-03 23:54:39 -08:00
//Remove any old icons
spinner.classList.remove('fa-pause');
spinner.classList.remove('fa-check');
spinner.classList.remove('fa-times');
spinner.classList.add('fa-spinner');
2020-10-20 19:05:17 -07:00
//Lookup what platform we're using
var portSelect = document.getElementById('portsSelect');
var uploadBoard = portSelect.options[portSelect.selectedIndex].getAttribute("board");
2020-10-20 19:05:17 -07:00
2019-01-14 14:21:56 -08:00
//Hide the terminal section incase it was there from a previous burn attempt
document.getElementById('terminalSection').style.display = "none";
//Same for the ini location link
document.getElementById('iniFileText').style.display = "none";
2019-01-14 14:21:56 -08:00
2019-01-01 19:47:18 -08:00
var statusText = document.getElementById('statusText');
2019-01-04 04:10:03 -08:00
var burnPercentText = document.getElementById('burnPercent');
statusText.innerHTML = "Downloading INI file"
downloadIni();
2019-01-01 19:47:18 -08:00
2019-01-04 04:10:03 -08:00
ipcRenderer.on("download complete", (event, file, state) => {
console.log("Saved file: " + file); // Full file path
var extension = file.substr(file.length - 3);
if(extension == "ini")
{
statusText.innerHTML = "Downloading firmware"
document.getElementById('iniFileText').style.display = "block"
document.getElementById('iniFileLocation').innerHTML = file
downloadHex(uploadBoard);
}
else if(extension == "hex")
{
2019-01-14 14:21:56 -08:00
statusText.innerHTML = "Beginning upload..."
//Retrieve the select serial port
var e = document.getElementById('portsSelect');
uploadPort = e.options[e.selectedIndex].value;
console.log("Using port: " + uploadPort);
2020-10-20 23:00:15 -07:00
//Show the sponsor banner
2023-01-15 05:59:59 -08:00
document.getElementById('sponsorbox').style.display = "block"
2020-10-20 23:00:15 -07:00
//Begin the upload
if(uploadBoard.includes("TEENSY"))
2020-10-20 19:05:17 -07:00
{
2021-07-19 23:31:54 -07:00
console.log("Uploading using Teensy_loader")
ipcRenderer.send("uploadFW_teensy", {
port: uploadPort,
firmwareFile: file,
board: uploadBoard
2020-10-20 19:05:17 -07:00
});
}
else
{
ipcRenderer.send("uploadFW", {
port: uploadPort,
firmwareFile: file
});
}
}
});
ipcRenderer.on("upload completed", (event, code) => {
2019-01-02 06:05:30 -08:00
statusText.innerHTML = "Upload to arduino completed successfully!";
2019-01-04 04:10:03 -08:00
burnPercentText.innerHTML = "";
//Turn the spinner off
2019-01-03 23:54:39 -08:00
spinner.classList.remove('fa-spinner');
spinner.classList.add('fa-check');
//Re-enable the re-burn button
reinstallButton.disabled = false;
2020-10-20 23:00:15 -07:00
2019-01-01 15:47:54 -08:00
});
2019-01-04 04:10:03 -08:00
ipcRenderer.on("upload percent", (event, percent) => {
2019-01-14 14:21:56 -08:00
statusText.innerHTML = "Uploading firmware to board"
2019-01-04 04:10:03 -08:00
burnPercentText.innerHTML = " (" + percent + "%)";
});
ipcRenderer.on("upload error", (event, code) => {
2019-01-14 14:21:56 -08:00
statusText.innerHTML = "Upload to Speeduino failed";
2021-07-26 22:29:11 -07:00
//Hide the donation bar as it makes the terminal go offscreen
2023-01-15 05:59:59 -08:00
document.getElementById('sponsorbox').style.display = "none"
2021-07-26 22:29:11 -07:00
//Mke the terminal/error section visible
2019-01-03 23:54:39 -08:00
document.getElementById('terminalSection').style.display = "block";
document.getElementById('terminalText').innerHTML = code;
2019-01-03 23:54:39 -08:00
spinner.classList.remove('fa-spinner');
spinner.classList.add('fa-times');
2021-07-26 22:29:11 -07:00
reinstallButton.disabled = false;
});
2018-12-31 05:59:18 -08:00
}
2023-01-11 13:30:15 -08:00
async function checkForUpdates()
2019-07-02 00:03:07 -07:00
{
2023-01-11 13:30:15 -08:00
//Adds the current version number to the Titlebar
let current_version = await ipcRenderer.invoke("getAppVersion");
document.getElementById('title').innerHTML = "Speeduino Universal Firmware Loader (v" + current_version + ")"
2019-07-02 00:03:07 -07:00
var url = "https://api.github.com/repos/speeduino/SpeedyLoader/releases/latest";
2019-01-26 18:01:17 -08:00
2019-07-02 00:03:07 -07:00
//document.getElementById('detailsHeading').innerHTML = version;
2023-01-13 13:15:48 -08:00
fetch(url)
.then((response) => {
if (response.ok) {
return response.json();
2019-07-02 00:03:07 -07:00
}
2023-01-13 13:15:48 -08:00
return Promise.reject(response);
})
.then((result) => {
2023-01-13 13:17:26 -08:00
2023-01-13 13:15:48 -08:00
latest_version = result.tag_name.substring(1);
console.log("Latest version: " + latest_version);
2019-07-02 00:03:07 -07:00
2023-01-13 13:15:48 -08:00
var semver = require('semver');
if(semver.gt(latest_version, current_version))
2019-07-02 00:03:07 -07:00
{
2023-01-13 13:15:48 -08:00
//New version has been found
document.getElementById('update_url').setAttribute("href", result.html_url);
document.getElementById('update_text').style.display = "block";
2019-07-02 00:03:07 -07:00
}
2023-01-13 13:15:48 -08:00
})
.catch((error) => {
console.log('Could not get latest version.', error);
2019-07-02 00:03:07 -07:00
});
}
window.onload = function () {
refreshAvailableFirmwares();
2019-07-16 23:51:27 -07:00
refreshBasetunes();
2019-07-02 00:03:07 -07:00
refreshSerialPorts();
checkForUpdates();
};
$(function(){
// Button handlers
$(document).on('click', '#btnChoosePort', function(event) {
$("[href='#port']").trigger('click');
});
$(document).on('click', '#btnBasetune', function(event) {
$("[href='#basetunes']").trigger('click');
});
$(document).on('click', '#btnLoader', function(event) {
$("[href='#loader']").trigger('click');
});
$(document).on('click', '#btnDetails', function(event) {
refreshDetails();
$("[href='#details']").trigger('click');
});
$(document).on('click', '#btnInstall', function(event) {
$("[href='#progress']").trigger('click');
uploadFW();
});
$(document).on('click', '#btnReinstall', function(event) {
$("[href='#progress']").trigger('click');
uploadFW();
});
$(document).on('click', '#btnDownloadBasetune', function(event) {
const select = document.getElementById('basetunesSelect');
const selectedTune = select.options[select.selectedIndex];
document.getElementById("tuneBoard").innerHTML = selectedTune.dataset.board;
$("[href='#basetunewarning']").trigger('click');
});
$(document).on('click', '#btnDownloadCancel', function(event) {
$("[href='#basetunes']").trigger('click');
});
$(document).on('click', '#btnExit', function(event) {
ipcRenderer.invoke('quit-app');
});
$(document).on('click', '#iniFileLink', function(event) {
var location = document.getElementById('iniFileLocation').innerHTML
if (location != "")
{
ipcRenderer.invoke('show-ini', location);
}
});
});