Skip to content
This repository was archived by the owner on Feb 16, 2024. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
173 changes: 109 additions & 64 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ let elements = {};
let windowOptions = {};
let menus = {};
let quittingApp = false;
let didReady = false;

// Single instance
let lastWindowId = null;
Expand All @@ -30,66 +31,96 @@ function onReady () {
const screen = electron.screen
Menu.setApplicationMenu(null)

// Listen to screen events
screen.on('display-added', function() {
client.write(consts.targetIds.app, consts.eventNames.displayEventAdded, {displays: {all: screen.getAllDisplays(), primary: screen.getPrimaryDisplay()}})
})
screen.on('display-metrics-changed', function() {
client.write(consts.targetIds.app, consts.eventNames.displayEventMetricsChanged, {displays: {all: screen.getAllDisplays(), primary: screen.getPrimaryDisplay()}})
})
screen.on('display-removed', function() {
client.write(consts.targetIds.app, consts.eventNames.displayEventRemoved, {displays: {all: screen.getAllDisplays(), primary: screen.getPrimaryDisplay()}})
})

const powerMonitor = electron.powerMonitor
// Listen to power events
powerMonitor.on('suspend', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventSuspend)
})

powerMonitor.on('resume', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventResume)
})

powerMonitor.on('on-ac', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventOnAC)
})

powerMonitor.on('on-battery', function () {
client.write(consts.targetIds.app, consts.eventNames.powerEventOnBattery)
})

powerMonitor.on('shutdown', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventShutdown)
})

powerMonitor.on('lock-screen', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventLockScreen)
})

powerMonitor.on('unlock-screen', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventUnlockScreen)
})
if (!didReady) {
didReady = true
// Listen to screen events
screen.on('display-added', function() {
client.write(consts.targetIds.app, consts.eventNames.displayEventAdded, {displays: {all: screen.getAllDisplays(), primary: screen.getPrimaryDisplay()}})
})
screen.on('display-metrics-changed', function() {
client.write(consts.targetIds.app, consts.eventNames.displayEventMetricsChanged, {displays: {all: screen.getAllDisplays(), primary: screen.getPrimaryDisplay()}})
})
screen.on('display-removed', function() {
client.write(consts.targetIds.app, consts.eventNames.displayEventRemoved, {displays: {all: screen.getAllDisplays(), primary: screen.getPrimaryDisplay()}})
})

powerMonitor.on('user-did-become-active', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventUserDidBecomeActive)
})
// Listen on main ipcMain
ipcMain.on(consts.eventNames.ipcEventMessage, (event, arg) => {
let payload = {message: arg.message};
if (typeof arg.callbackId !== "undefined") payload.callbackId = arg.callbackId;
client.write(arg.targetID, consts.eventNames.windowEventMessage, payload)
});
ipcMain.on(consts.eventNames.ipcEventMessageCallback, (event, arg) => {
let payload = {message: arg.message};
if (typeof arg.callbackId !== "undefined") payload.callbackId = arg.callbackId;
client.write(arg.targetID, consts.eventNames.windowEventMessageCallback, payload)
});
ipcMain.handle(consts.eventNames.sessionCmdSetWillDownloadExtensions, (event, possibleExtensions) => {
BrowserWindow.getFocusedWindow().webContents.session.on('will-download', (event, item) => {
let extension = item.getFilename().split('.').pop()
let extensionLabel = possibleExtensions[extension] ?? `Fichier ${extension}`
item.setSaveDialogOptions({
filters: [
{name: extensionLabel, extensions: [extension]},
],
});
});
});

powerMonitor.on('user-did-resign-active', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventUserDidResignActive)
})
ipcMain.handle(consts.eventNames.dialogShowOpen, async (event, options) => {
const res = await dialog.showOpenDialog(options)
return res
})
ipcMain.handle(consts.eventNames.dialogShowSave, async (event, options) => {
const res = await dialog.showSaveDialog(options)
return res
})
ipcMain.handle(consts.eventNames.desktopCapturerGetSources, async () => {
const res = await electron.desktopCapturer.getSources({ types: ['window', 'screen'] })
return res
})
ipcMain.handle(consts.eventNames.webContentsMediaSourceID, async () => {
return getLastWindow().getMediaSourceId()
})

// Listen on main ipcMain
ipcMain.on(consts.eventNames.ipcEventMessage, (event, arg) => {
let payload = {message: arg.message};
if (typeof arg.callbackId !== "undefined") payload.callbackId = arg.callbackId;
client.write(arg.targetID, consts.eventNames.windowEventMessage, payload)
});
ipcMain.on(consts.eventNames.ipcEventMessageCallback, (event, arg) => {
let payload = {message: arg.message};
if (typeof arg.callbackId !== "undefined") payload.callbackId = arg.callbackId;
client.write(arg.targetID, consts.eventNames.windowEventMessageCallback, payload)
});
const powerMonitor = electron.powerMonitor
// Listen to power events
powerMonitor.on('suspend', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventSuspend)
})

powerMonitor.on('resume', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventResume)
})

powerMonitor.on('on-ac', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventOnAC)
})

powerMonitor.on('on-battery', function () {
client.write(consts.targetIds.app, consts.eventNames.powerEventOnBattery)
})

powerMonitor.on('shutdown', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventShutdown)
})

powerMonitor.on('lock-screen', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventLockScreen)
})

powerMonitor.on('unlock-screen', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventUnlockScreen)
})

