mirror of
https://github.com/Pandipipas/scoreko-electron-dev.git
synced 2026-06-06 05:32:06 +00:00
feat: Implement application bootstrap and window management
- Added bootstrap functionality to initialize the Electron application. - Created a new paths module to manage application paths and URLs. - Introduced a shutdown service to handle graceful application shutdowns. - Refactored error logging to use a dedicated logger module. - Implemented process killing logic for NodeCG processes across platforms. - Established navigation policies for internal and external URL handling in windows. - Developed window service for creating and managing application windows. - Added tests for application paths, application controller, navigation policies, process killer, and shutdown service.
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
import { app, BrowserWindow } from "electron";
|
||||
|
||||
import { getRuntimeConfig } from "../config/runtime-config";
|
||||
import { showFatalError, log } from "../errors/error-presenter";
|
||||
import { createNodecgProcessManager } from "../nodecg/process-manager";
|
||||
import { prepareUserNodecgRuntime } from "../nodecg/runtime-provisioner";
|
||||
import { scheduleUpdateCheck } from "../updates/update-manager";
|
||||
import { createLoadingWindow, createMainWindow } from "../windows/window-service";
|
||||
import { createApplicationController } from "./application-controller";
|
||||
import { getApplicationPaths } from "./paths";
|
||||
|
||||
export function bootstrap(): void {
|
||||
const appConfig = getRuntimeConfig();
|
||||
const isDev = !app.isPackaged;
|
||||
const paths = getApplicationPaths({
|
||||
appConfig,
|
||||
appDataPath: app.getPath("appData"),
|
||||
compiledMainDir: __dirname,
|
||||
isDev,
|
||||
resourcesPath: process.resourcesPath,
|
||||
});
|
||||
|
||||
app.setName(appConfig.title);
|
||||
app.setPath("userData", paths.userDataPath);
|
||||
|
||||
const hasSingleInstanceLock = app.requestSingleInstanceLock();
|
||||
|
||||
if (!hasSingleInstanceLock) {
|
||||
app.quit();
|
||||
}
|
||||
|
||||
const controller = createApplicationController({
|
||||
appConfig,
|
||||
appVersion: app.getVersion(),
|
||||
isPackaged: app.isPackaged,
|
||||
isWindows: process.platform === "win32",
|
||||
paths,
|
||||
deps: {
|
||||
createLoadingWindow: () =>
|
||||
createLoadingWindow({
|
||||
allowDevTools: isDev,
|
||||
appConfig,
|
||||
rootPath: paths.rootPath,
|
||||
}),
|
||||
createMainWindow: () =>
|
||||
createMainWindow({
|
||||
allowDevTools: isDev,
|
||||
appConfig,
|
||||
rootPath: paths.rootPath,
|
||||
mainDashboardUrl: paths.mainDashboardUrl,
|
||||
}),
|
||||
createNodecgProcessManager: (runtimePath) =>
|
||||
createNodecgProcessManager({
|
||||
isDev,
|
||||
nodecgRootPath: runtimePath,
|
||||
nodecgBaseUrl: paths.nodecgBaseUrl,
|
||||
appConfig,
|
||||
log,
|
||||
}),
|
||||
getAllWindows: () => BrowserWindow.getAllWindows(),
|
||||
log,
|
||||
prepareRuntime: prepareUserNodecgRuntime,
|
||||
relaunch: () => app.relaunch(),
|
||||
scheduleUpdateCheck: ({ getParentWindow, beforeInstall }) => {
|
||||
scheduleUpdateCheck({
|
||||
appConfig,
|
||||
rootPath: paths.rootPath,
|
||||
getParentWindow: () => getParentWindow() as BrowserWindow | null,
|
||||
beforeInstall,
|
||||
log,
|
||||
});
|
||||
},
|
||||
setAppUserModelId: (userModelId) => app.setAppUserModelId(userModelId),
|
||||
exit: (code) => app.exit(code),
|
||||
},
|
||||
});
|
||||
|
||||
app.on("ready", () => {
|
||||
if (!hasSingleInstanceLock) {
|
||||
return;
|
||||
}
|
||||
|
||||
controller.launch().catch((error: unknown) => {
|
||||
showFatalError("No se pudo iniciar Scoreko.", error);
|
||||
app.exit(1);
|
||||
});
|
||||
});
|
||||
|
||||
app.on("second-instance", () => {
|
||||
controller.focusExistingWindow();
|
||||
});
|
||||
|
||||
app.on("activate", () => {
|
||||
controller.activate().catch((error: unknown) => {
|
||||
showFatalError("No se pudo reactivar Scoreko.", error);
|
||||
});
|
||||
});
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
if (process.platform !== "darwin") {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
app.on("before-quit", (event) => {
|
||||
if (controller.getState() === "stopping" || controller.getState() === "stopped") {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
controller.stopNodecgGracefully().finally(() => {
|
||||
app.quit();
|
||||
});
|
||||
});
|
||||
|
||||
app.on("will-quit", () => {
|
||||
if (controller.getState() !== "stopping" && controller.getState() !== "stopped") {
|
||||
void controller.stopNodecgGracefully();
|
||||
}
|
||||
});
|
||||
|
||||
process.on("exit", () => {
|
||||
if (controller.getState() !== "stopping" && controller.getState() !== "stopped") {
|
||||
void controller.stopNodecgGracefully();
|
||||
}
|
||||
});
|
||||
|
||||
process.on("uncaughtException", (error) => {
|
||||
showFatalError("Unexpected error in Electron main process.", error);
|
||||
});
|
||||
|
||||
process.on("unhandledRejection", (reason) => {
|
||||
showFatalError("Unhandled promise in Electron main process.", reason);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user