Add proper Electron launcher and building process #6
							
								
								
									
										247
									
								
								startHandler.js
									
									
									
									
									
								
							
							
						
						
									
										247
									
								
								startHandler.js
									
									
									
									
									
								
							@@ -1,104 +1,127 @@
 | 
			
		||||
const { app, BrowserWindow, ipcMain, Tray, Menu, nativeImage, MenuItem, dialog } = require('electron')
 | 
			
		||||
const { app, BrowserWindow, ipcMain, Tray, Menu, MenuItem, dialog } = require('electron')
 | 
			
		||||
const path = require('path')
 | 
			
		||||
const fs = require('fs')
 | 
			
		||||
const _ = require("underscore")
 | 
			
		||||
const open = require('open');
 | 
			
		||||
const childProcess = require('child_process');
 | 
			
		||||
const http = require('http');
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const packageJson = JSON.parse(fs.readFileSync("package.json"))
 | 
			
		||||
 | 
			
		||||
// a minimal config
 | 
			
		||||
let configObject = {
 | 
			
		||||
    language: "en_uk",
 | 
			
		||||
    startMinimised: false,
 | 
			
		||||
    port: 3000
 | 
			
		||||
	language: "en_uk",
 | 
			
		||||
	startMinimised: false,
 | 
			
		||||
	port: 3000
 | 
			
		||||
}
 | 
			
		||||
if (!fs.existsSync("config.json")) {
 | 
			
		||||
    fs.writeFileSync("config.json", "{}");
 | 
			
		||||
	fs.writeFileSync("config.json", "{}");
 | 
			
		||||
}
 | 
			
		||||
const tempJsonText = JSON.parse(fs.readFileSync("config.json", "utf8"));
 | 
			
		||||
configObject = _.extend(configObject, tempJsonText);
 | 
			
		||||
fs.writeFileSync("config.json", JSON.stringify(configObject));
 | 
			
		||||
 | 
			
		||||
let serverStatus = "Starting"
 | 
			
		||||
 | 
			
		||||
const processArgs = process.argv;
 | 
			
		||||
// Check if --headless is passed as an argument
 | 
			
		||||
