refactor: streamline game scanning logic and enhance notification handling

This commit is contained in:
Moyasee
2026-01-19 18:01:55 +02:00
parent fbbb2520e0
commit 2108a523bc
2 changed files with 42 additions and 57 deletions

View File

@@ -28,6 +28,39 @@ interface ScanResult {
total: number;
}
async function searchInDirectories(
executableNames: Set<string>
): Promise<string | null> {
for (const scanDir of SCAN_DIRECTORIES) {
if (!fs.existsSync(scanDir)) continue;
const foundPath = await findExecutableInFolder(scanDir, executableNames);
if (foundPath) return foundPath;
}
return null;
}
async function publishScanNotification(foundCount: number): Promise<void> {
const hasFoundGames = foundCount > 0;
await LocalNotificationManager.createNotification(
"SCAN_GAMES_COMPLETE",
t(
hasFoundGames
? "scan_games_complete_title"
: "scan_games_no_results_title",
{ ns: "notifications" }
),
t(
hasFoundGames
? "scan_games_complete_description"
: "scan_games_no_results_description",
{ ns: "notifications", count: foundCount }
),
{ url: "/library?openScanModal=true" }
);
}
const scanInstalledGames = async (
_event: Electron.IpcMainInvokeEvent
): Promise<ScanResult> => {
@@ -43,84 +76,36 @@ const scanInstalledGames = async (
);
const foundGames: FoundGame[] = [];
const gamesToScan = games.filter((g) => !g.game.executablePath);
for (const { key, game } of games) {
if (game.executablePath) {
continue;
}
for (const { key, game } of gamesToScan) {
const executableNames = GameExecutables.getExecutablesForGame(
game.objectId
);
if (!executableNames || executableNames.length === 0) {
continue;
}
if (!executableNames || executableNames.length === 0) continue;
const normalizedNames = new Set(
executableNames.map((name) => name.toLowerCase())
);
let foundPath: string | null = null;
for (const scanDir of SCAN_DIRECTORIES) {
if (!fs.existsSync(scanDir)) {
continue;
}
foundPath = await findExecutableInFolder(scanDir, normalizedNames);
if (foundPath) {
break;
}
}
const foundPath = await searchInDirectories(normalizedNames);
if (foundPath) {
await gamesSublevel.put(key, {
...game,
executablePath: foundPath,
});
await gamesSublevel.put(key, { ...game, executablePath: foundPath });
logger.info(
`[ScanInstalledGames] Found executable for ${game.objectId}: ${foundPath}`
);
foundGames.push({
title: game.title,
executablePath: foundPath,
});
foundGames.push({ title: game.title, executablePath: foundPath });
}
}
WindowManager.mainWindow?.webContents.send("on-library-batch-complete");
await publishScanNotification(foundGames.length);
const total = games.filter((g) => !g.game.executablePath).length;
const hasFoundGames = foundGames.length > 0;
await LocalNotificationManager.createNotification(
"SCAN_GAMES_COMPLETE",
t(
hasFoundGames
? "scan_games_complete_title"
: "scan_games_no_results_title",
{ ns: "notifications" }
),
t(
hasFoundGames
? "scan_games_complete_description"
: "scan_games_no_results_description",
{ ns: "notifications", count: foundGames.length }
),
{
url: "/library?openScanModal=true",
}
);
return {
foundGames,
total,
};
return { foundGames, total: gamesToScan.length };
};
async function findExecutableInFolder(

View File

@@ -31,7 +31,7 @@ export function ScanGamesModal({
scanResult,
onStartScan,
onClearResult,
}: ScanGamesModalProps) {
}: Readonly<ScanGamesModalProps>) {
const { t } = useTranslation("header");
const handleClose = () => {