214 lines
5.2 KiB
TypeScript
214 lines
5.2 KiB
TypeScript
import type { HandlerDetails } from 'electron';
|
|
import {
|
|
app, BrowserWindow, ipcMain, shell, systemPreferences,
|
|
} from 'electron';
|
|
import path from 'path';
|
|
|
|
import type { TrafficLightPosition } from '../types/electron';
|
|
import { ElectronAction, ElectronEvent } from '../types/electron';
|
|
|
|
import setupAutoUpdates from './autoUpdates';
|
|
import { processDeeplink } from './deeplink';
|
|
import tray from './tray';
|
|
import {
|
|
forceQuit, getAppTitle, getCurrentWindow, getLastWindow, hasExtraWindows, IS_MAC_OS, IS_WINDOWS,
|
|
TRAFFIC_LIGHT_POSITION, windows,
|
|
} from './utils';
|
|
import windowStateKeeper from './windowState';
|
|
|
|
const ALLOWED_DEVICE_ORIGINS = ['http://localhost:1234', 'file://'];
|
|
|
|
export function createWindow(url?: string) {
|
|
const windowState = windowStateKeeper({
|
|
defaultWidth: 1088,
|
|
defaultHeight: 700,
|
|
});
|
|
|
|
let x;
|
|
let y;
|
|
|
|
const currentWindow = getCurrentWindow();
|
|
if (currentWindow) {
|
|
const [currentWindowX, currentWindowY] = currentWindow.getPosition();
|
|
x = currentWindowX + 24;
|
|
y = currentWindowY + 24;
|
|
} else {
|
|
x = windowState.x;
|
|
y = windowState.y;
|
|
}
|
|
|
|
let width;
|
|
let height;
|
|
|
|
if (currentWindow) {
|
|
const bounds = currentWindow.getBounds();
|
|
|
|
width = bounds.width;
|
|
height = bounds.height;
|
|
} else {
|
|
width = windowState.width;
|
|
height = windowState.height;
|
|
}
|
|
|
|
const window = new BrowserWindow({
|
|
show: false,
|
|
x,
|
|
y,
|
|
minWidth: 360,
|
|
width,
|
|
height,
|
|
title: getAppTitle(),
|
|
webPreferences: {
|
|
preload: path.join(__dirname, 'preload.js'),
|
|
devTools: process.env.APP_ENV !== 'production',
|
|
},
|
|
...(IS_MAC_OS && {
|
|
titleBarStyle: 'hidden',
|
|
trafficLightPosition: TRAFFIC_LIGHT_POSITION.standard,
|
|
}),
|
|
});
|
|
|
|
window.on('page-title-updated', (event: Event) => {
|
|
event.preventDefault();
|
|
});
|
|
|
|
windowState.manage(window);
|
|
|
|
window.webContents.setWindowOpenHandler((details: HandlerDetails) => {
|
|
shell.openExternal(details.url);
|
|
return { action: 'deny' };
|
|
});
|
|
|
|
window.webContents.session.setDevicePermissionHandler(({ deviceType, origin }) => {
|
|
return deviceType === 'hid' && ALLOWED_DEVICE_ORIGINS.includes(origin);
|
|
});
|
|
|
|
window.on('enter-full-screen', () => {
|
|
window.webContents.send(ElectronEvent.FULLSCREEN_CHANGE, true);
|
|
});
|
|
|
|
window.on('leave-full-screen', () => {
|
|
window.webContents.send(ElectronEvent.FULLSCREEN_CHANGE, false);
|
|
});
|
|
|
|
window.on('close', (event) => {
|
|
if (IS_MAC_OS || IS_WINDOWS) {
|
|
if (forceQuit.isEnabled) {
|
|
app.exit(0);
|
|
forceQuit.disable();
|
|
} else if (hasExtraWindows()) {
|
|
windows.delete(window);
|
|
windowState.unmanage();
|
|
} else {
|
|
event.preventDefault();
|
|
window.hide();
|
|
}
|
|
}
|
|
});
|
|
|
|
if (url) {
|
|
window.loadURL(url);
|
|
} else if (app.isPackaged) {
|
|
window.loadURL(`file://${__dirname}/index.html${windowState.urlHash}`);
|
|
} else {
|
|
window.loadURL(`http://localhost:1234${windowState.urlHash}`);
|
|
window.webContents.openDevTools();
|
|
}
|
|
|
|
windowState.clearLastUrlHash();
|
|
|
|
if (!IS_MAC_OS) {
|
|
window.removeMenu();
|
|
}
|
|
|
|
if (IS_WINDOWS && tray.isEnabled) {
|
|
tray.setupListeners(window);
|
|
tray.create();
|
|
}
|
|
|
|
window.webContents.once('dom-ready', () => {
|
|
window.show();
|
|
processDeeplink();
|
|
|
|
if (process.env.APP_ENV === 'production') {
|
|
setupAutoUpdates(window, windowState);
|
|
}
|
|
});
|
|
|
|
windows.add(window);
|
|
}
|
|
|
|
export function setupElectronActionHandlers() {
|
|
ipcMain.handle(ElectronAction.OPEN_NEW_WINDOW, (_, url: string) => {
|
|
createWindow(url);
|
|
});
|
|
|
|
ipcMain.handle(ElectronAction.SET_WINDOW_TITLE, (_, newTitle?: string) => {
|
|
getCurrentWindow()?.setTitle(getAppTitle(newTitle));
|
|
});
|
|
|
|
ipcMain.handle(ElectronAction.GET_IS_FULLSCREEN, () => {
|
|
getCurrentWindow()?.isFullScreen();
|
|
});
|
|
|
|
ipcMain.handle(ElectronAction.HANDLE_DOUBLE_CLICK, () => {
|
|
const currentWindow = getCurrentWindow();
|
|
const doubleClickAction = systemPreferences.getUserDefault('AppleActionOnDoubleClick', 'string');
|
|
|
|
if (doubleClickAction === 'Minimize') {
|
|
currentWindow?.minimize();
|
|
} else if (doubleClickAction === 'Maximize') {
|
|
if (!currentWindow?.isMaximized()) {
|
|
currentWindow?.maximize();
|
|
} else {
|
|
currentWindow?.unmaximize();
|
|
}
|
|
}
|
|
});
|
|
|
|
ipcMain.handle(ElectronAction.SET_TRAFFIC_LIGHT_POSITION, (_, position: TrafficLightPosition) => {
|
|
if (!IS_MAC_OS) {
|
|
return;
|
|
}
|
|
|
|
getCurrentWindow()?.setTrafficLightPosition(TRAFFIC_LIGHT_POSITION[position]);
|
|
});
|
|
|
|
ipcMain.handle(ElectronAction.SET_IS_TRAY_ICON_ENABLED, (_, value: boolean) => {
|
|
if (value) {
|
|
tray.enable();
|
|
} else {
|
|
tray.disable();
|
|
}
|
|
});
|
|
|
|
ipcMain.handle(ElectronAction.GET_IS_TRAY_ICON_ENABLED, () => tray.isEnabled);
|
|
}
|
|
|
|
export function setupCloseHandlers() {
|
|
app.on('window-all-closed', () => {
|
|
if (!IS_MAC_OS) {
|
|
app.quit();
|
|
}
|
|
});
|
|
|
|
app.on('before-quit', (event) => {
|
|
if (IS_MAC_OS && !forceQuit.isEnabled) {
|
|
event.preventDefault();
|
|
forceQuit.enable();
|
|
app.quit();
|
|
}
|
|
});
|
|
|
|
app.on('activate', () => {
|
|
const hasActiveWindow = BrowserWindow.getAllWindows().length > 0;
|
|
|
|
if (!hasActiveWindow) {
|
|
createWindow();
|
|
} else if (IS_MAC_OS) {
|
|
forceQuit.disable();
|
|
getLastWindow()?.show();
|
|
}
|
|
});
|
|
}
|