if (processArgs.includes("--headless")) {
 | 
			
		||||
    startServer()
 | 
			
		||||
	startServer()
 | 
			
		||||
 | 
			
		||||
} else {
 | 
			
		||||
    // Start electron 
 | 
			
		||||
    app.whenReady().then(() => {
 | 
			
		||||
        startServer()
 | 
			
		||||
        createTray()
 | 
			
		||||
        createWindow()
 | 
			
		||||
    })
 | 
			
		||||
    
 | 
			
		||||
    ipcMain.on('info', function () {
 | 
			
		||||
        if (win) {
 | 
			
		||||
            win.webContents.send('info', { "appStatus": "Testing", "appURL": "http://127.0.0.1:" + configObject.port, "appName": "openCountdown " + packageJson.version, "startMinimised": configObject.startMinimised, "port": configObject.port })
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
    
 | 
			
		||||
    ipcMain.on('skeleton-close', function (req, cb) {
 | 
			
		||||
        trayQuit()
 | 
			
		||||
    })
 | 
			
		||||
    
 | 
			
		||||
    ipcMain.on('skeleton-minimize', function (req, cb) {
 | 
			
		||||
        win.hide()
 | 
			
		||||
    })
 | 
			
		||||
    
 | 
			
		||||
    ipcMain.on('skeleton-launch-gui', function () {
 | 
			
		||||
        launchUI()
 | 
			
		||||
    })
 | 
			
		||||
    
 | 
			
		||||
    ipcMain.on('skeleton-start-minimised', function (e, msg) {
 | 
			
		||||
        configObject.startMinimised = msg
 | 
			
		||||
        fs.writeFileSync("config.json", JSON.stringify(configObject));
 | 
			
		||||
    })
 | 
			
		||||
    
 | 
			
		||||
    ipcMain.on('skeleton-bind-port', function (e, msg) {
 | 
			
		||||
        configObject.port = msg
 | 
			
		||||
        console.log("Update port")
 | 
			
		||||
        fs.writeFileSync("config.json", JSON.stringify(configObject));
 | 
			
		||||
        dialog.showMessageBoxSync({
 | 
			
		||||
            message: "Port changed. Restart openCountdown to apply change.",
 | 
			
		||||
            buttons: ["OK"]})
 | 
			
		||||
    })
 | 
			
		||||
	// Start electron 
 | 
			
		||||
	app.whenReady().then(() => {
 | 
			
		||||
		startServer()
 | 
			
		||||
		createTray()
 | 
			
		||||
		createWindow()
 | 
			
		||||
		setInterval(() => {
 | 
			
		||||
			http.get('http://127.0.0.1:' + configObject.port + "/api/v1/system", (resp) => {
 | 
			
		||||
				let data = '';
 | 
			
		||||
 | 
			
		||||
				// A chunk of data has been received.
 | 
			
		||||
				resp.on('data', (chunk) => {
 | 
			
		||||
				  data += chunk;
 | 
			
		||||
				});
 | 
			
		||||
			      
 | 
			
		||||
				// The whole response has been received. Print out the result.
 | 
			
		||||
				resp.on('end', () => {
 | 
			
		||||
				  let parsed = JSON.parse(data)
 | 
			
		||||
				  serverStatus = "Running"
 | 
			
		||||
				});
 | 
			
		||||
			}).on("error", (err) => {
 | 
			
		||||
				console.log("Error: " + err.message);
 | 
			
		||||
			});
 | 
			
		||||
		}, 1000);
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	ipcMain.on('info', function () {
 | 
			
		||||
		if (win) {
 | 
			
		||||
			win.webContents.send('info', { "appStatus": serverStatus, "appURL": "http://127.0.0.1:" + configObject.port, "appName": "openCountdown " + packageJson.version, "startMinimised": configObject.startMinimised, "port": configObject.port })
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	ipcMain.on('skeleton-close', function (req, cb) {
 | 
			
		||||
		trayQuit()
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	ipcMain.on('skeleton-minimize', function (req, cb) {
 | 
			
		||||
		win.hide()
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	ipcMain.on('skeleton-launch-gui', function () {
 | 
			
		||||
		launchUI()
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	ipcMain.on('skeleton-start-minimised', function (e, msg) {
 | 
			
		||||
		configObject.startMinimised = msg
 | 
			
		||||
		fs.writeFileSync("config.json", JSON.stringify(configObject));
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
	ipcMain.on('skeleton-bind-port', function (e, msg) {
 | 
			
		||||
		configObject.port = msg
 | 
			
		||||
		console.log("Update port")
 | 
			
		||||
		fs.writeFileSync("config.json", JSON.stringify(configObject));
 | 
			
		||||
		dialog.showMessageBoxSync({
 | 
			
		||||
			message: "Port changed. Restart openCountdown to apply change.",
 | 
			
		||||
			buttons: ["OK"]
 | 
			
		||||
		})
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var win, tray = null;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
const createWindow = () => {
 | 
			
		||||
    win = new BrowserWindow({
 | 
			
		||||
        width: 370,
 | 
			
		||||
        height: 500,
 | 
			
		||||
        transparent: true,
 | 
			
		||||
        frame: false,
 | 
			
		||||
        resizable: false,
 | 
			
		||||
        icon: path.join(__dirname, 'static/logo/faviconLogo.svg'),
 | 
			
		||||
        webPreferences: {
 | 
			
		||||
            pageVisibility: true,
 | 
			
		||||
            nodeIntegration: true,
 | 
			
		||||
            contextIsolation: true,
 | 
			
		||||
            preload: path.join(__dirname, 'electronAssets/windowPreload.js'),
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
	win = new BrowserWindow({
 | 
			
		||||
		width: 370,
 | 
			
		||||
		height: 500,
 | 
			
		||||
		transparent: true,
 | 
			
		||||
		frame: false,
 | 
			
		||||
		resizable: false,
 | 
			
		||||
		icon: path.join(__dirname, 'static/logo/faviconLogo.svg'),
 | 
			
		||||
		webPreferences: {
 | 
			
		||||
			pageVisibility: true,
 | 
			
		||||
			nodeIntegration: true,
 | 
			
		||||
			contextIsolation: true,
 | 
			
		||||
			preload: path.join(__dirname, 'electronAssets/windowPreload.js'),
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    win.loadFile('electronAssets/index.html')
 | 
			
		||||
    if (configObject.startMinimised) {
 | 
			
		||||
        win.hide()
 | 
			
		||||
    }
 | 
			
		||||
	win.loadFile('electronAssets/index.html')
 | 
			
		||||
	if (configObject.startMinimised) {
 | 
			
		||||
		win.hide()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function createTray() {
 | 
			
		||||
    tray = new Tray('static/logo/faviconLogo.png')
 | 
			
		||||
    tray.setIgnoreDoubleClickEvents(true)
 | 
			
		||||
	tray = new Tray('static/logo/faviconLogo.png')
 | 
			
		||||
	tray.setIgnoreDoubleClickEvents(true)
 | 
			
		||||
 | 
			
		||||
    const menu = new Menu()
 | 
			
		||||
	const menu = new Menu()
 | 
			
		||||
	menu.append(
 | 
			
		||||
		new MenuItem({
 | 
			
		||||
			label: 'Show window',
 | 
			
		||||
@@ -114,78 +137,78 @@ function createTray() {
 | 
			
		||||
	menu.append(
 | 
			
		||||
		new MenuItem({
 | 
			
		||||
			label: 'Quit',
 | 
			
		||||
            accelerator: 'Command+Q',
 | 
			
		||||
			accelerator: 'Command+Q',
 | 
			
		||||
			click: trayQuit,
 | 
			
		||||
		})
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
    tray.setToolTip('openCountdown ' + packageJson.version)
 | 
			
		||||
    tray.setContextMenu(menu)
 | 
			
		||||
	tray.setToolTip('openCountdown ' + packageJson.version)
 | 
			
		||||
	tray.setContextMenu(menu)
 | 
			
		||||
 | 
			
		||||
    tray.on('click', function (e) {
 | 
			
		||||
        if (win.isVisible()) {
 | 
			
		||||
            win.hide()
 | 
			
		||||
        } else {
 | 
			
		||||
            win.show()
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
	tray.on('click', function (e) {
 | 
			
		||||
		if (win.isVisible()) {
 | 
			
		||||
			win.hide()
 | 
			
		||||
		} else {
 | 
			
		||||
			win.show()
 | 
			
		||||
		}
 | 
			
		||||
	});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function showScreen(){
 | 
			
		||||
    win.show()
 | 
			
		||||
function showScreen() {
 | 
			
		||||
	win.show()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function launchUI(){
 | 
			
		||||
    open("http://127.0.0.1:" + configObject.port)
 | 
			
		||||
function launchUI() {
 | 
			
		||||
	open("http://127.0.0.1:" + configObject.port)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function trayQuit(){
 | 
			
		||||
    let options  = {
 | 
			
		||||
        buttons: ["Yes","No"],
 | 
			
		||||
        message: "Do you really want to quit openCountdown?"
 | 
			
		||||
       }
 | 
			
		||||
    let response = dialog.showMessageBoxSync(options)
 | 
			
		||||
    if(response == 0){
 | 
			
		||||
        srvProc.kill("SIGINT")
 | 
			
		||||
        setTimeout(app.quit, 1000)
 | 
			
		||||
    }
 | 
			
		||||
function trayQuit() {
 | 
			
		||||
	let options = {
 | 
			
		||||
		buttons: ["Yes", "No"],
 | 
			
		||||
		message: "Do you really want to quit openCountdown?"
 | 
			
		||||
	}
 | 
			
		||||
	let response = dialog.showMessageBoxSync(options)
 | 
			
		||||
	if (response == 0) {
 | 
			
		||||
		srvProc.kill("SIGINT")
 | 
			
		||||
		setTimeout(app.quit, 1000)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
// taken from https://stackoverflow.com/a/22649812/11317151
 | 
			
		||||
function runScript(scriptPath, callback, valueCb) {
 | 
			
		||||
 | 
			
		||||
    // keep track of whether callback has been invoked to prevent multiple invocations
 | 
			
		||||
    var invoked = false;
 | 
			
		||||
	// keep track of whether callback has been invoked to prevent multiple invocations
 | 
			
		||||
	var invoked = false;
 | 
			
		||||
 | 
			
		||||
    var process = childProcess.fork(scriptPath);
 | 
			
		||||
	var process = childProcess.fork(scriptPath);
 | 
			
		||||
 | 
			
		||||
    valueCb(process)
 | 
			
		||||
    // listen for errors as they may prevent the exit event from firing
 | 
			
		||||
    process.on('error', function (err) {
 | 
			
		||||
        if (invoked) return;
 | 
			
		||||
        invoked = true;
 | 
			
		||||
        callback(err);
 | 
			
		||||
    });
 | 
			
		||||
    // execute the callback once the process has finished running
 | 
			
		||||
    process.on('exit', function (code) {
 | 
			
		||||
        if (invoked) return;
 | 
			
		||||
        invoked = true;
 | 
			
		||||
        // var err = code === 0 ? null : new Error('exit code ' + code);
 | 
			
		||||
        callback(code);
 | 
			
		||||
    });
 | 
			
		||||
	valueCb(process)
 | 
			
		||||
	// listen for errors as they may prevent the exit event from firing
 | 
			
		||||
	process.on('error', function (err) {
 | 
			
		||||
		if (invoked) return;
 | 
			
		||||
		invoked = true;
 | 
			
		||||
		callback(err);
 | 
			
		||||
	});
 | 
			
		||||
	// execute the callback once the process has finished running
 | 
			
		||||
	process.on('exit', function (code) {
 | 
			
		||||
		if (invoked) return;
 | 
			
		||||
		invoked = true;
 | 
			
		||||
		// var err = code === 0 ? null : new Error('exit code ' + code);
 | 
			
		||||
		callback(code);
 | 
			
		||||
	});
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
srvProc = null;
 | 
			
		||||
 | 
			
		||||
function setServer(process){
 | 
			
		||||
    srvProc = process
 | 
			
		||||
function setServer(process) {
 | 
			
		||||
	srvProc = process
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function startServer(){
 | 
			
		||||
    runScript(path.join(__dirname, 'index.js'), function (err) {
 | 
			
		||||
        if (err) throw err;
 | 
			
		||||
    }, setServer)
 | 
			
		||||
function startServer() {
 | 
			
		||||
	runScript(path.join(__dirname, 'index.js'), function (err) {
 | 
			
		||||
		if (err) throw err;
 | 
			
		||||
	}, setServer)
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user