2
0
mirror of https://github.com/frappe/books.git synced 2024-11-08 14:50:56 +00:00
books/main.ts

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();