2025-04-18 18:28:25 -05:00
|
|
|
import { BrowserWindow, ipcMain, IpcMainEvent, nativeImage, Tray, Menu, dialog, shell } from 'electron';
|
2025-02-13 11:21:49 -06:00
|
|
|
import { Opcode, PlaybackErrorMessage, PlaybackUpdateMessage, VolumeUpdateMessage } from 'common/Packets';
|
2024-12-09 00:56:55 -06:00
|
|
|
import { DiscoveryService } from 'common/DiscoveryService';
|
|
|
|
import { TcpListenerService } from 'common/TcpListenerService';
|
|
|
|
import { WebSocketListenerService } from 'common/WebSocketListenerService';
|
|
|
|
import { NetworkService } from 'common/NetworkService';
|
2023-06-20 08:45:01 +02:00
|
|
|
import { Updater } from './Updater';
|
2024-01-04 12:38:39 +01:00
|
|
|
import * as os from 'os';
|
|
|
|
import * as path from 'path';
|
2024-11-11 12:24:17 -06:00
|
|
|
import * as log4js from "log4js";
|
2024-09-06 15:44:20 -05:00
|
|
|
import yargs from 'yargs';
|
|
|
|
import { hideBin } from 'yargs/helpers';
|
2025-01-06 20:35:57 -06:00
|
|
|
import { ToastIcon } from 'common/components/Toast';
|
2024-12-09 00:56:55 -06:00
|
|
|
const cp = require('child_process');
|
2023-06-20 08:45:01 +02:00
|
|
|
|
2024-12-09 00:56:55 -06:00
|
|
|
export class Main {
|
2024-09-06 15:44:20 -05:00
|
|
|
static shouldOpenMainWindow = true;
|
2024-11-14 01:04:00 -06:00
|
|
|
static startFullscreen = false;
|
2023-12-06 13:03:23 +01:00
|
|
|
static playerWindow: Electron.BrowserWindow;
|
2023-06-20 08:45:01 +02:00
|
|
|
static mainWindow: Electron.BrowserWindow;
|
|
|
|
static application: Electron.App;
|
2023-12-06 11:50:26 +01:00
|
|
|
static tcpListenerService: TcpListenerService;
|
|
|
|
static webSocketListenerService: WebSocketListenerService;
|
2023-06-20 08:45:01 +02:00
|
|
|
static discoveryService: DiscoveryService;
|
|
|
|
static tray: Tray;
|
2024-11-11 12:24:17 -06:00
|
|
|
static logger: log4js.Logger;
|
2023-06-20 08:45:01 +02:00
|
|
|
|
2024-11-14 01:04:00 -06:00
|
|
|
private static toggleMainWindow() {
|
|
|
|
if (Main.mainWindow) {
|
|
|
|
Main.mainWindow.close();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Main.openMainWindow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-17 23:36:16 -06:00
|
|
|
private static async checkForUpdates(silent: boolean) {
|
|
|
|
if (Updater.updateDownloaded) {
|
2025-04-29 12:17:29 -05:00
|
|
|
Main.mainWindow?.webContents?.send("download-complete");
|
2024-11-17 23:36:16 -06:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
const updateAvailable = await Updater.checkForUpdates();
|
|
|
|
|
|
|
|
if (updateAvailable) {
|
2025-04-29 12:17:29 -05:00
|
|
|
Main.mainWindow?.webContents?.send("update-available");
|
2024-11-17 23:36:16 -06:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (!silent) {
|
|
|
|
await dialog.showMessageBox({
|
|
|
|
type: 'info',
|
|
|
|
title: 'Already up-to-date',
|
|
|
|
message: 'The application is already on the latest version.',
|
|
|
|
buttons: ['OK'],
|
|
|
|
defaultId: 0
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
if (!silent) {
|
|
|
|
await dialog.showMessageBox({
|
|
|
|
type: 'error',
|
|
|
|
title: 'Failed to check for updates',
|
|
|
|
message: err,
|
|
|
|
buttons: ['OK'],
|
|
|
|
defaultId: 0
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Main.logger.error('Failed to check for updates:', err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-06-20 08:45:01 +02:00
|
|
|
private static createTray() {
|
2024-12-09 00:56:55 -06:00
|
|
|
const icon = (process.platform === 'win32') ? path.join(__dirname, 'assets/icons/app/icon.ico') : path.join(__dirname, 'assets/icons/app/icon.png');
|
2023-06-20 08:45:01 +02:00
|
|
|
const trayicon = nativeImage.createFromPath(icon)
|
|
|
|
const tray = new Tray(trayicon.resize({ width: 16 }));
|
|
|
|
const contextMenu = Menu.buildFromTemplate([
|
2023-12-06 13:03:23 +01:00
|
|
|
{
|
2024-11-14 01:04:00 -06:00
|
|
|
label: 'Toggle window',
|
|
|
|
click: () => { Main.toggleMainWindow(); }
|
2023-12-06 13:03:23 +01:00
|
|
|
},
|
2023-06-20 08:45:01 +02:00
|
|
|
{
|
|
|
|
label: 'Check for updates',
|
2024-11-17 23:36:16 -06:00
|
|
|
click: async () => { await Main.checkForUpdates(false); },
|
2023-06-20 08:45:01 +02:00
|
|
|
},
|
2024-11-19 09:54:50 -06:00
|
|
|
{
|
|
|
|
label: 'About',
|
|
|
|
click: async () => {
|
2024-11-21 11:51:46 -06:00
|
|
|
let aboutMessage = `Version: ${Main.application.getVersion()}\n`;
|
|
|
|
|
|
|
|
if (Updater.getCommit()) {
|
|
|
|
aboutMessage += `Commit: ${Updater.getCommit()}\n`;
|
|
|
|
}
|
|
|
|
|
|
|
|
aboutMessage += `Release channel: ${Updater.releaseChannel}\n`;
|
2024-11-19 09:54:50 -06:00
|
|
|
|
|
|
|
if (Updater.releaseChannel !== 'stable') {
|
|
|
|
aboutMessage += `Release channel version: ${Updater.getChannelVersion()}\n`;
|
|
|
|
}
|
|
|
|
|
|
|
|
aboutMessage += `OS: ${process.platform} ${process.arch}\n`;
|
|
|
|
|
|
|
|
await dialog.showMessageBox({
|
|
|
|
type: 'info',
|
|
|
|
title: 'Fcast Receiver',
|
|
|
|
message: aboutMessage,
|
|
|
|
buttons: ['OK'],
|
|
|
|
defaultId: 0
|
|
|
|
});
|
|
|
|
},
|
|
|
|
},
|
2023-06-20 08:45:01 +02:00
|
|
|
{
|
|
|
|
type: 'separator',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Restart',
|
|
|
|
click: () => {
|
|
|
|
this.application.relaunch();
|
2024-11-11 12:24:17 -06:00
|
|
|
this.application.exit();
|
2023-06-20 08:45:01 +02:00
|
|
|
}
|
|
|
|
},
|
|
|
|
{
|
|
|
|
label: 'Quit',
|
|
|
|
click: () => {
|
|
|
|
this.application.quit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
])
|
2024-09-06 15:44:20 -05:00
|
|
|
|
2023-06-20 08:45:01 +02:00
|
|
|
tray.setContextMenu(contextMenu);
|
2024-11-14 01:15:21 -06:00
|
|
|
|
|
|
|
// Left-click opens up tray menu, unlike in Windows/Linux
|
|
|
|
if (process.platform !== 'darwin') {
|
|
|
|
tray.on('click', () => { Main.toggleMainWindow(); } );
|
|
|
|
}
|
|
|
|
|
2023-06-20 08:45:01 +02:00
|
|
|
this.tray = tray;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static onReady() {
|
|
|
|
Main.createTray();
|
|
|
|
|
|
|
|
Main.discoveryService = new DiscoveryService();
|
|
|
|
Main.discoveryService.start();
|
2024-09-06 15:44:20 -05:00
|
|
|
|
2023-12-06 11:50:26 +01:00
|
|
|
Main.tcpListenerService = new TcpListenerService();
|
|
|
|
Main.webSocketListenerService = new WebSocketListenerService();
|
|
|
|
|
2023-12-30 11:28:36 +01:00
|
|
|
const listeners = [Main.tcpListenerService, Main.webSocketListenerService];
|
2023-12-06 11:50:26 +01:00
|
|
|
listeners.forEach(l => {
|
2024-01-04 12:38:39 +01:00
|
|
|
l.emitter.on("play", async (message) => {
|
2023-12-06 13:03:23 +01:00
|
|
|
if (Main.playerWindow == null) {
|
|
|
|
Main.playerWindow = new BrowserWindow({
|
2023-12-06 11:50:26 +01:00
|
|
|
fullscreen: true,
|
|
|
|
autoHideMenuBar: true,
|
2024-10-21 20:51:07 +00:00
|
|
|
icon: path.join(__dirname, 'icon512.png'),
|
2023-12-06 11:50:26 +01:00
|
|
|
webPreferences: {
|
2023-12-06 13:03:23 +01:00
|
|
|
preload: path.join(__dirname, 'player/preload.js')
|
2023-12-06 11:50:26 +01:00
|
|
|
}
|
|
|
|
});
|
2024-09-06 15:44:20 -05:00
|
|
|
|
2023-12-06 13:03:23 +01:00
|
|
|
Main.playerWindow.setAlwaysOnTop(false, 'pop-up-menu');
|
|
|
|
Main.playerWindow.show();
|
2024-09-06 15:44:20 -05:00
|
|
|
|
2023-12-06 13:03:23 +01:00
|
|
|
Main.playerWindow.loadFile(path.join(__dirname, 'player/index.html'));
|
2024-01-04 12:38:39 +01:00
|
|
|
Main.playerWindow.on('ready-to-show', async () => {
|
2024-12-09 00:56:55 -06:00
|
|
|
Main.playerWindow?.webContents?.send("play", await NetworkService.proxyPlayIfRequired(message));
|
2023-12-06 13:03:23 +01:00
|
|
|
});
|
|
|
|
Main.playerWindow.on('closed', () => {
|
|
|
|
Main.playerWindow = null;
|
2023-12-06 11:50:26 +01:00
|
|
|
});
|
|
|
|
} else {
|
2024-12-09 00:56:55 -06:00
|
|
|
Main.playerWindow?.webContents?.send("play", await NetworkService.proxyPlayIfRequired(message));
|
2024-09-06 15:44:20 -05:00
|
|
|
}
|
2023-12-06 11:50:26 +01:00
|
|
|
});
|
2024-09-06 15:44:20 -05:00
|
|
|
|
2023-12-06 13:03:23 +01:00
|
|
|
l.emitter.on("pause", () => Main.playerWindow?.webContents?.send("pause"));
|
|
|
|
l.emitter.on("resume", () => Main.playerWindow?.webContents?.send("resume"));
|
2024-09-06 15:44:20 -05:00
|
|
|
|
2023-12-06 11:50:26 +01:00
|
|
|
l.emitter.on("stop", () => {
|
2024-11-21 00:40:15 -06:00
|
|
|
Main.playerWindow?.close();
|
|
|
|
Main.playerWindow = null;
|
2023-12-06 11:50:26 +01:00
|
|
|
});
|
2024-09-06 15:44:20 -05:00
|
|
|
|
2023-12-06 13:03:23 +01:00
|
|
|
l.emitter.on("seek", (message) => Main.playerWindow?.webContents?.send("seek", message));
|
|
|
|
l.emitter.on("setvolume", (message) => Main.playerWindow?.webContents?.send("setvolume", message));
|
2023-12-07 16:10:18 +01:00
|
|
|
l.emitter.on("setspeed", (message) => Main.playerWindow?.webContents?.send("setspeed", message));
|
2025-01-06 20:35:57 -06:00
|
|
|
|
2025-04-25 14:04:59 -05:00
|
|
|
l.emitter.on('connect', (message) => {
|
|
|
|
Main.mainWindow?.webContents?.send('connect', message);
|
|
|
|
Main.playerWindow?.webContents?.send('connect', message);
|
|
|
|
});
|
|
|
|
l.emitter.on('disconnect', (message) => {
|
|
|
|
Main.mainWindow?.webContents?.send('disconnect', message);
|
|
|
|
Main.playerWindow?.webContents?.send('disconnect', message);
|
|
|
|
});
|
|
|
|
l.emitter.on('ping', (message) => {
|
|
|
|
Main.mainWindow?.webContents?.send('ping', message);
|
|
|
|
Main.playerWindow?.webContents?.send('ping', message);
|
|
|
|
});
|
2025-04-29 11:57:25 -05:00
|
|
|
l.emitter.on('pong', (message) => {
|
|
|
|
Main.mainWindow?.webContents?.send('pong', message);
|
|
|
|
Main.playerWindow?.webContents?.send('pong', message);
|
|
|
|
});
|
2023-12-06 11:50:26 +01:00
|
|
|
l.start();
|
2023-06-20 08:45:01 +02:00
|
|
|
|
2023-12-07 16:10:18 +01:00
|
|
|
ipcMain.on('send-playback-error', (event: IpcMainEvent, value: PlaybackErrorMessage) => {
|
2023-12-30 10:55:30 +01:00
|
|
|
l.send(Opcode.PlaybackError, value);
|
2023-12-07 16:10:18 +01:00
|
|
|
});
|
|
|
|
|
2023-12-06 11:50:26 +01:00
|
|
|
ipcMain.on('send-playback-update', (event: IpcMainEvent, value: PlaybackUpdateMessage) => {
|
2023-12-30 10:55:30 +01:00
|
|
|
l.send(Opcode.PlaybackUpdate, value);
|
2023-12-06 11:50:26 +01:00
|
|
|
});
|
2024-09-06 15:44:20 -05:00
|
|
|
|
2023-12-06 11:50:26 +01:00
|
|
|
ipcMain.on('send-volume-update', (event: IpcMainEvent, value: VolumeUpdateMessage) => {
|
2023-12-30 10:55:30 +01:00
|
|
|
l.send(Opcode.VolumeUpdate, value);
|
2023-12-06 11:50:26 +01:00
|
|
|
});
|
2025-04-25 14:04:59 -05:00
|
|
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
ipcMain.on('send-session-message', (event: IpcMainEvent, value: any) => {
|
|
|
|
l.send(value.opcode, value.message);
|
|
|
|
});
|
|
|
|
|
|
|
|
ipcMain.on('disconnect-device', (event: IpcMainEvent, value: string) => {
|
|
|
|
l.disconnect(value);
|
|
|
|
});
|
2025-04-22 17:28:02 -05:00
|
|
|
});
|
2024-11-17 23:12:24 -06:00
|
|
|
|
2025-04-22 17:28:02 -05:00
|
|
|
ipcMain.on('send-download-request', async () => {
|
|
|
|
if (!Updater.isDownloading) {
|
|
|
|
try {
|
|
|
|
await Updater.downloadUpdate();
|
2025-04-29 12:17:29 -05:00
|
|
|
Main.mainWindow?.webContents?.send("download-complete");
|
2025-04-22 17:28:02 -05:00
|
|
|
} catch (err) {
|
|
|
|
await dialog.showMessageBox({
|
|
|
|
type: 'error',
|
|
|
|
title: 'Failed to download update',
|
|
|
|
message: err,
|
|
|
|
buttons: ['OK'],
|
|
|
|
defaultId: 0
|
|
|
|
});
|
|
|
|
|
|
|
|
Main.logger.error('Failed to download update:', err);
|
2025-04-29 12:17:29 -05:00
|
|
|
Main.mainWindow?.webContents?.send("download-failed");
|
2024-11-17 23:12:24 -06:00
|
|
|
}
|
2025-04-22 17:28:02 -05:00
|
|
|
}
|
|
|
|
});
|
2024-11-17 23:12:24 -06:00
|
|
|
|
2025-04-22 17:28:02 -05:00
|
|
|
ipcMain.on('send-restart-request', async () => {
|
|
|
|
Updater.restart();
|
2023-06-20 08:45:01 +02:00
|
|
|
});
|
|
|
|
|
2024-11-17 23:12:24 -06:00
|
|
|
ipcMain.handle('updater-progress', async () => { return Updater.updateProgress; });
|
|
|
|
|
2024-11-04 09:17:20 -06:00
|
|
|
ipcMain.handle('is-full-screen', async () => {
|
|
|
|
const window = Main.playerWindow;
|
|
|
|
if (!window) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
return window.isFullScreen();
|
|
|
|
});
|
|
|
|
|
2023-06-20 08:45:01 +02:00
|
|
|
ipcMain.on('toggle-full-screen', () => {
|
2023-12-06 13:03:23 +01:00
|
|
|
const window = Main.playerWindow;
|
2023-06-20 08:45:01 +02:00
|
|
|
if (!window) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
window.setFullScreen(!window.isFullScreen());
|
|
|
|
});
|
|
|
|
|
|
|
|
ipcMain.on('exit-full-screen', () => {
|
2023-12-06 13:03:23 +01:00
|
|
|
const window = Main.playerWindow;
|
2023-06-20 08:45:01 +02:00
|
|
|
if (!window) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
window.setFullScreen(false);
|
|
|
|
});
|
2023-12-06 13:03:23 +01:00
|
|
|
|
2025-04-29 13:03:10 -05:00
|
|
|
ipcMain.handle('get-sessions', () => {
|
|
|
|
return [].concat(Main.tcpListenerService.getSessions(), Main.webSocketListenerService.getSessions());
|
|
|
|
});
|
|
|
|
|
2025-04-30 10:17:20 -05:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
|
|
ipcMain.on('network-changed', (event: IpcMainEvent, value: any) => {
|
|
|
|
Main.mainWindow?.webContents?.send("device-info", { name: os.hostname(), interfaces: value });
|
|
|
|
});
|
|
|
|
|
2023-12-06 13:03:23 +01:00
|
|
|
if (Main.shouldOpenMainWindow) {
|
|
|
|
Main.openMainWindow();
|
|
|
|
}
|
2024-11-17 23:12:24 -06:00
|
|
|
|
|
|
|
if (Updater.updateError) {
|
|
|
|
dialog.showMessageBox({
|
|
|
|
type: 'error',
|
|
|
|
title: 'Error applying update',
|
|
|
|
message: 'Please try again later or visit https://fcast.org to update.',
|
|
|
|
buttons: ['OK'],
|
|
|
|
defaultId: 0
|
|
|
|
});
|
|
|
|
}
|
2024-11-17 23:36:16 -06:00
|
|
|
|
|
|
|
if (Updater.checkForUpdatesOnStart) {
|
|
|
|
Main.checkForUpdates(true);
|
|
|
|
}
|
2025-04-18 18:28:25 -05:00
|
|
|
|
2025-04-29 12:17:29 -05:00
|
|
|
Main.mainWindow?.webContents?.setWindowOpenHandler((details) => {
|
2025-04-18 18:28:25 -05:00
|
|
|
shell.openExternal(details.url);
|
|
|
|
return { action: "deny" };
|
|
|
|
});
|
2023-06-20 08:45:01 +02:00
|
|
|
}
|
|
|
|
|
2023-12-06 13:03:23 +01:00
|
|
|
static openMainWindow() {
|
|
|
|
if (Main.mainWindow) {
|
|
|
|
Main.mainWindow.focus();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Main.mainWindow = new BrowserWindow({
|
2024-11-14 01:04:00 -06:00
|
|
|
fullscreen: Main.startFullscreen,
|
2023-12-06 13:03:23 +01:00
|
|
|
autoHideMenuBar: true,
|
2024-10-21 20:51:07 +00:00
|
|
|
icon: path.join(__dirname, 'icon512.png'),
|
2023-12-06 13:03:23 +01:00
|
|
|
webPreferences: {
|
|
|
|
preload: path.join(__dirname, 'main/preload.js')
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2025-04-30 10:17:20 -05:00
|
|
|
const networkWorker = new BrowserWindow({
|
2025-04-30 10:30:56 -05:00
|
|
|
show: false,
|
2025-04-30 10:17:20 -05:00
|
|
|
webPreferences: {
|
|
|
|
nodeIntegration: true,
|
|
|
|
contextIsolation: false,
|
|
|
|
preload: path.join(__dirname, 'main/networkWorker.js')
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-12-06 13:03:23 +01:00
|
|
|
Main.mainWindow.loadFile(path.join(__dirname, 'main/index.html'));
|
|
|
|
Main.mainWindow.on('closed', () => {
|
|
|
|
Main.mainWindow = null;
|
2025-04-30 10:17:20 -05:00
|
|
|
networkWorker.close();
|
2023-12-06 13:03:23 +01:00
|
|
|
});
|
|
|
|
|
2024-11-14 01:04:00 -06:00
|
|
|
Main.mainWindow.maximize();
|
2023-12-06 13:03:23 +01:00
|
|
|
Main.mainWindow.show();
|
|
|
|
|
|
|
|
Main.mainWindow.on('ready-to-show', () => {
|
2025-04-23 19:21:17 -05:00
|
|
|
networkWorker.loadFile(path.join(__dirname, 'main/worker.html'));
|
2023-12-06 13:03:23 +01:00
|
|
|
});
|
2024-09-06 15:44:20 -05:00
|
|
|
}
|
2023-12-06 13:03:23 +01:00
|
|
|
|
2024-11-11 12:24:17 -06:00
|
|
|
static async main(app: Electron.App) {
|
2024-11-15 00:43:01 -06:00
|
|
|
try {
|
|
|
|
Main.application = app;
|
2024-11-19 17:31:03 -06:00
|
|
|
|
|
|
|
const argv = yargs(hideBin(process.argv))
|
|
|
|
.version(app.getVersion())
|
|
|
|
.parserConfiguration({
|
|
|
|
'boolean-negation': false
|
|
|
|
})
|
|
|
|
.options({
|
|
|
|
'no-main-window': { type: 'boolean', default: false, desc: "Start minimized to tray" },
|
|
|
|
'fullscreen': { type: 'boolean', default: false, desc: "Start application in fullscreen" }
|
|
|
|
})
|
|
|
|
.parseSync();
|
|
|
|
|
2024-11-15 00:43:01 -06:00
|
|
|
const isUpdating = Updater.isUpdating();
|
2024-11-17 11:54:02 -06:00
|
|
|
const fileLogType = isUpdating ? 'fileSync' : 'file';
|
2024-11-15 00:43:01 -06:00
|
|
|
log4js.configure({
|
|
|
|
appenders: {
|
|
|
|
out: { type: 'stdout' },
|
2024-11-17 11:54:02 -06:00
|
|
|
log: { type: fileLogType, filename: path.join(app.getPath('logs'), 'fcast-receiver.log'), flags: 'a', maxLogSize: '5M' },
|
2024-11-15 00:43:01 -06:00
|
|
|
},
|
|
|
|
categories: {
|
|
|
|
default: { appenders: ['out', 'log'], level: 'info' },
|
|
|
|
},
|
|
|
|
});
|
|
|
|
Main.logger = log4js.getLogger();
|
2024-11-19 14:49:27 -06:00
|
|
|
Main.logger.info(`Starting application: ${app.name} | ${app.getAppPath()}`);
|
|
|
|
Main.logger.info(`Version: ${app.getVersion()}`);
|
2024-11-21 11:51:46 -06:00
|
|
|
Main.logger.info(`Commit: ${Updater.getCommit()}`);
|
2024-11-19 14:49:27 -06:00
|
|
|
Main.logger.info(`Release channel: ${Updater.releaseChannel} - ${Updater.getChannelVersion()}`);
|
2024-11-19 09:54:50 -06:00
|
|
|
Main.logger.info(`OS: ${process.platform} ${process.arch}`);
|
2024-11-11 12:24:17 -06:00
|
|
|
|
2024-11-15 00:43:01 -06:00
|
|
|
if (isUpdating) {
|
|
|
|
await Updater.processUpdate();
|
|
|
|
}
|
2024-11-11 12:24:17 -06:00
|
|
|
|
2024-11-15 00:43:01 -06:00
|
|
|
Main.startFullscreen = argv.fullscreen;
|
|
|
|
Main.shouldOpenMainWindow = !argv.noMainWindow;
|
2025-04-18 11:32:01 -05:00
|
|
|
|
|
|
|
const lock = Main.application.requestSingleInstanceLock()
|
|
|
|
if (!lock) {
|
|
|
|
Main.application.quit();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
Main.application.on('second-instance', () => {
|
|
|
|
if (Main.mainWindow) {
|
|
|
|
if (Main.mainWindow.isMinimized()) {
|
|
|
|
Main.mainWindow.restore();
|
|
|
|
}
|
|
|
|
Main.mainWindow.focus();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
Main.openMainWindow();
|
|
|
|
}
|
|
|
|
})
|
2024-11-15 00:43:01 -06:00
|
|
|
Main.application.on('ready', Main.onReady);
|
|
|
|
Main.application.on('window-all-closed', () => { });
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
Main.logger.error(`Error starting application: ${err}`);
|
|
|
|
app.exit();
|
2024-11-11 12:24:17 -06:00
|
|
|
}
|
2023-06-20 08:45:01 +02:00
|
|
|
}
|
2024-11-11 12:24:17 -06:00
|
|
|
}
|
2024-12-09 00:56:55 -06:00
|
|
|
|
|
|
|
export function getComputerName() {
|
|
|
|
switch (process.platform) {
|
|
|
|
case "win32":
|
|
|
|
return process.env.COMPUTERNAME;
|
|
|
|
case "darwin":
|
|
|
|
return cp.execSync("scutil --get ComputerName").toString().trim();
|
|
|
|
case "linux": {
|
|
|
|
let hostname: string;
|
|
|
|
|
|
|
|
// Some distro's don't work with `os.hostname()`, but work with `hostnamectl` and vice versa...
|
|
|
|
try {
|
|
|
|
hostname = os.hostname();
|
|
|
|
}
|
|
|
|
catch (err) {
|
|
|
|
Main.logger.warn('Error fetching hostname, trying different method...');
|
|
|
|
Main.logger.warn(err);
|
|
|
|
|
|
|
|
try {
|
|
|
|
hostname = cp.execSync("hostnamectl hostname").toString().trim();
|
|
|
|
}
|
|
|
|
catch (err2) {
|
|
|
|
Main.logger.warn('Error fetching hostname again, using generic name...');
|
|
|
|
Main.logger.warn(err2);
|
|
|
|
|
|
|
|
hostname = 'linux device';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return hostname;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
return os.hostname();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function errorHandler(err: NodeJS.ErrnoException) {
|
|
|
|
Main.logger.error("Application error:", err);
|
2025-04-29 12:17:29 -05:00
|
|
|
Main.mainWindow?.webContents?.send("toast", { message: err, icon: ToastIcon.ERROR });
|
2024-12-09 00:56:55 -06:00
|
|
|
|
|
|
|
const restartPrompt = await dialog.showMessageBox({
|
|
|
|
type: 'error',
|
|
|
|
title: 'Failed to start',
|
|
|
|
message: 'The application failed to start properly.',
|
|
|
|
buttons: ['Restart', 'Close'],
|
|
|
|
defaultId: 0,
|
|
|
|
cancelId: 1
|
|
|
|
});
|
|
|
|
|
|
|
|
if (restartPrompt.response === 0) {
|
|
|
|
Main.application.relaunch();
|
|
|
|
Main.application.exit(0);
|
|
|
|
} else {
|
|
|
|
Main.application.exit(0);
|
|
|
|
}
|
|
|
|
}
|