diff --git a/main.js b/main.js
index 45b12e1..4b77b9d 100644
--- a/main.js
+++ b/main.js
@@ -1,6 +1,7 @@
const { app, BrowserWindow, ipcMain, session, screen, shell } = require('electron');
const fs = require('fs');
const path = require('path');
+const os = require('os');
const PerformanceMonitor = require('./performance-monitor');
const GPUFallback = require('./gpu-fallback');
const GPUConfig = require('./gpu-config');
@@ -443,3 +444,29 @@ ipcMain.handle('apply-gpu-fallback', (event, level) => {
return { error: err.message };
}
});
+
+// About/info handler
+ipcMain.handle('get-about-info', () => {
+ try {
+ return {
+ appName: app.getName(),
+ appVersion: app.getVersion(),
+ isPackaged: app.isPackaged,
+ appPath: app.getAppPath(),
+ userDataPath: app.getPath('userData'),
+ electronVersion: process.versions.electron,
+ chromeVersion: process.versions.chrome,
+ nodeVersion: process.versions.node,
+ v8Version: process.versions.v8,
+ platform: process.platform,
+ arch: process.arch,
+ osType: os.type(),
+ osRelease: os.release(),
+ cpu: os.cpus()?.[0]?.model || 'Unknown CPU',
+ totalMemGB: Math.round((os.totalmem() / (1024 ** 3)) * 10) / 10,
+ };
+ } catch (err) {
+ console.error('Error building about info:', err);
+ return { error: err.message };
+ }
+});
diff --git a/preload.js b/preload.js
index ccf7d7d..330a46c 100644
--- a/preload.js
+++ b/preload.js
@@ -84,4 +84,9 @@ const bookmarksAPI = {
// Expose APIs to main world
contextBridge.exposeInMainWorld('electronAPI', electronAPI);
-contextBridge.exposeInMainWorld('bookmarksAPI', bookmarksAPI);
\ No newline at end of file
+contextBridge.exposeInMainWorld('bookmarksAPI', bookmarksAPI);
+
+// Minimal about API for settings page
+contextBridge.exposeInMainWorld('aboutAPI', {
+ getInfo: () => ipcRenderer.invoke('get-about-info')
+});
\ No newline at end of file
diff --git a/renderer/settings.html b/renderer/settings.html
index f5fee0f..8f097d9 100644
--- a/renderer/settings.html
+++ b/renderer/settings.html
@@ -237,6 +237,36 @@
background: var(--accent);
border-radius: 8px;
}
+
+ /* About actions */
+ .about-actions {
+ display: flex;
+ gap: 10px;
+ align-items: center;
+ flex-wrap: wrap;
+ }
+ .github-btn, .help-btn {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+ padding: 8px 12px;
+ background: var(--primary);
+ color: #fff;
+ border: none;
+ border-radius: 6px;
+ text-decoration: none;
+ cursor: pointer;
+ transition: background 0.2s ease;
+ }
+ .github-btn:hover, .help-btn:hover {
+ background: var(--accent);
+ }
+ .github-btn svg, .help-btn svg {
+ width: 18px;
+ height: 18px;
+ fill: currentColor;
+ display: block;
+ }
@@ -437,8 +467,53 @@
About
- Nebula Browser Experimental Settings
- Version info and links can go here.
+
+
Application
+
+ - Name: Loading...
+ - Version: Loading...
+ - Packaged: Loading...
+ - User data: Loading...
+
+
+
+
+
Runtime
+
+ - Electron: Loading...
+ - Chromium: Loading...
+ - Node.js: Loading...
+ - V8: Loading...
+
+
+
+
+
System
+
+ - OS: Loading...
+ - CPU: Loading...
+ - Architecture: Loading...
+ - Memory: Loading...
+
+
+
+
diff --git a/renderer/settings.js b/renderer/settings.js
index 4b7d0d7..9ab0647 100644
--- a/renderer/settings.js
+++ b/renderer/settings.js
@@ -137,3 +137,101 @@ function initTabs() {
window.addEventListener('DOMContentLoaded', () => {
initTabs();
});
+
+// About tab population
+async function populateAbout() {
+ try {
+ const info = (window.aboutAPI && typeof window.aboutAPI.getInfo === 'function')
+ ? await window.aboutAPI.getInfo()
+ : null;
+ if (!info || info.error) {
+ console.warn('[ABOUT] Unable to load about info', info && info.error);
+ return;
+ }
+ const byId = (id) => document.getElementById(id);
+ byId('about-app-name').textContent = info.appName;
+ byId('about-app-version').textContent = info.appVersion;
+ byId('about-packaged').textContent = info.isPackaged ? 'Yes' : 'No';
+ byId('about-userdata').textContent = info.userDataPath;
+
+ byId('about-electron').textContent = info.electronVersion;
+ byId('about-chrome').textContent = info.chromeVersion;
+ byId('about-node').textContent = info.nodeVersion;
+ byId('about-v8').textContent = info.v8Version;
+
+ byId('about-os').textContent = `${info.osType} ${info.osRelease}`;
+ byId('about-cpu').textContent = info.cpu;
+ byId('about-arch').textContent = info.arch;
+ byId('about-mem').textContent = `${info.totalMemGB} GB`;
+
+ const copyBtn = document.getElementById('copy-about-btn');
+ if (copyBtn) {
+ copyBtn.addEventListener('click', async () => {
+ const payload = [
+ `Nebula ${info.appVersion} (${info.isPackaged ? 'packaged' : 'dev'})`,
+ `Electron ${info.electronVersion} | Chromium ${info.chromeVersion} | Node ${info.nodeVersion} | V8 ${info.v8Version}`,
+ `${info.osType} ${info.osRelease} ${info.arch}`,
+ `CPU: ${info.cpu}`,
+ `RAM: ${info.totalMemGB} GB`,
+ `UserData: ${info.userDataPath}`
+ ].join('\n');
+ try {
+ await navigator.clipboard.writeText(payload);
+ showStatus('Diagnostics copied');
+ } catch (err) {
+ console.error('Clipboard error:', err);
+ showStatus('Failed to copy diagnostics');
+ }
+ });
+ }
+ } catch (err) {
+ console.error('[ABOUT] Error populating about info:', err);
+ }
+}
+
+// Populate about info after DOM is ready
+window.addEventListener('DOMContentLoaded', () => {
+ populateAbout();
+});
+
+// Keep settings open when clicking GitHub by asking host to open externally/new tab
+window.addEventListener('DOMContentLoaded', () => {
+ const gh = document.getElementById('github-link');
+ if (gh) {
+ gh.addEventListener('click', (e) => {
+ try {
+ e.preventDefault();
+ const url = gh.getAttribute('href');
+ if (window.electronAPI && typeof window.electronAPI.sendToHost === 'function') {
+ window.electronAPI.sendToHost('navigate', url, { newTab: true });
+ } else if (window.parent) {
+ window.parent.postMessage({ type: 'navigate', url, newTab: true }, '*');
+ } else {
+ window.open(url, '_blank', 'noopener');
+ }
+ } catch (err) {
+ console.error('Failed to open GitHub link:', err);
+ window.open(gh.getAttribute('href'), '_blank');
+ }
+ });
+ }
+ const help = document.getElementById('help-link');
+ if (help) {
+ help.addEventListener('click', (e) => {
+ try {
+ e.preventDefault();
+ const url = help.getAttribute('href');
+ if (window.electronAPI && typeof window.electronAPI.sendToHost === 'function') {
+ window.electronAPI.sendToHost('navigate', url, { newTab: true });
+ } else if (window.parent) {
+ window.parent.postMessage({ type: 'navigate', url, newTab: true }, '*');
+ } else {
+ window.open(url, '_blank', 'noopener');
+ }
+ } catch (err) {
+ console.error('Failed to open Help link:', err);
+ window.open(help.getAttribute('href'), '_blank');
+ }
+ });
+ }
+});
diff --git a/site-history.json b/site-history.json
index 1e23822..46ab1e1 100644
--- a/site-history.json
+++ b/site-history.json
@@ -1,3 +1,8 @@
[
+ "https://nebula.zambazosmedia.group/roadmap.html",
+ "https://nebula.zambazosmedia.group/index.html",
+ "https://nebula.zambazosmedia.group/wiki/index.html",
+ "https://nebula.zambazosmedia.group/",
+ "https://github.com/Bobbybear007/NebulaBrowser",
"https://www.youtube.com/"
]
\ No newline at end of file