Expand electron-tests into full modular app source with tray+window and production-ready structure
This commit is contained in:
parent
0800b06ae3
commit
ef73b13262
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
node_modules/
|
||||
dist/
|
||||
*.log
|
||||
.DS_Store
|
||||
28
README.md
Normal file
28
README.md
Normal file
@ -0,0 +1,28 @@
|
||||
# electron-tests
|
||||
|
||||
Electron tray/window test app for CI/CD validation.
|
||||
|
||||
## Features
|
||||
|
||||
- Tray icon + context menu
|
||||
- Main desktop window
|
||||
- Simple status UI showing runtime versions
|
||||
|
||||
## Run locally
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
npm start
|
||||
```
|
||||
|
||||
## Build AppImage
|
||||
|
||||
```bash
|
||||
npm run build:linux:amd64
|
||||
npm run build:linux:arm64
|
||||
```
|
||||
|
||||
Artifacts are produced via CI workflows:
|
||||
|
||||
- `electron-linux-amd64`
|
||||
- `electron-linux-arm64`
|
||||
20
index.html
20
index.html
@ -1,20 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Electron Tray Demo</title>
|
||||
<style>
|
||||
body { font-family: Inter, system-ui, Arial, sans-serif; margin: 24px; }
|
||||
h1 { margin-bottom: 8px; }
|
||||
.card { border: 1px solid #ddd; border-radius: 12px; padding: 16px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Electron Tray Demo</h1>
|
||||
<div class="card">
|
||||
<p>This is a test desktop window for the Electron tray application.</p>
|
||||
<p>Close window to hide to tray, use tray menu to show it again.</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
70
main.js
70
main.js
@ -1,70 +0,0 @@
|
||||
const { app, BrowserWindow, Menu, Tray } = require('electron');
|
||||
const path = require('path');
|
||||
|
||||
let tray = null;
|
||||
let mainWindow = null;
|
||||
|
||||
function createWindow() {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 700,
|
||||
height: 420,
|
||||
title: 'Electron Tray Demo',
|
||||
webPreferences: {
|
||||
contextIsolation: true,
|
||||
nodeIntegration: false,
|
||||
},
|
||||
});
|
||||
mainWindow.loadFile(path.join(__dirname, 'index.html'));
|
||||
mainWindow.on('close', (event) => {
|
||||
if (!app.isQuiting) {
|
||||
event.preventDefault();
|
||||
mainWindow.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function createTray() {
|
||||
const iconPath = path.join(__dirname, 'assets', 'trayTemplate.png');
|
||||
tray = new Tray(iconPath);
|
||||
tray.setToolTip('Electron Tray Demo');
|
||||
|
||||
const contextMenu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: 'Show Window',
|
||||
click: () => {
|
||||
if (mainWindow) {
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
click: () => {
|
||||
app.isQuiting = true;
|
||||
app.quit();
|
||||
},
|
||||
},
|
||||
]);
|
||||
|
||||
tray.setContextMenu(contextMenu);
|
||||
tray.on('double-click', () => {
|
||||
if (mainWindow) {
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
createTray();
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
||||
});
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
// keep tray app alive on Linux/macOS
|
||||
});
|
||||
@ -2,7 +2,7 @@
|
||||
"name": "electron-tray-demo",
|
||||
"version": "1.0.0",
|
||||
"description": "Electron tray demo app",
|
||||
"main": "main.js",
|
||||
"main": "src/main/index.js",
|
||||
"author": "marksaitis",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
@ -18,8 +18,7 @@
|
||||
"appId": "io.swissline.electrontraydemo",
|
||||
"productName": "electron_tray_demo",
|
||||
"files": [
|
||||
"main.js",
|
||||
"index.html",
|
||||
"src/**/*",
|
||||
"assets/**/*",
|
||||
"package.json"
|
||||
],
|
||||
|
||||
86
src/main/index.js
Normal file
86
src/main/index.js
Normal file
@ -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
|
||||
});
|
||||
6
src/preload/index.js
Normal file
6
src/preload/index.js
Normal file
@ -0,0 +1,6 @@
|
||||
const { contextBridge } = require('electron');
|
||||
|
||||
contextBridge.exposeInMainWorld('electronTest', {
|
||||
appName: 'Electron Test',
|
||||
runtime: process.versions,
|
||||
});
|
||||
28
src/renderer/index.html
Normal file
28
src/renderer/index.html
Normal file
@ -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>
|
||||
6
src/renderer/renderer.js
Normal file
6
src/renderer/renderer.js
Normal file
@ -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';
|
||||
22
src/renderer/styles.css
Normal file
22
src/renderer/styles.css
Normal file
@ -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; }
|
||||
Loading…
x
Reference in New Issue
Block a user