Skip to content

Commit bced3d5

Browse files
committed
chore: elecctron health metrics migration
1 parent 66b655a commit bced3d5

5 files changed

Lines changed: 54 additions & 4 deletions

File tree

src-electron/config-staging.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
"identifier": "io.phcode.staging",
33
"stage": "stage",
44
"productName": "Phoenix Code Pre-release",
5+
"trustedElectronDomains": ["phtauri://localhost/", "https://phcode.dev/", "https://staging.phcode.dev/"],
56
"gaMetricsURL": "https://staging.phcode.dev/desktop-metrics.html"
67
}

src-electron/config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const configJson = require('./config-effective.json');
1313
// Core config values
1414
const identifier = configJson.identifier;
1515
const phoenixLoadURL = configJson.phoenixLoadURL;
16+
const gaMetricsURL = configJson.gaMetricsURL;
1617
const stage = configJson.stage;
1718
const version = configJson.version;
1819
const productName = configJson.productName;
@@ -37,6 +38,7 @@ module.exports = {
3738
// App info
3839
identifier,
3940
phoenixLoadURL,
41+
gaMetricsURL,
4042
stage,
4143
version,
4244
productName,

src-electron/main-window-ipc.js

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ function getNextLabel(prefix) {
2727
// Track close handlers per window
2828
const windowCloseHandlers = new Map();
2929

30+
// Callback when all registered windows are closed
31+
let onAllWindowsClosedCallback = null;
32+
3033
function registerWindow(win, label) {
3134
const webContents = win.webContents;
3235
const webContentsId = webContents.id;
@@ -52,6 +55,10 @@ function registerWindow(win, label) {
5255
cleanupWindowTrust(webContentsId, label);
5356
// Clean up security trust
5457
cleanupTrust(webContentsId);
58+
// Notify if all registered windows are closed
59+
if (windowRegistry.size === 0 && onAllWindowsClosedCallback) {
60+
onAllWindowsClosedCallback();
61+
}
5562
});
5663
}
5764

@@ -313,4 +320,8 @@ function getWindowLabel(webContentsId) {
313320
return webContentsToLabel.get(webContentsId) || 'unknown';
314321
}
315322

316-
module.exports = { registerWindowIpcHandlers, registerWindow, setupCloseHandler, windowRegistry, getWindowLabel };
323+
function setOnAllWindowsClosed(callback) {
324+
onAllWindowsClosedCallback = callback;
325+
}
326+
327+
module.exports = { registerWindowIpcHandlers, registerWindow, getWindowLabel, setOnAllWindowsClosed };

src-electron/main.js

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ const fs = require('fs');
55
const { registerAppIpcHandlers, terminateAllProcesses, filterCliArgs } = require('./main-app-ipc');
66
const { registerFsIpcHandlers, getAppDataDir } = require('./main-fs-ipc');
77
const { registerCredIpcHandlers } = require('./main-cred-ipc');
8-
const { registerWindowIpcHandlers, registerWindow } = require('./main-window-ipc');
8+
const { registerWindowIpcHandlers, registerWindow, setOnAllWindowsClosed } = require('./main-window-ipc');
99
const { assertTrusted } = require('./ipc-security');
1010
const { getWindowOptions, trackWindowState, DEFAULTS } = require('./window-state');
11-
const { phoenixLoadURL } = require('./config');
11+
const { phoenixLoadURL, gaMetricsURL } = require('./config');
1212

1313
// Request single instance lock - only one instance of the app should run at a time
1414
const gotTheLock = app.requestSingleInstanceLock();
@@ -22,6 +22,25 @@ if (!gotTheLock) {
2222
// Used for multi-window storage synchronization
2323
const sharedStorageMap = new Map();
2424

25+
// Hidden metrics window for Google Analytics
26+
let metricsWindow = null;
27+
28+
async function createMetricsWindow() {
29+
metricsWindow = new BrowserWindow({
30+
show: false,
31+
width: 400,
32+
height: 300,
33+
webPreferences: {
34+
preload: path.join(__dirname, 'preload.js'),
35+
contextIsolation: true,
36+
nodeIntegration: false
37+
}
38+
});
39+
metricsWindow.loadURL(gaMetricsURL);
40+
// uncomment line below if you want to open dev tools at app start
41+
metricsWindow.webContents.openDevTools();
42+
}
43+
2544
async function createWindow() {
2645
// Get window options with restored state or defaults
2746
const windowOptions = getWindowOptions();
@@ -71,6 +90,11 @@ registerFsIpcHandlers();
7190
registerCredIpcHandlers();
7291
registerWindowIpcHandlers();
7392

93+
// Quit when all registered Phoenix windows are closed (metrics window doesn't count)
94+
setOnAllWindowsClosed(() => {
95+
gracefulShutdown(0);
96+
});
97+
7498
/**
7599
* IPC handlers for electronAPI
76100
* Preload location: contextBridge.exposeInMainWorld('electronAPI', { ... })
@@ -119,6 +143,13 @@ ipcMain.handle('get-src-node-path', (event) => {
119143
return srcNodePath;
120144
});
121145

146+
// Health metrics forwarding to hidden metrics window (no assertTrusted needed - metrics come from Phoenix windows)
147+
ipcMain.on('send-health-metric', (event, payload) => {
148+
if (metricsWindow && !metricsWindow.isDestroyed()) {
149+
metricsWindow.webContents.send('health-metric', payload);
150+
}
151+
});
152+
122153
// Handle quit request from renderer
123154
app.on('quit-requested', (exitCode) => {
124155
gracefulShutdown(exitCode);
@@ -170,6 +201,7 @@ app.whenReady().then(async () => {
170201
}
171202
});
172203

204+
await createMetricsWindow();
173205
await createWindow();
174206
});
175207

src-electron/preload.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,9 @@ contextBridge.exposeInMainWorld('electronAPI', {
139139
onSingleInstance: (callback) => ipcRenderer.on('single-instance', (_event, payload) => callback(payload)),
140140

141141
// Drag and drop: get native file path from a dropped File object
142-
getPathForFile: (file) => webUtils.getPathForFile(file)
142+
getPathForFile: (file) => webUtils.getPathForFile(file),
143+
144+
// Health metrics for Google Analytics (sends to hidden metrics window)
145+
sendHealthMetric: (payload) => ipcRenderer.send('send-health-metric', payload),
146+
onHealthMetric: (callback) => ipcRenderer.on('health-metric', (_event, payload) => callback(payload))
143147
});

0 commit comments

Comments
 (0)