Expand electron-tests into full modular app source with tray+window and production-ready structure
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
const { app, BrowserWindow, Menu, Tray, nativeImage } = require('electron');
|
||||
const path = require('path');
|
||||
|
||||
let tray = null;
|
||||
let mainWindow = null;
|
||||
|
||||
function createMainWindow() {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 900,
|
||||
height: 560,
|
||||
minWidth: 720,
|
||||
minHeight: 420,
|
||||
title: 'Electron Test App',
|
||||
backgroundColor: '#0f172a',
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, '..', 'preload', 'index.js'),
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
sandbox: true,
|
||||
},
|
||||
});
|
||||
|
||||
mainWindow.loadFile(path.join(__dirname, '..', 'renderer', 'index.html'));
|
||||
|
||||
mainWindow.on('close', (event) => {
|
||||
if (!app.isQuiting) {
|
||||
event.preventDefault();
|
||||
mainWindow.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function buildTrayMenu() {
|
||||
return Menu.buildFromTemplate([
|
||||
{
|
||||
label: 'Show window',
|
||||
click: () => {
|
||||
if (mainWindow) {
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'separator',
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
click: () => {
|
||||
app.isQuiting = true;
|
||||
app.quit();
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
function createTray() {
|
||||
const iconPath = path.join(__dirname, '..', '..', 'assets', 'trayTemplate.png');
|
||||
const icon = nativeImage.createFromPath(iconPath);
|
||||
tray = new Tray(icon);
|
||||
tray.setToolTip('Electron Test');
|
||||
tray.setContextMenu(buildTrayMenu());
|
||||
tray.on('double-click', () => {
|
||||
if (mainWindow) {
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createMainWindow();
|
||||
createTray();
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createMainWindow();
|
||||
} else if (mainWindow) {
|
||||
mainWindow.show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
// keep tray app alive by default
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
const { contextBridge } = require('electron');
|
||||
|
||||
contextBridge.exposeInMainWorld('electronTest', {
|
||||
appName: 'Electron Test',
|
||||
runtime: process.versions,
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Electron Test</title>
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
</head>
|
||||
<body>
|
||||
<main class="page">
|
||||
<h1>Electron Test App</h1>
|
||||
<p class="muted">Tray + Window demo used for CI/CD validation.</p>
|
||||
|
||||
<section class="card">
|
||||
<h2>Status</h2>
|
||||
<ul>
|
||||
<li>Window launched ✅</li>
|
||||
<li>Tray icon active ✅</li>
|
||||
<li>Platform: <span id="platform">...</span></li>
|
||||
<li>Electron: <span id="electron">...</span></li>
|
||||
<li>Node: <span id="node">...</span></li>
|
||||
<li>Chrome: <span id="chrome">...</span></li>
|
||||
</ul>
|
||||
</section>
|
||||
</main>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,6 @@
|
||||
const versions = (window.electronTest && window.electronTest.runtime) || {};
|
||||
|
||||
document.getElementById('platform').textContent = navigator.userAgentData?.platform || navigator.platform || 'unknown';
|
||||
document.getElementById('electron').textContent = versions.electron || 'unknown';
|
||||
document.getElementById('node').textContent = versions.node || 'unknown';
|
||||
document.getElementById('chrome').textContent = versions.chrome || 'unknown';
|
||||
@@ -0,0 +1,22 @@
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: Inter, system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
|
||||
color: #e2e8f0;
|
||||
background: radial-gradient(circle at top left, #1e293b, #0f172a 55%);
|
||||
}
|
||||
.page {
|
||||
max-width: 980px;
|
||||
margin: 0 auto;
|
||||
padding: 24px;
|
||||
}
|
||||
h1 { margin: 0 0 8px; font-size: 32px; }
|
||||
.muted { opacity: .8; margin: 0 0 16px; }
|
||||
.card {
|
||||
border: 1px solid #334155;
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
background: rgba(30, 41, 59, 0.5);
|
||||
}
|
||||
ul { margin: 0; padding-left: 20px; }
|
||||
li { margin: 8px 0; }
|
||||
Reference in New Issue
Block a user