mirror of
https://github.com/tcsenpai/Spin.git
synced 2025-06-03 18:00:18 +00:00
193 lines
6.4 KiB
JavaScript
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()
|
|
})
|