From 9c8788fb2e419ae63c3a6545f4c5966547232702 Mon Sep 17 00:00:00 2001 From: Amadou Ada DIENE Date: Sat, 18 Apr 2020 04:57:24 +0200 Subject: [PATCH] feat: change project structure to meet targeted architecture --- electron-webpack.json | 9 +++++ src/electron/components/app.ts | 65 ++++++++++++++++++++++++++++++ src/electron/components/window.ts | 67 +++++++++++++++++++++++++++++++ src/electron/main.ts | 3 ++ src/electron/preload.ts | 1 + src/electron/tsconfig.json | 7 ++++ 6 files changed, 152 insertions(+) create mode 100644 electron-webpack.json create mode 100644 src/electron/components/app.ts create mode 100644 src/electron/components/window.ts create mode 100644 src/electron/main.ts create mode 100644 src/electron/preload.ts create mode 100644 src/electron/tsconfig.json diff --git a/electron-webpack.json b/electron-webpack.json new file mode 100644 index 0000000..52e8c81 --- /dev/null +++ b/electron-webpack.json @@ -0,0 +1,9 @@ +{ + "main": { + "extraEntries": ["@/preload.js"], + "sourceDirectory": "dist/electron" + }, + "renderer": { + "sourceDirectory": null + } +} diff --git a/src/electron/components/app.ts b/src/electron/components/app.ts new file mode 100644 index 0000000..9765a6c --- /dev/null +++ b/src/electron/components/app.ts @@ -0,0 +1,65 @@ +import { app, BrowserWindow, shell } from 'electron'; +import { Window } from './window'; + +export class App { + private static _wrapper: Window; + + public static launch() { + app.on('window-all-closed', App.quit); + app.on('activate', App.start); + app.on('ready', App.start); + + // Fix warning by applying electron new default value for this property + // Further details : https://github.com/electron/electron/issues/18397 + app.allowRendererProcessReuse = true; + + // Limit navigation and open external links in default browser + app.on('web-contents-created', App.openExternalLinksInDefaultBrowser); + } + + public static get window(): BrowserWindow | any { + return this._wrapper ? this._wrapper.window : null; + } + + private static start() { + // On MacOS it is common to re-create a window from app even after all windows have been closed + if (!App.window) { + App._wrapper = new Window(); + } + } + + private static quit() { + // On MacOS it is common for applications to stay open until the user explicitly quits + if (process.platform !== 'darwin') { + app.quit(); + } + } + + private static openExternalLinksInDefaultBrowser = ( + event: Electron.Event, + contents: Electron.WebContents + ) => { + // Disabling creation of new windows + contents.on( + 'new-window', + (event: Electron.Event, navigationUrl: string) => { + // Blocking this event from loading in current app + event.preventDefault(); + // Telling the user platform to open this event's url in the default browser + shell.openExternal(navigationUrl); + } + ); + + // Limiting navigation + contents.on( + 'will-navigate', + (event: Electron.Event, navigationUrl: string) => { + const parsedUrl = new URL(navigationUrl); + // Allowing local navigation only + if (parsedUrl.origin !== 'http://localhost:4200') { + event.preventDefault(); + } + } + ); + }; +} diff --git a/src/electron/components/window.ts b/src/electron/components/window.ts new file mode 100644 index 0000000..40ca932 --- /dev/null +++ b/src/electron/components/window.ts @@ -0,0 +1,67 @@ +import { app, BrowserWindow } from 'electron'; +import * as path from 'path'; +import * as url from 'url'; + +export class Window { + private _window: BrowserWindow | any; + private _dev: boolean; + + constructor() { + const env = process.env.NODE_ENV; + this._dev = env === 'development'; + + this.createWindow(); + this.loadRender(); + } + + private createWindow(): void { + this._window = new BrowserWindow({ + width: 800, + height: 600, + backgroundColor: '#FFFFFF', + webPreferences: { + // Isolate window context to protect against prototype pollution + contextIsolation: true, + // Disable the remote module to enhance security + enableRemoteModule: false, + // Use a preload script to enhance security + preload: path.join(app.getAppPath(), 'preload.js'), + }, + }); + } + + private loadRender(): void { + if (this._dev) { + // Dev mode, take advantage of the live reload by loading local URL + this.window.loadURL(`http://localhost:4200`); + this.openDevTools(); + } else { + // Else mode, we simply load angular bundle + const indexPath = url.format({ + pathname: path.join(__dirname, `index.html`), + protocol: 'file:', + slashes: true, + }); + this.window.loadURL(indexPath); + } + + // Delete current reference when the window is closed + this._window.on('closed', () => { + delete this._window; + }); + } + + private openDevTools(): void { + this._window.webContents.openDevTools(); + this._window.webContents.on('devtools-opened', () => { + this._window.focus(); + setImmediate(() => { + this._window.focus(); + }); + }); + } + + public get window(): BrowserWindow | any { + return this._window; + } +} diff --git a/src/electron/main.ts b/src/electron/main.ts new file mode 100644 index 0000000..ae90f32 --- /dev/null +++ b/src/electron/main.ts @@ -0,0 +1,3 @@ +import { App } from './components/app'; + +App.launch(); diff --git a/src/electron/preload.ts b/src/electron/preload.ts new file mode 100644 index 0000000..5301eda --- /dev/null +++ b/src/electron/preload.ts @@ -0,0 +1 @@ +console.log('The preload script has been injected successfully.'); diff --git a/src/electron/tsconfig.json b/src/electron/tsconfig.json new file mode 100644 index 0000000..430f6d3 --- /dev/null +++ b/src/electron/tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "../../dist/electron" + }, + "include": ["./**/*.ts"] +}