powerMonitor.on('user-did-become-active', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventUserDidBecomeActive)
})

powerMonitor.on('user-did-resign-active', function() {
client.write(consts.targetIds.app, consts.eventNames.powerEventUserDidResignActive)
})
}

// Read from client
rl.on('line', function(line){
Expand Down Expand Up @@ -366,15 +397,16 @@ function onReady () {

// start begins listening to go-astilectron.
function start(address = process.argv[2]) {
client.init(address);
rl = readline.createInterface({ input: client.socket });
client.init(address, function () {
rl = readline.createInterface({ input: client.socket });
if (app.isReady()) {
onReady();
} else {
app.on("ready", onReady);
}
});

app.on("before-quit", beforeQuit);
if (app.isReady()) {
onReady();
} else {
app.on("ready", onReady);
}
app.on("window-all-closed", app.quit);
}

Expand Down Expand Up @@ -473,6 +505,7 @@ function windowCreate(json) {
}
json.windowOptions.webPreferences.contextIsolation = false
json.windowOptions.webPreferences.nodeIntegration = true
json.windowOptions.webPreferences.enableRemoteModule = true
elements[json.targetID] = new BrowserWindow(json.windowOptions)
windowOptions[json.targetID] = json.windowOptions
if (typeof json.windowOptions.proxy !== "undefined") {
Expand Down Expand Up @@ -511,6 +544,9 @@ function windowCreateFinish(json) {
elements[json.targetID].on('closed', () => {
client.write(json.targetID, consts.eventNames.windowEventClosed)
delete elements[json.targetID]
setTimeout(() => {
Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this part is consistent with apps that use multiple windows. Why do you need this logic?

app.quit()
}, 1000)
})
elements[json.targetID].on('enter-full-screen', () => { client.write(json.targetID, consts.eventNames.windowEventEnterFullScreen, {windowOptions: {fullscreen: true}})} )
elements[json.targetID].on('focus', () => { client.write(json.targetID, consts.eventNames.windowEventFocus) })
Expand Down Expand Up @@ -621,6 +657,15 @@ function windowCreateFinish(json) {
url: url
})
})
elements[json.targetID].webContents.on('render-process-gone', (event, details) => {
if (details.reason !== 'clean-exit') {
console.error('Renderer process crashed. Reloading the window...');
// Using a small delay before reloading can help prevent potential race conditions
setTimeout(() => {
elements[json.targetID].reload();
}, 500);
}
})
if (typeof json.windowOptions.appDetails !== "undefined" && process.platform === "win32"){
elements[json.targetID].setThumbarButtons([]);
elements[json.targetID].setAppDetails(json.windowOptions.appDetails);
Expand Down
9 changes: 9 additions & 0 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@
const { app } = require("electron");
const { start, getLastWindow, client, consts } = require("./index");

process
.on('unhandledRejection', (reason, p) => {
//console.error(reason, 'Unhandled Rejection at Promise', p);
})
.on('uncaughtException', err => {
//console.error(err, 'Uncaught Exception thrown');
//process.exit(1);
});

// edge case when the program is launched without arguments
if (process.argv.length == 1) {
app.requestSingleInstanceLock();
Expand Down
11 changes: 7 additions & 4 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ const url = require("url");
// Client can read/write messages from a TCP server
class Client {
// init initializes the Client
init(addr) {
init(addr, onConnect) {
let u = url.parse("tcp://" + addr, false, false);
this.socket = new net.Socket();
this.socket.connect(u.port, u.hostname, function() {});
this.socket.connect(u.port, u.hostname, onConnect);
this.socket.on("close", function() {
process.exit();
});
// Socket closed, try to reconnect
setTimeout(() => {
this.init(addr, onConnect);
}, 200)
}.bind(this));
this.socket.on("error", function(err) {
// Prevent Unhandled Exception resulting from TCP Error
console.error(err);
Expand Down
7 changes: 6 additions & 1 deletion src/consts.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ module.exports = {
displayEventAdded: "display.event.added",
displayEventMetricsChanged: "display.event.metrics.changed",
displayEventRemoved: "display.event.removed",
dialogShowOpen: "dialog.show.open",
dialogShowSave: "dialog.show.save",
dockCmdBounce: "dock.cmd.bounce",
dockCmdBounceDownloads: "dock.cmd.bounce.downloads",
dockCmdCancelBounce: "dock.cmd.cancel.bounce",
Expand Down Expand Up @@ -64,6 +66,7 @@ module.exports = {
sessionCmdClearCache: "session.cmd.clear.cache",
sessionCmdFlushStorage: "session.cmd.flush.storage",
sessionCmdLoadExtension: "session.cmd.load.extension",
sessionCmdSetWillDownloadExtensions: "session.cmd.set-will-download-extensions",
sessionEventClearedCache: "session.event.cleared.cache",
sessionEventWillDownload: "session.event.will.download",
sessionEventFlushedStorage: "session.event.flushed.storage",
Expand Down Expand Up @@ -143,7 +146,9 @@ module.exports = {
windowEventUnresponsive: "window.event.unresponsive",
windowEventWebContentsExecutedJavaScript: "window.event.web.contents.executed.javascript",
windowEventWillMove: "window.event.will.move",
windowEventUpdatedCustomOptions: "window.event.updated.custom.options"
windowEventUpdatedCustomOptions: "window.event.updated.custom.options",
desktopCapturerGetSources: "desktopCapturer.sources",
webContentsMediaSourceID: "webContents.mediaSourceID",
},
targetIds: {
app: 'app',
Expand Down