Add crash monitor, OOBE flow & factory-reset

Introduce crash monitoring and an OOBE onboarding flow. Adds a crash logger (koring-crash.log), crash-monitor handler/window, preload-crash bridge, crash UI (crash.html, src/crash.tsx, pages/crash) and a debug page. Main process now sets up crash listeners, startup checks (first-launch, .minecraft), and a config reset/factory-reset that removes Koring.yml, koring-auth.json and background cache and can relaunch the app. Exposes config preloading to renderer, adds OOBE pages/layout, confirm dialog store/UI, trims Silk renderer settings, bumps version to 1.0.1 and adds motion dependency, and registers crash.html in Vite. Various related type and config updates included.
This commit is contained in:
2026-07-12 01:24:31 +08:00
parent 2b19144352
commit 0a2b8bd018
50 changed files with 1867 additions and 296 deletions
+45 -2
View File
@@ -1,5 +1,6 @@
import electron from 'electron';
import path from 'path';
import fs from 'fs';
import { registerConfigHandlers } from './handlers/config';
import { registerAuthHandlers } from './handlers/auth';
import { registerInstallHandlers } from './handlers/install';
@@ -10,17 +11,47 @@ import { registerBackgroundHandlers } from './handlers/background';
import { registerTaskHandlers } from './handlers/task';
import { registerSystemHandlers } from './handlers/system';
import { registerWindowHandlers } from './handlers/window';
import { registerCrashHandlers, setupCrashListeners, testCrashDialog } from './handlers/crash-monitor';
import { loadConfig, saveConfig, configExists } from './config';
const { app } = electron;
const isDev = !app.isPackaged;
// Mutable ref — handlers always read from this
// GPU acceleration flags
app.commandLine.appendSwitch('enable-gpu-rasterization');
app.commandLine.appendSwitch('enable-zero-copy');
const win: { mainWindow: electron.BrowserWindow | null; splashWindow: electron.BrowserWindow | null } = {
mainWindow: null,
splashWindow: null,
};
// Startup checks: .minecraft dir + config file + first launch detection
function runStartupChecks(): { isFirstLaunch: boolean; config: ReturnType<typeof loadConfig> } {
const dataPath = app.isPackaged
? path.dirname(app.getPath('exe'))
: path.join(__dirname, '..');
// 1. Ensure .minecraft directory exists
const minecraftDir = path.join(dataPath, '.minecraft');
if (!fs.existsSync(minecraftDir)) {
fs.mkdirSync(minecraftDir, { recursive: true });
}
// 2. Check if config exists, if not create with defaults
const hasConfig = configExists();
const isFirstLaunch = !hasConfig;
// 3. Load (or create) config
const config = loadConfig();
if (isFirstLaunch) {
saveConfig(config);
}
return { isFirstLaunch, config };
}
function createSplashWindow(): electron.BrowserWindow {
const iconPath = isDev
? path.join(__dirname, '../build/icon.ico')
@@ -101,18 +132,27 @@ function registerAllHandlers() {
registerTaskHandlers(win);
registerSystemHandlers();
registerWindowHandlers(win);
registerCrashHandlers();
}
app.whenReady().then(() => {
registerAllHandlers();
// Run startup checks before creating windows
const { isFirstLaunch, config } = runStartupChecks();
// 1. Show splash immediately
win.splashWindow = createSplashWindow();
// 2. Create main window in background
win.mainWindow = createMainWindow();
// 3. When main window finishes loading, wait a minimum time then transition
// 3. Preload config into renderer before it renders
win.mainWindow.webContents.on('did-finish-load', () => {
win.mainWindow?.webContents.send('config:preload', { config, isFirstLaunch });
});
// 4. When main window finishes loading, wait a minimum time then transition
let mainReady = false;
let splashMinTimeDone = false;
@@ -134,6 +174,9 @@ app.whenReady().then(() => {
tryTransition();
});
// Setup crash listeners on main window
setupCrashListeners(win.mainWindow);
// Minimum splash display time (1.5s)
setTimeout(() => {
splashMinTimeDone = true;