Files
peardata/electron/preload.cjs
T
Raven Scott d56c6757a5
CI / test (push) Successful in 57s
Release rolling / release (push) Successful in 4m45s
Updates
2026-07-18 16:41:09 -04:00

130 lines
3.2 KiB
JavaScript

/**
* 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 = `<svg width="10" height="10" viewBox="0 0 10 10" aria-hidden="true"><path fill="currentColor" d="${pathD}"/></svg>`
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)