Add detailed About panel to settings page
Introduces an About tab in the settings page displaying app, runtime, and system diagnostics. Adds IPC and preload bridge for about info, clipboard copy functionality, and external navigation for GitHub and Help links. Updates site-history.json with relevant links.
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
const { app, BrowserWindow, ipcMain, session, screen, shell } = require('electron');
|
const { app, BrowserWindow, ipcMain, session, screen, shell } = require('electron');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const os = require('os');
|
||||||
const PerformanceMonitor = require('./performance-monitor');
|
const PerformanceMonitor = require('./performance-monitor');
|
||||||
const GPUFallback = require('./gpu-fallback');
|
const GPUFallback = require('./gpu-fallback');
|
||||||
const GPUConfig = require('./gpu-config');
|
const GPUConfig = require('./gpu-config');
|
||||||
@@ -443,3 +444,29 @@ ipcMain.handle('apply-gpu-fallback', (event, level) => {
|
|||||||
return { error: err.message };
|
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 };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -85,3 +85,8 @@ const bookmarksAPI = {
|
|||||||
// Expose APIs to main world
|
// Expose APIs to main world
|
||||||
contextBridge.exposeInMainWorld('electronAPI', electronAPI);
|
contextBridge.exposeInMainWorld('electronAPI', electronAPI);
|
||||||
contextBridge.exposeInMainWorld('bookmarksAPI', bookmarksAPI);
|
contextBridge.exposeInMainWorld('bookmarksAPI', bookmarksAPI);
|
||||||
|
|
||||||
|
// Minimal about API for settings page
|
||||||
|
contextBridge.exposeInMainWorld('aboutAPI', {
|
||||||
|
getInfo: () => ipcRenderer.invoke('get-about-info')
|
||||||
|
});
|
||||||
+77
-2
@@ -237,6 +237,36 @@
|
|||||||
background: var(--accent);
|
background: var(--accent);
|
||||||
border-radius: 8px;
|
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;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@@ -437,8 +467,53 @@
|
|||||||
<!-- About Panel -->
|
<!-- About Panel -->
|
||||||
<section class="tab-panel" id="panel-about" role="tabpanel" aria-labelledby="tab-about">
|
<section class="tab-panel" id="panel-about" role="tabpanel" aria-labelledby="tab-about">
|
||||||
<h2>About</h2>
|
<h2>About</h2>
|
||||||
<p class="note">Nebula Browser Experimental Settings</p>
|
<div class="customization-group">
|
||||||
<p class="note">Version info and links can go here.</p>
|
<h3>Application</h3>
|
||||||
|
<ul id="about-app">
|
||||||
|
<li><strong>Name:</strong> <span id="about-app-name">Loading...</span></li>
|
||||||
|
<li><strong>Version:</strong> <span id="about-app-version">Loading...</span></li>
|
||||||
|
<li><strong>Packaged:</strong> <span id="about-packaged">Loading...</span></li>
|
||||||
|
<li><strong>User data:</strong> <span id="about-userdata" style="word-break: break-all;">Loading...</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="customization-group">
|
||||||
|
<h3>Runtime</h3>
|
||||||
|
<ul id="about-runtime">
|
||||||
|
<li><strong>Electron:</strong> <span id="about-electron">Loading...</span></li>
|
||||||
|
<li><strong>Chromium:</strong> <span id="about-chrome">Loading...</span></li>
|
||||||
|
<li><strong>Node.js:</strong> <span id="about-node">Loading...</span></li>
|
||||||
|
<li><strong>V8:</strong> <span id="about-v8">Loading...</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="customization-group">
|
||||||
|
<h3>System</h3>
|
||||||
|
<ul id="about-system">
|
||||||
|
<li><strong>OS:</strong> <span id="about-os">Loading...</span></li>
|
||||||
|
<li><strong>CPU:</strong> <span id="about-cpu">Loading...</span></li>
|
||||||
|
<li><strong>Architecture:</strong> <span id="about-arch">Loading...</span></li>
|
||||||
|
<li><strong>Memory:</strong> <span id="about-mem">Loading...</span></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="customization-group about-actions">
|
||||||
|
<button id="copy-about-btn">Copy diagnostics</button>
|
||||||
|
<a id="github-link" href="https://github.com/Bobbybear007/NebulaBrowser" class="github-btn" rel="noopener noreferrer">
|
||||||
|
<!-- GitHub mark (Octicons) MIT License -->
|
||||||
|
<svg viewBox="0 0 16 16" aria-hidden="true" focusable="false" role="img">
|
||||||
|
<path d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.01.08-2.11 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.91.08 2.11.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z"/>
|
||||||
|
</svg>
|
||||||
|
<span>GitHub</span>
|
||||||
|
</a>
|
||||||
|
<a id="help-link" href="https://nebula.zambazosmedia.group" class="help-btn" rel="noopener noreferrer">
|
||||||
|
<!-- Help icon -->
|
||||||
|
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false" role="img">
|
||||||
|
<path d="M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20zm0 15a1.25 1.25 0 1 1 0 2.5A1.25 1.25 0 0 1 12 17zm-.02-1.9c-.6 0-1.02-.42-1.02-.98 0-1.97 2.76-1.95 2.76-3.62 0-.77-.66-1.4-1.72-1.4-1 0-1.67.5-2.06 1.22-.3.54-.95.73-1.45.44-.54-.31-.72-1-.42-1.53C7.7 7.7 9.06 6.5 12 6.5c2.26 0 3.98 1.3 3.98 3.35 0 2.74-2.96 2.77-3 3.83-.03.6-.43 1.02-1 1.02z"/>
|
||||||
|
</svg>
|
||||||
|
<span>Help</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -137,3 +137,101 @@ function initTabs() {
|
|||||||
window.addEventListener('DOMContentLoaded', () => {
|
window.addEventListener('DOMContentLoaded', () => {
|
||||||
initTabs();
|
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');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|||||||
@@ -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/"
|
"https://www.youtube.com/"
|
||||||
]
|
]
|
||||||
Reference in New Issue
Block a user