64 lines
3.4 KiB
JavaScript
64 lines
3.4 KiB
JavaScript
// Entwicklung ohne Handy: startet die gebaute Oberfläche (www/) in einem Fenster in Handygröße
|
|
// und das Node-Backend im Electron-Hauptprozess, verbunden über eine nachgebaute Capacitor-Bridge.
|
|
// cd mobile && node build.js && ../node_modules/.bin/electron dev/electron-dev.js [--user-data-dir=…]
|
|
const { app, BrowserWindow, ipcMain, clipboard } = require('electron');
|
|
const path = require('path');
|
|
const Module = require('module');
|
|
const EventEmitter = require('events');
|
|
const crypto = require('crypto');
|
|
|
|
const WWW = path.join(__dirname, '..', 'www');
|
|
const toWeb = new EventEmitter();
|
|
const fromWeb = new EventEmitter();
|
|
let win;
|
|
|
|
// require('bridge') im Backend auf diese Nachbildung umleiten
|
|
const bridge = {
|
|
channel: { send: (name, ...args) => toWeb.emit('msg', name, args), addListener: (name, fn) => fromWeb.on(name, fn) },
|
|
getDataPath: () => path.join(app.getPath('userData'), 'mobile-data'),
|
|
};
|
|
const resolve = Module._resolveFilename;
|
|
Module._resolveFilename = function (req, ...rest) { return req === 'bridge' ? 'bridge' : resolve.call(this, req, ...rest); };
|
|
require.cache.bridge = { id: 'bridge', filename: 'bridge', loaded: true, exports: bridge };
|
|
|
|
toWeb.on('msg', (name, args) => { if (win && !win.isDestroyed()) win.webContents.send('dev:node', name, args); });
|
|
ipcMain.on('dev:send', (_e, name, args) => fromWeb.emit(name, ...args));
|
|
ipcMain.handle('dev:start', (_e, env) => {
|
|
Object.assign(process.env, env, { DATADIR: bridge.getDataPath() });
|
|
require('fs').mkdirSync(process.env.DATADIR, { recursive: true });
|
|
setTimeout(() => { started = true; require(path.join(WWW, 'nodejs', 'index.js')); }, 500);
|
|
});
|
|
let started;
|
|
ipcMain.handle('dev:ready', async () => { while (!started) await new Promise((r) => setTimeout(r, 100)); });
|
|
ipcMain.handle('dev:native', (_e, method, arg) => {
|
|
if (method === 'vaultKey') return { key: crypto.createHash('sha256').update(app.getPath('userData')).digest('base64') };
|
|
if (method === 'info') return { device: 'Dev Phone', locale: process.env.MRTERM_DEV_LOCALE || 'en-US', version: require('../../package.json').version };
|
|
if (method === 'bioAvailable') return { available: true, enrolled: false };
|
|
if (method === 'bioEnroll' || method === 'bioUnlock') return { secret: Buffer.alloc(32, 1).toString('base64') };
|
|
if (method === 'copy') return clipboard.writeText(arg.text);
|
|
if (method === 'paste') return { text: clipboard.readText() };
|
|
return {};
|
|
});
|
|
|
|
app.whenReady().then(() => {
|
|
win = new BrowserWindow({
|
|
width: 412, height: 870, backgroundColor: '#14161d',
|
|
webPreferences: { preload: path.join(__dirname, 'preload.js'), contextIsolation: true },
|
|
});
|
|
win.loadFile(path.join(WWW, 'index.html'));
|
|
if (process.env.MRTERM_SHOT) {
|
|
const steps = JSON.parse(require('fs').readFileSync(process.env.MRTERM_SHOT, 'utf8'));
|
|
win.webContents.on('console-message', (e) => console.log('[r]', e.message));
|
|
win.webContents.once('did-finish-load', async () => {
|
|
await new Promise((r) => setTimeout(r, 2500));
|
|
for (const s of steps) {
|
|
if (s.js) await win.webContents.executeJavaScript(`(async()=>{${s.js}})();0`).catch((e) => console.log('js', e.message));
|
|
await new Promise((r) => setTimeout(r, s.wait || 900));
|
|
if (s.shot) require('fs').writeFileSync(path.join(process.env.MRTERM_SHOT_OUT, s.shot), (await win.webContents.capturePage()).toPNG());
|
|
}
|
|
app.exit(0);
|
|
});
|
|
}
|
|
});
|
|
app.on('window-all-closed', () => app.exit(0));
|