Skip to content

Commit

Permalink
feat(unreleased): add shortcut to open dev tools in electron
Browse files Browse the repository at this point in the history
also some general electron cleanup
  • Loading branch information
MichaelMakesGames committed Dec 13, 2024
1 parent a9c5dae commit 8db5b4b
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 48 deletions.
1 change: 0 additions & 1 deletion forge.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ const config: ForgeConfig = {
[FuseV1Options.EnableCookieEncryption]: true,
[FuseV1Options.EnableNodeOptionsEnvironmentVariable]: false,
[FuseV1Options.EnableNodeCliInspectArguments]: false,
// [FuseV1Options.GrantFileProtocolExtraPrivileges]: false,
}),
],
};
Expand Down
8 changes: 4 additions & 4 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ fn main() {
// running the electron-forge start command directly here doesn't open the window for some reason
// instead, we write a bash script to a file that the dev start script is watching for
let command = format!(
"npx --package=@electron-forge/cli electron-forge start -- --__PORT__={} --__INVOKE_KEY__='{}' --__ORIGIN__='{}'",
"npx --package=@electron-forge/cli electron-forge start -- --PORT={} --INVOKE_KEY='{}' --ORIGIN='{}'",
invoke_http_port,
app.invoke_key(),
invoke_http_origin,
Expand All @@ -65,9 +65,9 @@ fn main() {
.resolve("electron/games.michaelmakes.stellarmaps-electron", BaseDirectory::Resource)?;
std::process::Command::new(resource_path)
.args([
format!("--__PORT__={}", invoke_http_port),
format!("--__INVOKE_KEY__={}", app.invoke_key()),
format!("--__ORIGIN__={}", invoke_http_origin)
format!("--PORT={}", invoke_http_port),
format!("--INVOKE_KEY={}", app.invoke_key()),
format!("--ORIGIN={}", invoke_http_origin)
])
.spawn()
.expect("electron frontend failed to start");
Expand Down
89 changes: 59 additions & 30 deletions src/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,30 @@ import path from 'node:path';
import { parseArgs } from 'node:util';

import { app, BrowserWindow, ipcMain, nativeImage, session, shell } from 'electron';
import { z } from 'zod';

import icon from '../../resources/icon.png?inline';

const { values: args } = parseArgs({
args: process.argv,
options: {
__PORT__: { type: 'string' },
__INVOKE_KEY__: { type: 'string' },
__ORIGIN__: { type: 'string' },
},
allowPositionals: true,
});
declare const MAIN_WINDOW_VITE_DEV_SERVER_URL: string;
declare const MAIN_WINDOW_VITE_NAME: string;

const args = z
.object({
PORT: z.coerce.number().int().min(1),
INVOKE_KEY: z.string(),
ORIGIN: z.string().url(),
})
.parse(
parseArgs({
args: process.argv,
options: {
PORT: { type: 'string' },
INVOKE_KEY: { type: 'string' },
ORIGIN: { type: 'string' },
},
allowPositionals: true,
}).values,
);

const createWindow = () => {
// Create the browser window.
Expand All @@ -26,30 +38,38 @@ const createWindow = () => {
title: 'StellarMaps',
icon: nativeImage.createFromDataURL(icon),
});
mainWindow.removeMenu();
mainWindow.maximize();

// and load the index.html of the app.
// @ts-expect-error -- provided by @electron-forge/plugin-vite
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
// load the index.html of the app.
if (MAIN_WINDOW_VITE_DEV_SERVER_URL) {
// @ts-expect-error -- provided by @electron-forge/plugin-vite
mainWindow.loadURL(MAIN_WINDOW_VITE_DEV_SERVER_URL);
} else {
mainWindow.loadFile(
// @ts-expect-error -- provided by @electron-forge/plugin-vite
path.join(import.meta.dirname, `../renderer/${MAIN_WINDOW_VITE_NAME}/index.html`),
);
}

ipcMain.handle('get-args', () => args);

// open _blank links in system default browser
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: 'deny' };
});

mainWindow.removeMenu();
mainWindow.maximize();
if (process.env.NODE_ENV === 'development') {
// open dev tools on F12 / Ctrl+Shfit+I / Cmd+Opt+I
mainWindow.webContents.on('before-input-event', (_, input) => {
if (
input.type === 'keyDown' &&
(input.key === 'F12' ||
(input.control && input.shift && input.key === 'I') ||
(input.meta && input.alt && input.key === 'I'))
) {
mainWindow.webContents.toggleDevTools();
}
});

// open dev tools in dev mode
if (!app.isPackaged) {
mainWindow.webContents.openDevTools();
}
};
Expand All @@ -58,34 +78,43 @@ const createWindow = () => {
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', () => {
createWindow();
// tauri invoke http validates the origin, which we fake here
// set up get-args ipc, which is used by preload script
ipcMain.handle('get-args', () => args);

// fake the origin for tauri invoke requests
session.defaultSession.webRequest.onBeforeSendHeaders((details, callback) => {
details.requestHeaders['Origin'] = args.__ORIGIN__ ?? 'tauri://localhost';
details.requestHeaders['Origin'] = args.ORIGIN;
callback({ requestHeaders: details.requestHeaders });
});

// wildcard cors for tauri invoke requests
session.defaultSession.webRequest.onHeadersReceived(
{ urls: [`http://localhost:${args.__PORT__}/*`] },
{ urls: [`http://localhost:${args.PORT}/*`] },
(details, callback) => {
if (details.responseHeaders) {
details.responseHeaders['Access-Control-Allow-Origin'] = ['*'];
}
callback({ responseHeaders: details.responseHeaders });
callback({
responseHeaders: {
...details.responseHeaders,
'Access-Control-Allow-Origin': ['*'],
},
});
},
);

// finally, create the window
createWindow();
});

// when closed, send electron_closed command to tauri
app.on('window-all-closed', async () => {
await fetch(`http://localhost:${args.__PORT__}/main/electron_closed`, {
await fetch(`http://localhost:${args.PORT}/main/electron_closed`, {
method: 'POST',
body: '{}',
headers: {
'Content-Type': 'application/json',
'Tauri-Callback': '12345',
'Tauri-Error': '12345',
'Tauri-Invoke-Key': args.__INVOKE_KEY__ ?? '',
Origin: args.__ORIGIN__ ?? 'tauri://localhost',
'Tauri-Invoke-Key': args.INVOKE_KEY,
Origin: args.ORIGIN,
},
});
app.quit();
Expand Down
26 changes: 13 additions & 13 deletions src/electron/preload.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,25 @@ const { contextBridge, ipcRenderer } = require('electron/renderer');
let __PORT__ = null;
let __INVOKE_KEY__ = null;
const ready = ipcRenderer.invoke('get-args').then((args) => {
__PORT__ = args.__PORT__;
__INVOKE_KEY__ = args.__INVOKE_KEY__;
__PORT__ = args.PORT;
__INVOKE_KEY__ = args.INVOKE_KEY;
});
const __CALLBACKS__ = {};
const CALLBACKS = {};
const __TAURI_INTERNALS__ = {
metadata: { currentWindow: { label: 'main' } },
invoke(cmd, payload, options) {
return new Promise(async (resolve, reject) => {
const callback = window.crypto.getRandomValues(new Uint32Array(1))[0]?.toString() ?? '';
const error = window.crypto.getRandomValues(new Uint32Array(1))[0]?.toString() ?? '';
__CALLBACKS__[callback] = (data) => {
CALLBACKS[callback] = (data) => {
resolve(data);
delete __CALLBACKS__[callback];
delete __CALLBACKS__[error];
delete CALLBACKS[callback];
delete CALLBACKS[error];
};
__CALLBACKS__[error] = (data) => {
CALLBACKS[error] = (data) => {
reject(data);
delete __CALLBACKS__[callback];
delete __CALLBACKS__[error];
delete CALLBACKS[callback];
delete CALLBACKS[error];
};
await ready;
sendIpcMessage({ cmd, callback, error, payload, options });
Expand Down Expand Up @@ -103,12 +103,12 @@ function sendIpcMessage(message) {
}
})
.then(([cb, data]) => {
// tauri-electron: check __CALLBACKS__[cb] instead of window[`_${cb}`]
if (__CALLBACKS__[cb]) {
__CALLBACKS__[cb](data);
// tauri-electron: check CALLBACKS[cb] instead of window[`_${cb}`]
if (CALLBACKS[cb]) {
CALLBACKS[cb](data);
} else {
console.warn(
`[TAURI] Couldn't find callback id {cb} in __CALLBACKS__. This might happen when the app is reloaded while Rust is running an asynchronous operation.`,
`[TAURI] Couldn't find callback id {cb} in CALLBACKS. This might happen when the app is reloaded while Rust is running an asynchronous operation.`,
);
}
});
Expand Down

0 comments on commit 8db5b4b

Please sign in to comment.