mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-10-27 11:35:23 -07:00
fix(stats): harden server lifecycle and verify compiled runtime (#261)
This commit is contained in:
1 parent
f9c4e892dc
commit
383aed8bad
37 files changed
+1381
-323
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { BrowserWindow, dialog, ipcMain } from 'electron';
|
||||
import * as path from 'path';
|
||||
import { createLogger } from '../../logger.js';
|
||||
import type { WindowGeometry } from '../../types.js';
|
||||
import { IPC_CHANNELS } from '../../shared/ipc/contracts.js';
|
||||
import {
|
||||
@@ -26,9 +27,11 @@ import {
|
||||
} from './stats-window-layer.js';
|
||||
|
||||
let statsWindow: BrowserWindow | null = null;
|
||||
let statsWindowGeneration = 0;
|
||||
let toggleRegistered = false;
|
||||
let nativeDialogLayerRegistered = false;
|
||||
const nativeDialogLayerSuspension = createStatsWindowLayerSuspensionState();
|
||||
const logger = createLogger('main:stats-window');
|
||||
|
||||
export interface StatsWindowOptions {
|
||||
/** Absolute path to stats/dist/ directory */
|
||||
@@ -36,7 +39,9 @@ export interface StatsWindowOptions {
|
||||
/** Absolute path to the compiled preload-stats.js */
|
||||
preloadPath: string;
|
||||
/** Resolve the active stats API base URL */
|
||||
getApiBaseUrl?: () => string;
|
||||
getApiBaseUrl?: () => Promise<string> | string;
|
||||
/** Report server startup failure through the configured notification surface. */
|
||||
onStartupError?: (error: unknown) => void;
|
||||
/** Resolve the active stats toggle key from config */
|
||||
getToggleKey: () => string;
|
||||
/** Resolve the tracked overlay/mpv bounds */
|
||||
@@ -179,8 +184,16 @@ function registerStatsNativeDialogLayerHandlers(): void {
|
||||
* Toggle the stats overlay window: create on first call, then show/hide.
|
||||
* The React app stays mounted across toggles — state is preserved.
|
||||
*/
|
||||
export function toggleStatsOverlay(options: StatsWindowOptions): void {
|
||||
export async function toggleStatsOverlay(options: StatsWindowOptions): Promise<void> {
|
||||
if (!statsWindow) {
|
||||
const generation = statsWindowGeneration;
|
||||
const apiBaseUrl = await Promise.resolve()
|
||||
.then(() => options.getApiBaseUrl?.())
|
||||
.catch((error: unknown) => {
|
||||
options.onStartupError?.(error);
|
||||
throw error;
|
||||
});
|
||||
if (generation !== statsWindowGeneration || statsWindow) return;
|
||||
statsWindow = new BrowserWindow(
|
||||
buildStatsWindowOptions({
|
||||
preloadPath: options.preloadPath,
|
||||
@@ -195,7 +208,7 @@ export function toggleStatsOverlay(options: StatsWindowOptions): void {
|
||||
});
|
||||
|
||||
const indexPath = path.join(options.staticDir, 'index.html');
|
||||
statsWindow.loadFile(indexPath, buildStatsWindowLoadFileOptions(options.getApiBaseUrl?.()));
|
||||
statsWindow.loadFile(indexPath, buildStatsWindowLoadFileOptions(apiBaseUrl));
|
||||
|
||||
statsWindow.on('closed', () => {
|
||||
options.onVisibilityChanged?.(false);
|
||||
@@ -243,7 +256,9 @@ export function registerStatsOverlayToggle(options: StatsWindowOptions): void {
|
||||
if (toggleRegistered) return;
|
||||
toggleRegistered = true;
|
||||
ipcMain.on(IPC_CHANNELS.command.toggleStatsOverlay, () => {
|
||||
toggleStatsOverlay(options);
|
||||
void toggleStatsOverlay(options).catch((error: unknown) => {
|
||||
logger.error('Failed to open stats overlay:', error);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -252,6 +267,7 @@ export function registerStatsOverlayToggle(options: StatsWindowOptions): void {
|
||||
* Call during app quit.
|
||||
*/
|
||||
export function destroyStatsWindow(): void {
|
||||
statsWindowGeneration += 1;
|
||||
if (statsWindow && !statsWindow.isDestroyed()) {
|
||||
statsWindow.destroy();
|
||||
statsWindow = null;
|
||||
|
||||
Reference in new issue
Block a user