const { app, BrowserWindow, ipcMain } = require('electron') const Path = require('node:path') const URL = require('node:url') const p = require('node:util').promisify const Keypair = require('ppppp-keypair') process.env.ZOOBOARD_DATA ??= Path.join(app.getPath('appData'), 'zooboard') app.setPath('userData', process.env.ZOOBOARD_DATA) const path = Path.resolve(app.getPath('userData'), 'ppppp') const keypairPath = Path.join(path, 'keypair.json') const keypair = Keypair.loadOrCreateSync(keypairPath) const peer = require('secret-stack/bare')() .use(require('secret-stack/plugins/net')) .use(require('secret-handshake-ext/secret-stack')) .use(require('ssb-conn')) .use(require('ppppp-db')) .use(require('ppppp-set')) .use(require('ppppp-dict')) .use(require('ppppp-goals')) .use(require('ppppp-sync')) .use(require('ppppp-gc')) .use(require('ppppp-conductor')) .use(require('ppppp-hub-client')) .use(require('ppppp-promise')) .use(require('ppppp-invite')) .call(null, { shse: { caps: require('ppppp-caps'), }, global: { keypair, path, timers: { inactivity: 10 * 60e3, }, connections: { incoming: { tunnel: [{ transform: 'shse', scope: 'public' }], }, outgoing: { net: [{ transform: 'shse' }], tunnel: [{ transform: 'shse' }], }, }, }, conn: { autostart: false, }, }) // WARNING monkey patch! -------------------------------------- const na = require('sodium-native') na.sodium_malloc = function sodium_malloc_monkey_patched(n) { return Buffer.alloc(n) } na.sodium_free = function sodium_free_monkey_patched() {} // Electron > 20.3.8 breaks a napi method that `sodium_malloc` // depends on to create external buffers. (see v8 memory cage) // // This crashes electron when called by various libraries, so // we monkey-patch this particular function. // ------------------------------------------------------------ function createWindow() { const mainWindow = new BrowserWindow({ width: 1200, height: 800, title: 'Zooboard', webPreferences: { preload: Path.join(__dirname, 'preload.js'), }, }) const startUrl = process.env.ELECTRON_START_URL ?? URL.format({ pathname: Path.join(__dirname, '/../build/index.html'), protocol: 'file:', slashes: true, }) mainWindow.loadURL(startUrl) // mainWindow.webContents.openDevTools() } async function loadAccount() { await peer.db.loaded() const id = await p(peer.db.account.findOrCreate)({ subdomain: 'account' }) await p(peer.set.load)(id) await p(peer.dict.load)(id) return id } app.whenReady().then(() => { ipcMain.handle('loadAccount', loadAccount) createWindow() app.on('activate', function () { if (BrowserWindow.getAllWindows().length === 0) createWindow() }) }) app.on('window-all-closed', function () { if (process.platform !== 'darwin') app.quit() })