mirror of
https://github.com/frappe/books.git
synced 2024-11-08 14:50:56 +00:00
213 lines
5.1 KiB
TypeScript
213 lines
5.1 KiB
TypeScript
// eslint-disable-next-line
|
|
require('source-map-support').install({
|
|
handleUncaughtException: false,
|
|
environment: 'node',
|
|
});
|
|
|
|
import {
|
|
app,
|
|
BrowserWindow,
|
|
BrowserWindowConstructorOptions,
|
|
protocol,
|
|
ProtocolRequest,
|
|
ProtocolResponse,
|
|
} from 'electron';
|
|
import Store from 'electron-store';
|
|
import { autoUpdater } from 'electron-updater';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import registerAppLifecycleListeners from './main/registerAppLifecycleListeners';
|
|
import registerAutoUpdaterListeners from './main/registerAutoUpdaterListeners';
|
|
import registerIpcMainActionListeners from './main/registerIpcMainActionListeners';
|
|
import registerIpcMainMessageListeners from './main/registerIpcMainMessageListeners';
|
|
import registerProcessListeners from './main/registerProcessListeners';
|
|
import { emitMainProcessError } from 'backend/helpers';
|
|
|
|
export class Main {
|
|
title = 'Frappe Books';
|
|
icon: string;
|
|
|
|
winURL = '';
|
|
checkedForUpdate = false;
|
|
mainWindow: BrowserWindow | null = null;
|
|
|
|
WIDTH = 1200;
|
|
HEIGHT = process.platform === 'win32' ? 826 : 800;
|
|
|
|
constructor() {
|
|
this.icon = this.isDevelopment
|
|
? path.resolve('./build/icon.png')
|
|
: path.join(__dirname, 'icons', '512x512.png');
|
|
|
|
protocol.registerSchemesAsPrivileged([
|
|
{ scheme: 'app', privileges: { secure: true, standard: true } },
|
|
]);
|
|
|
|
if (this.isDevelopment) {
|
|
autoUpdater.logger = console;
|
|
}
|
|
|
|
// https://github.com/electron-userland/electron-builder/issues/4987
|
|
app.commandLine.appendSwitch('disable-http2');
|
|
autoUpdater.requestHeaders = {
|
|
'Cache-Control':
|
|
'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0',
|
|
};
|
|
|
|
Store.initRenderer();
|
|
|
|
this.registerListeners();
|
|
if (this.isMac && this.isDevelopment) {
|
|
app.dock.setIcon(this.icon);
|
|
}
|
|
}
|
|
|
|
get isDevelopment() {
|
|
return process.env.NODE_ENV === 'development';
|
|
}
|
|
|
|
get isTest() {
|
|
return !!process.env.IS_TEST;
|
|
}
|
|
|
|
get isMac() {
|
|
return process.platform === 'darwin';
|
|
}
|
|
|
|
get isLinux() {
|
|
return process.platform === 'linux';
|
|
}
|
|
|
|
registerListeners() {
|
|
registerIpcMainMessageListeners(this);
|
|
registerIpcMainActionListeners(this);
|
|
registerAutoUpdaterListeners(this);
|
|
registerAppLifecycleListeners(this);
|
|
registerProcessListeners(this);
|
|
}
|
|
|
|
getOptions(): BrowserWindowConstructorOptions {
|
|
const options: BrowserWindowConstructorOptions = {
|
|
width: this.WIDTH,
|
|
height: this.HEIGHT,
|
|
title: this.title,
|
|
titleBarStyle: 'hidden',
|
|
trafficLightPosition: { x: 16, y: 16 },
|
|
webPreferences: {
|
|
contextIsolation: false, // TODO: Switch this off
|
|
nodeIntegration: true,
|
|
},
|
|
autoHideMenuBar: true,
|
|
frame: !this.isMac,
|
|
resizable: true,
|
|
};
|
|
|
|
if (!this.isMac) {
|
|
options.titleBarOverlay = {
|
|
color: '#FFFFFF',
|
|
height: 26,
|
|
};
|
|
}
|
|
|
|
if (this.isDevelopment || this.isLinux) {
|
|
Object.assign(options, { icon: this.icon });
|
|
}
|
|
|
|
if (this.isLinux) {
|
|
Object.assign(options, {
|
|
icon: path.join(__dirname, '/icons/512x512.png'),
|
|
});
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
async createWindow() {
|
|
const options = this.getOptions();
|
|
this.mainWindow = new BrowserWindow(options);
|
|
|
|
if (this.isDevelopment) {
|
|
this.setViteServerURL();
|
|
} else {
|
|
this.registerAppProtocol();
|
|
}
|
|
|
|
await this.mainWindow.loadURL(this.winURL);
|
|
if (this.isDevelopment && !this.isTest) {
|
|
this.mainWindow.webContents.openDevTools();
|
|
}
|
|
|
|
this.setMainWindowListeners();
|
|
}
|
|
|
|
setViteServerURL() {
|
|
let port = 6969;
|
|
let host = '0.0.0.0';
|
|
|
|
if (process.env.VITE_PORT && process.env.VITE_HOST) {
|
|
port = Number(process.env.VITE_PORT);
|
|
host = process.env.VITE_HOST;
|
|
}
|
|
|
|
// Load the url of the dev server if in development mode
|
|
this.winURL = `http://${host}:${port}/`;
|
|
}
|
|
|
|
registerAppProtocol() {
|
|
protocol.registerBufferProtocol('app', bufferProtocolCallback);
|
|
|
|
// Use the registered protocol url to load the files.
|
|
this.winURL = 'app://./index.html';
|
|
}
|
|
|
|
setMainWindowListeners() {
|
|
if (this.mainWindow === null) {
|
|
return;
|
|
}
|
|
|
|
this.mainWindow.on('closed', () => {
|
|
this.mainWindow = null;
|
|
});
|
|
|
|
this.mainWindow.webContents.on('did-fail-load', () => {
|
|
this.mainWindow!.loadURL(this.winURL).catch((err) =>
|
|
emitMainProcessError(err)
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Callback used to register the custom app protocol,
|
|
* during prod, files are read and served by using this
|
|
* protocol.
|
|
*/
|
|
function bufferProtocolCallback(
|
|
request: ProtocolRequest,
|
|
callback: (response: ProtocolResponse) => void
|
|
) {
|
|
const { pathname, host } = new URL(request.url);
|
|
const filePath = path.join(
|
|
__dirname,
|
|
'src',
|
|
decodeURI(host),
|
|
decodeURI(pathname)
|
|
);
|
|
|
|
fs.readFile(filePath, (_, data) => {
|
|
const extension = path.extname(filePath).toLowerCase();
|
|
const mimeType =
|
|
{
|
|
'.js': 'text/javascript',
|
|
'.css': 'text/css',
|
|
'.html': 'text/html',
|
|
'.svg': 'image/svg+xml',
|
|
'.json': 'application/json',
|
|
}[extension] ?? '';
|
|
|
|
callback({ mimeType, data });
|
|
});
|
|
}
|
|
|
|
export default new Main();
|