diff --git a/gui/electron/index.html b/gui/electron/index.html
index 7faaa62..cf7d671 100644
--- a/gui/electron/index.html
+++ b/gui/electron/index.html
@@ -53,6 +53,8 @@
window.voxvera.onOnionUrl(url => {
document.getElementById('onion-address').textContent = `Onion address: ${url}`;
+ const tear = document.getElementById('tear_off_link');
+ if (tear) tear.value = url;
});
window.voxvera.onLog((msg, isErr) => {
diff --git a/gui/electron/main.js b/gui/electron/main.js
index da471f3..8d70f9c 100644
--- a/gui/electron/main.js
+++ b/gui/electron/main.js
@@ -5,6 +5,7 @@ const which = require('which');
const fs = require('fs');
let mainWindow;
+let onionProc;
function createWindow() {
mainWindow = new BrowserWindow({
@@ -17,7 +18,50 @@ function createWindow() {
mainWindow.loadFile('index.html');
}
-app.whenReady().then(createWindow);
+function startOnionShare() {
+ const configPath = getConfigPath();
+ const voxveraPath = which.sync('voxvera', { nothrow: true });
+ if (!voxveraPath) {
+ dialog.showErrorBox(
+ 'voxvera not found',
+ 'Install the voxvera CLI and ensure it is in your PATH.'
+ );
+ return;
+ }
+ const build = spawn(voxveraPath, ['--config', configPath, 'build']);
+ build.on('close', () => {
+ const args = ['--config', configPath, 'serve'];
+ onionProc = spawn(voxveraPath, args);
+ onionProc.stdout.on('data', data => {
+ const line = data.toString();
+ process.stdout.write(line);
+ if (mainWindow) {
+ mainWindow.webContents.send('log', { text: line, isError: false });
+ }
+ const m = line.match(/Onion URL:\s*(https?:\/\/[a-z0-9.-]+\.onion)/i);
+ if (m && mainWindow) {
+ mainWindow.webContents.send('onion-url', m[1]);
+ }
+ });
+ onionProc.stderr.on('data', data => {
+ const line = data.toString();
+ process.stderr.write(line);
+ if (mainWindow) {
+ mainWindow.webContents.send('log', { text: line, isError: true });
+ }
+ });
+ onionProc.on('close', code => {
+ if (code !== 0) {
+ dialog.showErrorBox('OnionShare error', `onionshare exited with code ${code}.`);
+ }
+ });
+ });
+}
+
+app.whenReady().then(() => {
+ createWindow();
+ startOnionShare();
+});
function getConfigPath() {
return path.join(__dirname, '..', '..', 'voxvera', 'src', 'config.json');
@@ -43,6 +87,10 @@ ipcMain.handle('run-quickstart', async (_, config) => {
return -1;
}
return new Promise((resolve) => {
+ if (onionProc) {
+ onionProc.kill();
+ onionProc = null;
+ }
const args = ['--config', configPath, 'quickstart', '--non-interactive'];
const proc = spawn(voxveraPath, args);
proc.stdout.on('data', data => {
@@ -77,5 +125,9 @@ ipcMain.handle('run-quickstart', async (_, config) => {
});
app.on('window-all-closed', () => {
+ if (onionProc) {
+ onionProc.kill();
+ onionProc = null;
+ }
if (process.platform !== 'darwin') app.quit();
});