Skip to content

Instantly share code, notes, and snippets.

@lilpolymath
Last active October 18, 2022 09:17
Show Gist options
  • Save lilpolymath/64232ae2d91ec6b7bfb22acd2b1a5416 to your computer and use it in GitHub Desktop.
Save lilpolymath/64232ae2d91ec6b7bfb22acd2b1a5416 to your computer and use it in GitHub Desktop.
Electron
/* eslint-disable-line global-require */
import {
app,
BrowserWindow,
BrowserView,
ipcMain,
IpcMainEvent,
} from 'electron';
declare const MAIN_WINDOW_WEBPACK_ENTRY: string;
declare const MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY: string;
let mainWindow: BrowserWindow | null;
const createWindow = (): void => {
// Create the browser window.
mainWindow = new BrowserWindow({
height: 700,
width: 1280,
title: 'Gandalf',
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
sandbox: true,
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
},
});
// and load the index.html of the app.
mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
// Open the DevTools.
mainWindow.webContents.openDevTools();
};
const setupView = (url: string) => {
const view = new BrowserView();
mainWindow.addBrowserView(view);
resizeView(view);
view.webContents.loadURL(url);
};
const resizeView = (view: BrowserView) => {
const bound = mainWindow.getBounds();
view.setBounds({
x: 0,
y: 30,
width: bound.width,
height: bound.height - 30,
});
};
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow);
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
ipcMain.handle('loadnew', (e: IpcMainEvent, message: any) => {
setupView('https://github.com');
console.log(message);
});
import React, { ReactNode } from 'react';
type BrowserLayoutType = {
children: ReactNode;
};
const BrowserLayout = ({ children }: BrowserLayoutType) => {
return (
<div className='browserLayout'>
<button
onClick={() => {
window.api.send('loadnew', 'test event');
}}
>
Open BrowserWindow
</button>
<main className='browserLayout__children'>{children}</main>
</div>
);
};
export default BrowserLayout;
{
"name": "gandalf-desktop",
"productName": "gandalf-desktop",
"version": "1.0.0",
"description": "My Electron application description",
"main": ".webpack/main",
"scripts": {
"start": "electron-forge start",
"package": "electron-forge package",
"make": "electron-forge make",
"publish": "electron-forge publish",
"lint": "eslint --ext .ts,.tsx ."
},
"keywords": [],
"author": {
"name": "Favour",
"email": "[email protected]"
},
"target": "node",
"license": "MIT",
"config": {
"forge": {
"packagerConfig": {},
"makers": [
{
"name": "@electron-forge/maker-squirrel",
"config": {
"name": "gandalf_desktop"
}
},
{
"name": "@electron-forge/maker-zip",
"platforms": [
"darwin"
]
},
{
"name": "@electron-forge/maker-deb",
"config": {}
},
{
"name": "@electron-forge/maker-rpm",
"config": {}
}
],
"plugins": [
[
"@electron-forge/plugin-webpack",
{
"devContentSecurityPolicy": "default-src * self blob: data: gap:; style-src * self 'unsafe-inline' blob: data: gap:; script-src * 'self' 'unsafe-eval' 'unsafe-inline' blob: data: gap:; object-src * 'self' blob: data: gap:; img-src * self 'unsafe-inline' blob: data: gap:; connect-src self * 'unsafe-inline' blob: data: gap:; frame-src * self blob: data: gap:;",
"mainConfig": "./webpack.main.config.js",
"renderer": {
"config": "./webpack.renderer.config.js",
"entryPoints": [
{
"html": "./src/index.html",
"js": "./src/renderer.ts",
"name": "main_window",
"preload": {
"js": "./src/preload.ts"
}
}
]
}
}
]
]
}
},
"devDependencies": {
"@electron-forge/cli": "^6.0.0-beta.67",
"@electron-forge/maker-deb": "^6.0.0-beta.67",
"@electron-forge/maker-rpm": "^6.0.0-beta.67",
"@electron-forge/maker-squirrel": "^6.0.0-beta.67",
"@electron-forge/maker-zip": "^6.0.0-beta.67",
"@electron-forge/plugin-webpack": "6.0.0-beta.67",
"@types/react": "^18.0.21",
"@types/react-dom": "^18.0.6",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"@vercel/webpack-asset-relocator-loader": "1.7.3",
"css-loader": "^6.0.0",
"electron": "21.1.0",
"eslint": "^8.0.1",
"eslint-plugin-import": "^2.25.0",
"fork-ts-checker-webpack-plugin": "^7.2.1",
"node-loader": "^2.0.0",
"style-loader": "^3.0.0",
"ts-loader": "^9.2.2",
"typescript": "~4.5.4"
},
"dependencies": {
"@electron/remote": "^2.0.8",
"@svgr/webpack": "^6.4.0",
"electron-is-dev": "^2.0.0",
"electron-squirrel-startup": "^1.0.0",
"ethers": "^5.7.1",
"path": "^0.12.7",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"wagmi": "^0.7.2"
}
}
import { contextBridge, ipcRenderer, IpcRendererEvent } from 'electron';
export const api = {
/**
* The function below can accessed using `window.api.send`
*/
send: (channel: string, data: string) => {
// whitelisted channels
const validChannels = ['loadnew'];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
/**
* Listen to events
*/
receive: (channel: string, func: (...args: unknown[]) => void) => {
const validChannels = ['fromMain'];
if (validChannels.includes(channel)) {
// Deliberately strip event as it includes `sender`
ipcRenderer.on(channel, (event: IpcRendererEvent, ...args: unknown[]) =>
func(...args)
);
}
},
};
contextBridge.exposeInMainWorld('api', api);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment