mirror of
https://github.com/usebruno/bruno.git
synced 2026-06-25 13:45:52 +00:00
* feat: Add Default Sample Collection On First Launch * feat(initial-load): add attribute for app readiness --------- Co-authored-by: Bijin Bruno <bijin@usebruno.com>
235 lines
7.7 KiB
JavaScript
235 lines
7.7 KiB
JavaScript
const fs = require('fs');
|
|
const path = require('path');
|
|
const isDev = require('electron-is-dev');
|
|
|
|
if (isDev) {
|
|
if(!fs.existsSync(path.join(__dirname, '../../bruno-js/src/sandbox/bundle-browser-rollup.js'))) {
|
|
console.log('JS Sandbox libraries have not been bundled yet');
|
|
console.log('Please run the below command \nnpm run sandbox:bundle-libraries --workspace=packages/bruno-js');
|
|
throw new Error('JS Sandbox libraries have not been bundled yet');
|
|
}
|
|
}
|
|
|
|
const { format } = require('url');
|
|
const { BrowserWindow, app, session, Menu, globalShortcut, ipcMain } = require('electron');
|
|
const { setContentSecurityPolicy } = require('electron-util');
|
|
|
|
if (isDev && process.env.ELECTRON_USER_DATA_PATH) {
|
|
console.debug("`ELECTRON_USER_DATA_PATH` found, modifying `userData` path: \n"
|
|
+ `\t${app.getPath("userData")} -> ${process.env.ELECTRON_USER_DATA_PATH}`);
|
|
|
|
app.setPath('userData', process.env.ELECTRON_USER_DATA_PATH);
|
|
}
|
|
|
|
const menuTemplate = require('./app/menu-template');
|
|
const { openCollection } = require('./app/collections');
|
|
const LastOpenedCollections = require('./store/last-opened-collections');
|
|
const registerNetworkIpc = require('./ipc/network');
|
|
const registerCollectionsIpc = require('./ipc/collection');
|
|
const registerFilesystemIpc = require('./ipc/filesystem');
|
|
const registerPreferencesIpc = require('./ipc/preferences');
|
|
const collectionWatcher = require('./app/collection-watcher');
|
|
const { loadWindowState, saveBounds, saveMaximized } = require('./utils/window');
|
|
const registerNotificationsIpc = require('./ipc/notifications');
|
|
const registerGlobalEnvironmentsIpc = require('./ipc/global-environments');
|
|
const { safeParseJSON, safeStringifyJSON } = require('./utils/common');
|
|
const { getDomainsWithCookies } = require('./utils/cookies');
|
|
const { cookiesStore } = require('./store/cookies');
|
|
const onboardUser = require('./app/onboarding');
|
|
|
|
const lastOpenedCollections = new LastOpenedCollections();
|
|
|
|
// Reference: https://content-security-policy.com/
|
|
const contentSecurityPolicy = [
|
|
"default-src 'self'",
|
|
"connect-src 'self' https://*.posthog.com",
|
|
"font-src 'self' https: data:;",
|
|
"frame-src data:",
|
|
// this has been commented out to make oauth2 work
|
|
// "form-action 'none'",
|
|
// we make an exception and allow http for images so that
|
|
// they can be used as link in the embedded markdown editors
|
|
"img-src 'self' blob: data: http: https:",
|
|
"media-src 'self' blob: data: https:",
|
|
"style-src 'self' 'unsafe-inline' https:"
|
|
];
|
|
|
|
setContentSecurityPolicy(contentSecurityPolicy.join(';') + ';');
|
|
|
|
const menu = Menu.buildFromTemplate(menuTemplate);
|
|
|
|
let mainWindow;
|
|
|
|
// Prepare the renderer once the app is ready
|
|
app.on('ready', async () => {
|
|
|
|
if (isDev) {
|
|
const { installExtension, REDUX_DEVTOOLS, REACT_DEVELOPER_TOOLS } = require('electron-devtools-installer');
|
|
try {
|
|
const extensions = await installExtension([REDUX_DEVTOOLS, REACT_DEVELOPER_TOOLS], {
|
|
loadExtensionOptions: {allowFileAccess: true},
|
|
})
|
|
console.log(`Added Extensions: ${extensions.map(ext => ext.name).join(", ")}`)
|
|
await require("node:timers/promises").setTimeout(1000);
|
|
session.defaultSession.getAllExtensions().map((ext) => {
|
|
console.log(`Loading Extension: ${ext.name}`);
|
|
session.defaultSession.loadExtension(ext.path)
|
|
});
|
|
} catch (err) {
|
|
console.error('An error occurred while loading extensions: ', err);
|
|
}
|
|
}
|
|
|
|
Menu.setApplicationMenu(menu);
|
|
const { maximized, x, y, width, height } = loadWindowState();
|
|
|
|
mainWindow = new BrowserWindow({
|
|
x,
|
|
y,
|
|
width,
|
|
height,
|
|
minWidth: 1000,
|
|
minHeight: 640,
|
|
show: false,
|
|
webPreferences: {
|
|
nodeIntegration: true,
|
|
contextIsolation: true,
|
|
preload: path.join(__dirname, 'preload.js'),
|
|
webviewTag: true
|
|
},
|
|
title: 'Bruno',
|
|
icon: path.join(__dirname, 'about/256x256.png')
|
|
// we will bring this back
|
|
// see https://github.com/usebruno/bruno/issues/440
|
|
// autoHideMenuBar: true
|
|
});
|
|
|
|
if (maximized) {
|
|
mainWindow.maximize();
|
|
}
|
|
|
|
mainWindow.once('ready-to-show', () => {
|
|
mainWindow.show();
|
|
});
|
|
const url = isDev
|
|
? 'http://localhost:3000'
|
|
: format({
|
|
pathname: path.join(__dirname, '../web/index.html'),
|
|
protocol: 'file:',
|
|
slashes: true
|
|
});
|
|
|
|
mainWindow.loadURL(url).catch((reason) => {
|
|
console.error(`Error: Failed to load URL: "${url}" (Electron shows a blank screen because of this).`);
|
|
console.error('Original message:', reason);
|
|
if (isDev) {
|
|
console.error(
|
|
'Could not connect to Next.Js dev server, is it running?' +
|
|
' Start the dev server using "npm run dev:web" and restart electron'
|
|
);
|
|
} else {
|
|
console.error(
|
|
'If you are using an official production build: the above error is most likely a bug! ' +
|
|
' Please report this under: https://github.com/usebruno/bruno/issues'
|
|
);
|
|
}
|
|
});
|
|
|
|
const handleBoundsChange = () => {
|
|
if (!mainWindow.isMaximized()) {
|
|
saveBounds(mainWindow);
|
|
}
|
|
};
|
|
|
|
mainWindow.on('resize', handleBoundsChange);
|
|
mainWindow.on('move', handleBoundsChange);
|
|
|
|
mainWindow.on('maximize', () => saveMaximized(true));
|
|
mainWindow.on('unmaximize', () => saveMaximized(false));
|
|
mainWindow.on('close', (e) => {
|
|
e.preventDefault();
|
|
ipcMain.emit('main:start-quit-flow');
|
|
});
|
|
|
|
mainWindow.webContents.on('will-redirect', (event, url) => {
|
|
event.preventDefault();
|
|
if (/^(http:\/\/|https:\/\/)/.test(url)) {
|
|
require('electron').shell.openExternal(url);
|
|
}
|
|
});
|
|
|
|
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
|
|
try {
|
|
const { protocol } = new URL(url);
|
|
if (['https:', 'http:'].includes(protocol)) {
|
|
require('electron').shell.openExternal(url);
|
|
}
|
|
} catch (e) {
|
|
console.error(e);
|
|
}
|
|
return { action: 'deny' };
|
|
});
|
|
|
|
|
|
mainWindow.webContents.on('did-finish-load', async () => {
|
|
let ogSend = mainWindow.webContents.send;
|
|
mainWindow.webContents.send = function(channel, ...args) {
|
|
return ogSend.apply(this, [channel, ...args?.map(_ => {
|
|
// todo: replace this with @msgpack/msgpack encode/decode
|
|
return safeParseJSON(safeStringifyJSON(_));
|
|
})]);
|
|
}
|
|
|
|
// Handle onboarding
|
|
await onboardUser(mainWindow, lastOpenedCollections);
|
|
|
|
// Send cookies list after renderer is ready
|
|
try {
|
|
cookiesStore.initializeCookies();
|
|
const cookiesList = await getDomainsWithCookies();
|
|
mainWindow.webContents.send('main:cookies-update', cookiesList);
|
|
} catch (err) {
|
|
console.error('Failed to load cookies for renderer', err);
|
|
}
|
|
|
|
mainWindow.webContents.send('main:app-loaded');
|
|
});
|
|
|
|
// register all ipc handlers
|
|
registerNetworkIpc(mainWindow);
|
|
registerGlobalEnvironmentsIpc(mainWindow);
|
|
registerCollectionsIpc(mainWindow, collectionWatcher, lastOpenedCollections);
|
|
registerPreferencesIpc(mainWindow, collectionWatcher, lastOpenedCollections);
|
|
registerNotificationsIpc(mainWindow, collectionWatcher);
|
|
registerFilesystemIpc(mainWindow);
|
|
});
|
|
|
|
// Quit the app once all windows are closed
|
|
app.on('before-quit', () => {
|
|
try {
|
|
cookiesStore.saveCookieJar(true);
|
|
} catch (err) {
|
|
console.warn('Failed to flush cookies on quit', err);
|
|
}
|
|
});
|
|
|
|
app.on('window-all-closed', app.quit);
|
|
|
|
// Open collection from Recent menu (#1521)
|
|
app.on('open-file', (event, path) => {
|
|
openCollection(mainWindow, collectionWatcher, path);
|
|
});
|
|
|
|
|
|
// Register the global shortcuts
|
|
app.on('browser-window-focus', () => {
|
|
// Quick fix for Electron issue #29996: https://github.com/electron/electron/issues/29996
|
|
globalShortcut.register('Ctrl+=', () => {
|
|
mainWindow.webContents.setZoomLevel(mainWindow.webContents.getZoomLevel() + 1);
|
|
});
|
|
})
|
|
|
|
// Disable global shortcuts when not focused
|
|
app.on('browser-window-blur', () => {
|
|
globalShortcut.unregisterAll()
|
|
}) |