/** * Preload + Pear polyfill for the PearData GUI under Electron. * Runs with contextIsolation: false / nodeIntegration: true so app.js can * import HyperDHT packages (pear-electron UI equivalent). */ 'use strict' const { ipcRenderer } = require('electron') const path = require('path') const fs = require('fs') const os = require('os') const cfg = ipcRenderer.sendSync('peardata:get-pear-config') || {} const storage = cfg.storage || process.env.PEARDATA_STORAGE || path.join(os.homedir(), '.config', 'peardata', 'storage') try { fs.mkdirSync(storage, { recursive: true }) } catch { // ignore } const teardownHooks = [] /** Pear surface used by PearData UI */ const Pear = { config: { storage, name: cfg.name || 'PearData', version: cfg.version || '0.0.0', }, app: { storage, name: cfg.name || 'PearData', }, exit(code = 0) { try { ipcRenderer.invoke('peardata:exit', code) } catch { // ignore } }, teardown(fn) { if (typeof fn === 'function') teardownHooks.push(fn) }, constructor: { IPC: null, UI: null, CUTOVER: false, }, } globalThis.Pear = Pear try { window.Pear = Pear } catch { // ignore } // pear-ctrl: platform chrome for frameless / hiddenInset titlebar try { if (typeof customElements !== 'undefined' && !customElements.get('pear-ctrl')) { const platform = (cfg && cfg.platform) || (typeof process !== 'undefined' && process.platform) || 'darwin' class PearCtrl extends HTMLElement { connectedCallback() { this.setAttribute('data-platform', platform) this.setAttribute('role', 'group') this.setAttribute('aria-label', 'Window controls') if (platform === 'darwin') { this.replaceChildren() return } this.replaceChildren() this.classList.add('pd-electron-ctrl') const mkBtn = (action, label, pathD) => { const btn = document.createElement('button') btn.type = 'button' btn.className = `pd-win-btn pd-win-btn--${action}` btn.title = label btn.setAttribute('aria-label', label) btn.innerHTML = `` btn.addEventListener('click', (e) => { e.preventDefault() e.stopPropagation() try { ipcRenderer.invoke(`peardata:window-${action}`) } catch { // ignore } }) return btn } this.append( mkBtn('minimize', 'Minimize', 'M0 5h10v1H0z'), mkBtn('maximize', 'Maximize', 'M1 1h8v8H1V1zm1 1v6h6V2H2z'), mkBtn( 'close', 'Close', 'M1.2 0.5L5 4.3 8.8.5l.7.7L5.7 5l3.8 3.8-.7.7L5 5.7 1.2 9.5l-.7-.7L4.3 5 .5 1.2l.7-.7z' ) ) } } customElements.define('pear-ctrl', PearCtrl) } } catch { // ignore } window.addEventListener('beforeunload', () => { for (const fn of teardownHooks) { try { const r = fn() if (r && typeof r.then === 'function') r.catch(() => {}) } catch { // ignore } } }) console.log('[peardata] Pear polyfill ready, storage=', storage)