mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-09 01:13:55 +00:00
55d1aca9b6
* refactor: cleanup routes * style: smaller base font * chore: upgrade dependencies * chore: lock node version to electron * refactor: pass HTTP to integration controller (#652) * refactor: deprecate onair control * refactor: remove playback router * Several project files user folder (#617) * chore: automated screenshots (#667) * feat: app settings (#658) * refactor: remove deprecated event data (#674) * Studio clock (#663) --------- Co-authored-by: Carlos Valente <carlosvalente@pm.me> * Feat: reorder events with alt+ctrl + arrow up/down (#645) * Warning and danger per event (#677) --------- Co-authored-by: Fabian Posenau <fabian@fphome.de> * refactor: stabilise actionHandler (#683) Co-authored-by: Fabian Posenau <fabian@fphome.de> * improvement: hide seconds (#675) * wip: overview (#688) * fix: focus cursor (#695) * refactor: update lower third (#665) * Refactor/time formatting (#696) --------- Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Co-authored-by: Carlos Valente <carlosvalente@pm.me> * feat: multiple selection (#703) --------- Co-authored-by: asharonbaltazar <asharonbaltazar@outlook.com> Co-authored-by: Alex <ac@omnivox.dk> * fix: test - go to `Edit mode` befor tying to click `Event options` button (#708) * refactor: runtime service (#715) * fix: issue with loosing cursor position on message (#719) * remove info panel (#721) * Event editor continue (#722) * update API - part (#709) --------- Co-authored-by: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Co-authored-by: Carlos Valente <carlosvalente@pm.me> * refactor: update timers (#729) * feat: many timers (#706) --------- Co-authored-by: arc-alex <ac@omnivox.dk> * refactor: excel cleanup (#734) * refactor: allow import of blocks and skip import (#735) * Project manager (#697) * refactor: UI for linking events (#763) * upgraded pipeline actions (#777) * Over under (#771) * custom fields (#744) --------- Co-authored-by: Carlos Valente <carlosvalente@pm.me> * Sheets settings (#774) --------- Co-authored-by: arc-alex <ac@omnivox.dk> * style: tweaks to lower thirds (#785) * refactor: delays account for gaps (#784) * refactor: partial state updates (#780) * feat: generate crash report (#787) * Sheet use limited input device auth flow (#782) --------- Co-authored-by: cv <34649812+cpvalente@users.noreply.github.com> Co-authored-by: Carlos Valente <carlosvalente@pm.me> * Custom fields views (#789) * refactor: deprecate presenter and subtitle (#795) * refactor: organise API around resources (#798) --------- Co-authored-by: Bianca Procopio <biancahprocopio@gmail.com> * Time to end (#804) * Skip fixes (#805) * fix: onair derives from playback * Param nav (#822) --------- Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk> * refactor: download files from interface (#831) * Quick options (#814) * End pause (#832) * chore: bump node version in docker (#834) * refactor: follow in run mode (#840) * fix: uncaught error in http integration (#837) * Apply project (#843) Co-authored-by: Matteo Gheza <matteo.gheza07@gmail.com> Co-authored-by: Ary <arylmoraesn@gmail.com> Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk> Co-authored-by: Fabian Posenau <19673098+kellhogs@users.noreply.github.com> Co-authored-by: Fabian Posenau <fabian@fphome.de> Co-authored-by: Alex Rohleder <alexrohleder96@gmail.com> Co-authored-by: asharonbaltazar <asharonbaltazar@outlook.com> Co-authored-by: Bianca Procopio <biancahprocopio@gmail.com> Co-authored-by: Fabian Posenau <fabianpos99+github@gmail.com>
250 lines
5.9 KiB
JavaScript
250 lines
5.9 KiB
JavaScript
const { app, BrowserWindow, Menu, globalShortcut, Tray, dialog, ipcMain, shell, Notification } = require('electron');
|
|
const path = require('path');
|
|
const electronConfig = require('./electron.config');
|
|
|
|
const env = process.env.NODE_ENV || 'production';
|
|
const isProduction = env === 'production';
|
|
const isMac = process.platform === 'darwin';
|
|
const isWindows = process.platform === 'win32';
|
|
|
|
// path to server
|
|
const nodePath = isProduction
|
|
? path.join(__dirname, electronConfig.server.pathToEntrypoint)
|
|
: path.join(__dirname, '../server/dist/index.cjs');
|
|
|
|
if (!isProduction) {
|
|
console.log(`Electron running in ${env} environment`);
|
|
console.log(`Ontime server at ${nodePath}`);
|
|
process.traceProcessWarnings = true;
|
|
}
|
|
|
|
// path to icons
|
|
const trayIcon = path.join(__dirname, electronConfig.assets.pathToAssets, 'background.png');
|
|
const appIcon = path.join(__dirname, electronConfig.assets.pathToAssets, 'logo.png');
|
|
let loaded = 'Nothing loaded';
|
|
let isQuitting = false;
|
|
|
|
// initialise
|
|
let win;
|
|
let splash;
|
|
let tray = null;
|
|
|
|
async function startBackend() {
|
|
// in dev mode, we expect both UI and server to be running
|
|
if (!isProduction) {
|
|
return;
|
|
}
|
|
|
|
const ontimeServer = require(nodePath);
|
|
const { initAssets, startServer, startIntegrations } = ontimeServer;
|
|
|
|
await initAssets();
|
|
|
|
const result = await startServer();
|
|
loaded = result.message;
|
|
|
|
await startIntegrations();
|
|
|
|
return result.serverPort;
|
|
}
|
|
|
|
/**
|
|
* @description utility function to create a notification
|
|
* @param title
|
|
* @param text
|
|
*/
|
|
function showNotification(title, text) {
|
|
new Notification({
|
|
title,
|
|
body: text,
|
|
silent: true,
|
|
}).show();
|
|
}
|
|
|
|
function appShutdown() {
|
|
// terminate node service
|
|
(async () => {
|
|
const ontimeServer = require(nodePath);
|
|
const { shutdown } = ontimeServer;
|
|
await shutdown(electronConfig.appIni.shutdownCode);
|
|
})();
|
|
|
|
isQuitting = true;
|
|
tray.destroy();
|
|
win.destroy();
|
|
app.quit();
|
|
}
|
|
|
|
function bringToFront() {
|
|
win.show();
|
|
win.focus();
|
|
}
|
|
|
|
function askToQuit() {
|
|
bringToFront();
|
|
win.send('user-request-shutdown');
|
|
}
|
|
|
|
// Ensure there isn't another instance of the app running already
|
|
const lock = app.requestSingleInstanceLock();
|
|
if (!lock) {
|
|
dialog.showErrorBox('Multiple instances', 'An instance of the App is already running.');
|
|
app.quit();
|
|
} else {
|
|
app.on('second-instance', () => {
|
|
// Someone tried to run a second instance, we should focus our window.
|
|
if (win) {
|
|
if (win.isMinimized()) {
|
|
win.restore();
|
|
}
|
|
bringToFront();
|
|
}
|
|
});
|
|
}
|
|
|
|
function createWindow() {
|
|
splash = new BrowserWindow({
|
|
width: 333,
|
|
height: 333,
|
|
transparent: true,
|
|
icon: appIcon,
|
|
resizable: false,
|
|
frame: false,
|
|
alwaysOnTop: true,
|
|
focusable: false,
|
|
skipTaskbar: true,
|
|
});
|
|
splash.setIgnoreMouseEvents(true);
|
|
const splashPath = path.join('file://', __dirname, '/src/splash/splash.html');
|
|
splash.loadURL(splashPath);
|
|
|
|
win = new BrowserWindow({
|
|
width: 1920,
|
|
height: 1000,
|
|
minWidth: 525,
|
|
minHeight: 405,
|
|
backgroundColor: '#101010', // $gray-1350
|
|
icon: appIcon,
|
|
show: false,
|
|
textAreasAreResizable: false,
|
|
enableWebSQL: false,
|
|
darkTheme: true,
|
|
webPreferences: {
|
|
preload: path.join(__dirname, './src/preload.js'),
|
|
nodeIntegration: true,
|
|
contextIsolation: false,
|
|
},
|
|
});
|
|
|
|
win.setMenu(null);
|
|
}
|
|
|
|
app.disableHardwareAcceleration();
|
|
app.whenReady().then(() => {
|
|
// Set app title in windows
|
|
if (isWindows) {
|
|
app.setAppUserModelId(app.name);
|
|
}
|
|
|
|
createWindow();
|
|
|
|
// register global shortcuts
|
|
// (available regardless of whether app is in focus)
|
|
// bring focus to window
|
|
globalShortcut.register('Alt+1', () => {
|
|
bringToFront();
|
|
});
|
|
|
|
startBackend()
|
|
.then((port) => {
|
|
// Load page served by node or use React dev run
|
|
const clientUrl = isProduction
|
|
? electronConfig.reactAppUrl.production(port)
|
|
: electronConfig.reactAppUrl.development(port);
|
|
|
|
win
|
|
.loadURL(clientUrl)
|
|
.then(() => {
|
|
win.webContents.setBackgroundThrottling(false);
|
|
|
|
win.show();
|
|
win.focus();
|
|
|
|
splash.destroy();
|
|
|
|
if (typeof loaded === 'string') {
|
|
tray.setToolTip(loaded);
|
|
} else {
|
|
tray.setToolTip('Initialising error: please restart Ontime');
|
|
}
|
|
})
|
|
.catch((error) => {
|
|
console.log('ERROR: Ontime failed to reach server', error);
|
|
});
|
|
})
|
|
.catch((error) => {
|
|
console.log('ERROR: Ontime failed to start', error);
|
|
});
|
|
|
|
// recreate window if no others open
|
|
app.on('activate', () => {
|
|
win.show();
|
|
});
|
|
|
|
// Hide on close
|
|
win.on('close', function (event) {
|
|
event.preventDefault();
|
|
if (!isQuitting) {
|
|
showNotification('Window Closed', 'App running in background');
|
|
win.hide();
|
|
}
|
|
});
|
|
|
|
// create tray
|
|
tray = new Tray(trayIcon);
|
|
|
|
// Define context menu
|
|
const { getTrayMenu } = require('./src/menu/trayMenu.js');
|
|
const trayMenuTemplate = getTrayMenu(bringToFront, askToQuit);
|
|
const trayContextMenu = Menu.buildFromTemplate(trayMenuTemplate);
|
|
tray.setContextMenu(trayContextMenu);
|
|
});
|
|
|
|
const { getApplicationMenu } = require('./src/menu/applicationMenu.js');
|
|
const template = getApplicationMenu(isMac, askToQuit);
|
|
const menu = Menu.buildFromTemplate(template);
|
|
Menu.setApplicationMenu(menu);
|
|
|
|
// unregister shortcuts before quitting
|
|
app.once('will-quit', () => {
|
|
globalShortcut.unregisterAll();
|
|
});
|
|
|
|
// Ask for main window reload
|
|
// Test message
|
|
ipcMain.on('reload', () => {
|
|
win?.reload();
|
|
});
|
|
|
|
// Terminate
|
|
ipcMain.on('shutdown', () => {
|
|
console.log('Electron got IPC shutdown');
|
|
appShutdown();
|
|
});
|
|
|
|
// Window manipulation
|
|
ipcMain.on('set-window', (event, arg) => {
|
|
switch (arg) {
|
|
case 'show-dev':
|
|
win.webContents.openDevTools({ mode: 'detach' });
|
|
break;
|
|
default:
|
|
console.log('Electron unhandled window request', arg);
|
|
}
|
|
});
|
|
|
|
// Open links external
|
|
ipcMain.on('send-to-link', (event, arg) => {
|
|
shell.openExternal(arg);
|
|
});
|