diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json
index 9a97423b..833685d7 100755
--- a/src/locales/en/translation.json
+++ b/src/locales/en/translation.json
@@ -629,7 +629,11 @@
"game_extracted": "{{title}} extracted successfully",
"friend_started_playing_game": "{{displayName}} started playing a game",
"test_achievement_notification_title": "This is a test notification",
- "test_achievement_notification_description": "Pretty cool, huh?"
+ "test_achievement_notification_description": "Pretty cool, huh?",
+ "scan_games_complete_title": "Scanning for games finished successfully",
+ "scan_games_complete_description": "Found {{count}} games without executable path set",
+ "scan_games_no_results_title": "Scanning for games finished",
+ "scan_games_no_results_description": "No installed games were found"
},
"system_tray": {
"open": "Open Hydra",
diff --git a/src/main/events/library/scan-installed-games.ts b/src/main/events/library/scan-installed-games.ts
index cb123ee9..0bdc818c 100644
--- a/src/main/events/library/scan-installed-games.ts
+++ b/src/main/events/library/scan-installed-games.ts
@@ -1,8 +1,14 @@
import path from "node:path";
import fs from "node:fs";
+import { t } from "i18next";
import { registerEvent } from "../register-event";
import { gamesSublevel } from "@main/level";
-import { GameExecutables, logger, WindowManager } from "@main/services";
+import {
+ GameExecutables,
+ LocalNotificationManager,
+ logger,
+ WindowManager,
+} from "@main/services";
const SCAN_DIRECTORIES = [
String.raw`C:\Games`,
@@ -88,9 +94,32 @@ const scanInstalledGames = async (
WindowManager.mainWindow?.webContents.send("on-library-batch-complete");
+ 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: games.filter((g) => !g.game.executablePath).length,
+ total,
};
};
diff --git a/src/renderer/src/components/header/header.scss b/src/renderer/src/components/header/header.scss
index 0debe0fc..35148ee1 100644
--- a/src/renderer/src/components/header/header.scss
+++ b/src/renderer/src/components/header/header.scss
@@ -61,22 +61,25 @@
cursor: pointer;
transition: all ease 0.2s;
padding: globals.$spacing-unit;
+ display: flex;
+ align-items: center;
+ justify-content: center;
&:hover {
color: #dadbe1;
}
- &--scanning {
+ &--scanning svg {
animation: spin 2s linear infinite;
}
}
@keyframes spin {
from {
- transform: rotate(-0deg);
+ transform: rotate(0deg);
}
to {
- transform: rotate(-360deg);
+ transform: rotate(360deg);
}
}
diff --git a/src/renderer/src/components/header/header.tsx b/src/renderer/src/components/header/header.tsx
index faf60a1e..b84a6dba 100644
--- a/src/renderer/src/components/header/header.tsx
+++ b/src/renderer/src/components/header/header.tsx
@@ -1,6 +1,6 @@
import { useTranslation } from "react-i18next";
import { useEffect, useId, useMemo, useRef, useState } from "react";
-import { useLocation, useNavigate } from "react-router-dom";
+import { useLocation, useNavigate, useSearchParams } from "react-router-dom";
import {
ArrowLeftIcon,
SearchIcon,
@@ -40,6 +40,7 @@ export function Header() {
const navigate = useNavigate();
const location = useLocation();
+ const [searchParams, setSearchParams] = useSearchParams();
const { headerTitle, draggingDisabled } = useAppSelector(
(state) => state.window
@@ -268,6 +269,14 @@ export function Header() {
return () => window.removeEventListener("resize", handleResize);
}, [isDropdownVisible]);
+ useEffect(() => {
+ if (searchParams.get("openScanModal") === "true") {
+ setShowScanModal(true);
+ searchParams.delete("openScanModal");
+ setSearchParams(searchParams, { replace: true });
+ }
+ }, [searchParams, setSearchParams]);
+
return (
<>
;
case "ACHIEVEMENT_UNLOCKED":
return ;
+ case "SCAN_GAMES_COMPLETE":
+ return ;
default:
return ;
}
diff --git a/src/types/index.ts b/src/types/index.ts
index 3ddd660c..39fd0791 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -330,7 +330,8 @@ export type LocalNotificationType =
| "EXTRACTION_COMPLETE"
| "DOWNLOAD_COMPLETE"
| "UPDATE_AVAILABLE"
- | "ACHIEVEMENT_UNLOCKED";
+ | "ACHIEVEMENT_UNLOCKED"
+ | "SCAN_GAMES_COMPLETE";
export interface Notification {
id: string;