Spin/main.js
thecookingsenpai 7a7f027796 Initial commit
2023-12-25 13:29:59 +01:00

193 lines
6.4 KiB
JavaScript

// NOTE Loading modules (app and BrowserWindow) for main and rederer
const {app, BrowserWindow} = require('electron')
const { Worker } = require('worker_threads')
// SECTION Subroutine management
// NOTE Loading subprocesses and starting the listeners
subroutines = {}
function start_subroutine(name, path, data) {
if (name in subroutines) {
console.log("[x] Subroutine already exists")
alert("Error launching the subroutine: subroutine already exists")
return
}
subroutines[name] = new Worker(path, { workerData: data });
subroutines[name].on('message', (message) => {
// On message load it
let j_message = JSON.parse(message.toString('utf8'))
console.log("[*] Message from " + name)
console.log(j_message)
// Extract the message id
let msg_id = j_message.id
console.log("ID: " + msg_id)
var result;
var message;
// Send it to the parser
var packed = parseMessage(j_message, name)
result = packed[0]
message = packed[1]
console.log(result)
console.log(message)
// Manage errors
if (result == "error") {
console.log("[x] Error in " + name + ".js")
alert("Error in the subroutine " + name + " at " + path + ": " + message)
}
else {
console.log("[+] Message from " + name + " parsed")
}
// Send the response back solving promises if any
solved = null
if (message.toString().includes("Promise")) {
// In case of promise, solve it and send it
message.then((value) => {
console.log("Promise resolved: " + value)
let payload = '{ "type": "response", "id": "' + msg_id + '", "result": "' + result + '", "message": "' + value + '"}'
console.log("[*] Sending response: " + JSON.stringify(payload))
subroutines[name].postMessage(JSON.stringify(payload))
})
} else {
// In case of normal message, send it
let payload = '{ "type": "response", "id": "' + msg_id + '", "result": "' + result + '", "message": "' + message + '"}'
console.log("[*] Sending response: " + JSON.stringify(payload))
subroutines[name].postMessage(JSON.stringify(payload))
}
})
}
// NOTE Parsing the response
function parseMessage (j_response, sender) {
// Schema being like:
/*
{
"type": "render|info|error",
[...] (properties of the above)
}
*/
console.log("Parsing message from " + sender + ": " + JSON.stringify(j_response))
let type = j_response.type
let id = j_response.id
if (type == "error") {
console.log("[x] Error in " + sender + ".js")
console.log(j_response.message)
return ["error", j_response.message]
}
// NOTE Rendering an element (overwriting it if exists)
else if (type == "render") {
let element = j_response.element
console.log("[*] Rendering")
// Loading element to replace
console.log("Element: " + element)
// Normalizing and loading the HTML to insert
let newHTML = j_response.html.replace("'", '"')
console.log("HTML: " + newHTML)
// Executing the rendering command
let renderCmd = "document.getElementById('" + j_response.element + "').innerHTML += '" + newHTML + "'"
console.log(renderCmd)
mainWindow.webContents.executeJavaScript(renderCmd)
console.log("[+] Rendered")
return ["ok", "Rendered"]
}
// NOTE Changing style of an existing element
else if (type == "style") {
let element = j_response.element
let property = j_response.property
let value = j_response.value
console.log("[*] Styling")
// Loading element to replace
console.log("Element: " + element)
// Normalizing and loading the HTML to insert
let newProperty = j_response.property.replace("'", '"')
console.log("Property: " + newProperty)
// Executing the rendering command
let renderCmd = "document.getElementById('" + element + "').style." + property + "='" + value + "'"
console.log(renderCmd)
mainWindow.webContents.executeJavaScript(renderCmd)
console.log("[+] Styled")
return ["ok", "Styled"]
}
// NOTE Executing a js command
// REVIEW Remember to sanitize it
else if (j_response.type == "exec") {
let command = j_response.command
console.log("[*] Executing")
console.log(command)
mainWindow.webContents.executeJavaScript(command + ";")
console.log("[+] Executed")
return ["ok", "Executed"]
}
// NOTE Getting an existing element
else if (type == "get") {
let element = j_response.element
console.log("[*] Getting " + element + " for renderer")
let cmd = "document.getElementById('" + element + "');"
console.log(cmd)
let response = mainWindow.webContents.executeJavaScript("document.getElementById('" + element + "').innerHTML;")
console.log("[+] Got " + element + " for renderer")
console.log('[>] Returning ' + response)
return ["ok", response]
}
else if (type == "info") {
console.log("[i] Info from " + sender)
console.log(j_response.message)
return ["ok", "Info"]
}
}
// !SECTION Subroutine management
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow
// Create a new BrowserWindow when `app` is ready
// NOTE This is just a definition which will be executed later
function createWindow () {
mainWindow = new BrowserWindow({
width: 1280, height: 720,
webPreferences: {
// --- !! IMPORTANT !! ---
// Disable 'contextIsolation' to allow 'nodeIntegration'
// 'contextIsolation' defaults to "true" as from Electron v12
contextIsolation: false,
nodeIntegration: true
}
})
// NOTE Load index.html into the new BrowserWindow
mainWindow.loadFile('index.html')
// Open DevTools - Remove for PRODUCTION!
//mainWindow.webContents.openDevTools();
// NOTE Listen for window being closed
mainWindow.on('closed', () => {
mainWindow = null
})
// NOTE Once the window is loaded, start the subroutines
// INFO: graphics subroutine is responsible for the loading of the graphics
start_subroutine("template", "./worker_template.js", { })
}
// NOTE Listener for app ready that will execute the createWindow function
app.on('ready', createWindow)
// NOTE Quit when all windows are closed - (Not macOS - Darwin)
app.on('window-all-closed', () => {
// also on mac
app.quit()
})
// NOTE When app icon is clicked and app is running, (macOS) recreate the BrowserWindow
app.on('activate', () => {
if (mainWindow === null) createWindow()
})