Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions application/src/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,10 @@ async function handleLaunchHooks(
if (mainWindow) {
registerMainHandlers(mainWindow);
await startAddonRuntime();
await runStartupTasks(mainWindow);
const startupResult = await runStartupTasks(mainWindow);
if (startupResult.shutdownPending) {
return;
}

// Load the main app with game ID and hook flags
const baseUrl = isDev()
Expand Down Expand Up @@ -232,7 +235,10 @@ async function launchGameById(gameId: number, wrapperCommand?: string | null) {
registerMainHandlers(mainWindow);
await startAddonRuntime();
// Run startup tasks first
await runStartupTasks(mainWindow);
const startupResult = await runStartupTasks(mainWindow);
if (startupResult.shutdownPending) {
return;
}

// Load the main app with the game ID in the query params
// The Svelte frontend will detect this and show the GameLaunchOverlay
Expand Down Expand Up @@ -592,8 +598,14 @@ function createWindow(options: { gameLaunchMode?: boolean } = {}) {

async function startAppFlow(win: BrowserWindow) {
// Run startup tasks; splash updates go to the main window
let shutdownPending = false;
if (win && !win.isDestroyed()) {
await runStartupTasks(win);
const startupResult = await runStartupTasks(win);
shutdownPending = startupResult.shutdownPending;
}

if (shutdownPending) {
return;
}

// Load the main app into the same window (replaces splash)
Expand Down
42 changes: 32 additions & 10 deletions application/src/electron/startup-runner.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { app, BrowserWindow } from 'electron';
import { join } from 'path';
import type { UpdaterCallbacks } from '@/electron/updater.js';
import { createDefaultSystemUpdateManager } from '@/electron/system-updater.js';
import {
createDefaultSystemUpdateManager,
type SystemUpdateResult,
} from '@/electron/system-updater.js';
import {
restoreBackup,
removeCachedAppUpdates,
Expand Down Expand Up @@ -91,6 +94,15 @@ export function closeSplashWindow() {
}
}

export type StartupTasksResult = {
/** When true, an installer update is shutting the app down; do not load the main UI. */
shutdownPending: boolean;
};

function isShutdownPendingFromUpdates(results: SystemUpdateResult[]): boolean {
return results.some((result) => result.updated === true);
}

/**
* Runs all pre-launch startup tasks with splash screen feedback.
* This includes restoring backups, running migrations, checking for updates, etc.
Expand All @@ -103,7 +115,8 @@ export function closeSplashWindow() {
*/
export async function runStartupTasks(
mainWindow?: BrowserWindow | null
): Promise<void> {
): Promise<StartupTasksResult> {
let shutdownPending = false;
try {
if (mainWindow && !mainWindow.isDestroyed()) {
splashTargetWindow = mainWindow;
Expand Down Expand Up @@ -165,15 +178,24 @@ export async function runStartupTasks(
updateSplashProgress(current, total, speed);
},
};
await createDefaultSystemUpdateManager().updateOnlineSystem(
updaterCallbacks
);
const updateResults =
await createDefaultSystemUpdateManager().updateOnlineSystem(
updaterCallbacks
);

// Final status before main window loads
updateSplashStatus('Starting application...');
shutdownPending = isShutdownPendingFromUpdates(updateResults);

// Final status before main window loads (skip when installer update will exit)
if (!shutdownPending) {
updateSplashStatus('Starting application...');
}
} finally {
splashTargetWindow = null;
// Ensure splash window is closed if it was created
closeSplashWindow();
if (!shutdownPending) {
splashTargetWindow = null;
// Ensure splash window is closed if it was created
closeSplashWindow();
}
}

return { shutdownPending };
}
16 changes: 15 additions & 1 deletion application/src/electron/startup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,20 @@ export async function restoreBackup(
return { needsAddonReinstall: false };
}

if (process.platform === 'linux') {
console.log('[backup] Skipping setup backup restore on Linux.');
try {
rmSync(backupDir, { recursive: true, force: true });
console.log('[backup] Removed stale Linux update backup.');
} catch (deleteError: any) {
console.warn(
'[backup] Could not delete stale Linux update backup:',
deleteError.message
);
}
return { needsAddonReinstall: false };
}

const flagPath = join(backupDir, 'needs-addon-reinstall.flag');
needsAddonReinstall = existsSync(flagPath);

Expand All @@ -469,7 +483,7 @@ export async function restoreBackup(
return { needsAddonReinstall };
}

// Check for addon reinstall flag (works for both Windows and Linux)
// Check for addon reinstall flag.
if (needsAddonReinstall) {
needsAddonReinstall = true;
console.log('[backup] Addon reinstall flag found');
Expand Down
24 changes: 16 additions & 8 deletions application/src/electron/updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ import { spawn, exec } from 'child_process';
import { createHash } from 'crypto';
import * as zlib from 'zlib';
import * as path from 'path';
import { __dirname as persistentDataDir } from '@/electron/manager/manager.paths.js';
import { getEffectiveOnlineState } from '@/electron/lib/online.js';
import { __dirname } from '@/electron/manager/manager.paths.js';

function isDev() {
return !app.isPackaged;
Expand Down Expand Up @@ -52,10 +52,6 @@ if (process.platform === 'linux') {
__dirname = './';
}

function getBackupSourceRoot() {
return process.platform === 'linux' ? persistentDataDir : __dirname;
}

/**
* Counts the total number of files to backup, excluding specified directories.
*/
Expand Down Expand Up @@ -151,7 +147,7 @@ async function backupFilesAsync(
updateStatus: (text: string, subtext?: string) => void,
updateProgress: (current: number, total: number, speed: string) => void
): Promise<{ success: boolean; needsAddonReinstall: boolean }> {
const sourceRoot = getBackupSourceRoot();
const sourceRoot = __dirname;

// First, count total files to backup
let totalFiles = 0;
Expand Down Expand Up @@ -591,6 +587,20 @@ async function backupStateForSetupReplacement(
updateProgress: (current: number, total: number, speed: string) => void
) {
const tempFolder = join(app.getPath('temp'), 'ogi-update-backup');

if (process.platform === 'linux') {
console.log('[updater] Skipping setup backup on Linux.');
try {
rmSync(tempFolder, { recursive: true, force: true });
} catch (cleanupError: any) {
console.warn(
'[updater] Failed to clean stale Linux update backup:',
cleanupError.message
);
}
return;
}

updateStatus('Backing up Files', 'Calculating...');

try {
Expand Down Expand Up @@ -868,8 +878,6 @@ export function checkIfInstallerUpdateAvailable(
updateProgress,
});
console.log(`[updater] Setup downloaded successfully.`);
console.log(`[updater] Backing up files in update.`);
await backupStateForSetupReplacement(updateStatus, updateProgress);

updateStatus('Starting Setup');

Expand Down
Loading