Compare commits

...

7 Commits
3-7-5 ... test

Author SHA1 Message Date
Zamitto
20c0d3174b test 2025-11-12 14:37:44 -03:00
Zamitto
cd3fa10bf7 chore: fix version code
Some checks failed
Build / build (ubuntu-latest) (push) Has been cancelled
Build / build (windows-2022) (push) Has been cancelled
2025-11-11 18:27:53 -03:00
Zamitto
a57cc83076 Merge branch 'release/v3.7.5' 2025-11-11 18:17:53 -03:00
Moyase
05d68fa23b Merge pull request #1856 from hydralauncher/fix/library-game-card
fix: custom assets not being showed in library page
2025-11-11 22:10:24 +02:00
Moyasee
527a65e9bc feat: remembering the view user left the library and restoring it on opening library again 2025-11-11 22:07:42 +02:00
Moyasee
fe6bb5763d fix: deleting game from context menu doesnt work in library 2025-11-11 22:03:33 +02:00
Moyasee
002dff098c fix: custom assets not being showed in library page 2025-11-11 21:50:48 +02:00
5 changed files with 56 additions and 15 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "hydralauncher",
"version": "3.7.5",
"version": "3.7.4",
"description": "Hydra",
"main": "./out/main/index.js",
"author": "Los Broxas",

View File

@@ -7,9 +7,25 @@ export function useLibrary() {
const library = useAppSelector((state) => state.library.value);
const updateLibrary = useCallback(async () => {
return window.electron
.getLibrary()
.then((updatedLibrary) => dispatch(setLibrary(updatedLibrary)));
return window.electron.getLibrary().then(async (updatedLibrary) => {
const libraryWithAchievements = await Promise.all(
updatedLibrary.map(async (game) => {
const unlockedAchievements =
await window.electron.getUnlockedAchievements(
game.objectId,
game.shop
);
return {
...game,
unlockedAchievementCount:
game.unlockedAchievementCount || unlockedAchievements.length,
};
})
);
dispatch(setLibrary(libraryWithAchievements));
});
}, [dispatch]);
return { library, updateLibrary };

View File

@@ -12,12 +12,18 @@ interface LibraryGameCardLargeProps {
) => void;
}
const normalizePathForCss = (url: string | null | undefined): string => {
if (!url) return "";
return url.replaceAll("\\", "/");
};
const getImageWithCustomPriority = (
customUrl: string | null | undefined,
originalUrl: string | null | undefined,
fallbackUrl?: string | null | undefined
) => {
return customUrl || originalUrl || fallbackUrl || "";
const selectedUrl = customUrl || originalUrl || fallbackUrl || "";
return normalizePathForCss(selectedUrl);
};
export const LibraryGameCardLarge = memo(function LibraryGameCardLarge({
@@ -30,15 +36,21 @@ export const LibraryGameCardLarge = memo(function LibraryGameCardLarge({
const backgroundImage = useMemo(
() =>
getImageWithCustomPriority(
game.customHeroImageUrl,
game.libraryHeroImageUrl,
game.libraryImageUrl,
game.iconUrl
game.libraryImageUrl ?? game.iconUrl
),
[game.libraryHeroImageUrl, game.libraryImageUrl, game.iconUrl]
[
game.customHeroImageUrl,
game.libraryHeroImageUrl,
game.libraryImageUrl,
game.iconUrl,
]
);
const backgroundStyle = useMemo(
() => ({ backgroundImage: `url(${backgroundImage})` }),
() =>
backgroundImage ? { backgroundImage: `url(${backgroundImage})` } : {},
[backgroundImage]
);
@@ -49,7 +61,7 @@ export const LibraryGameCardLarge = memo(function LibraryGameCardLarge({
[game.unlockedAchievementCount, game.achievementCount]
);
const logoImage = game.logoImageUrl;
const logoImage = game.customLogoImageUrl ?? game.logoImageUrl;
return (
<button

View File

@@ -25,12 +25,14 @@ export const LibraryGameCard = memo(function LibraryGameCard({
const { formatPlayTime, handleCardClick, handleContextMenuClick } =
useGameCard(game, onContextMenu);
const coverImage =
const coverImage = (
game.customIconUrl ??
game.coverImageUrl ??
game.libraryImageUrl ??
game.libraryHeroImageUrl ??
game.iconUrl ??
undefined;
""
).replaceAll("\\", "/");
return (
<button

View File

@@ -19,7 +19,10 @@ export default function Library() {
onLibraryBatchComplete?: (cb: () => void) => () => void;
};
const [viewMode, setViewMode] = useState<ViewMode>("compact");
const [viewMode, setViewMode] = useState<ViewMode>(() => {
const savedViewMode = localStorage.getItem("library-view-mode");
return (savedViewMode as ViewMode) || "compact";
});
const [filterBy, setFilterBy] = useState<FilterOption>("all");
const [contextMenu, setContextMenu] = useState<{
game: LibraryGame | null;
@@ -31,6 +34,11 @@ export default function Library() {
const dispatch = useAppDispatch();
const { t } = useTranslation("library");
const handleViewModeChange = useCallback((mode: ViewMode) => {
setViewMode(mode);
localStorage.setItem("library-view-mode", mode);
}, []);
useEffect(() => {
dispatch(setHeaderTitle(t("library")));
const electron = (globalThis as unknown as { electron?: ElectronAPI })
@@ -71,7 +79,7 @@ export default function Library() {
);
const handleCloseContextMenu = useCallback(() => {
setContextMenu({ game: null, visible: false, position: { x: 0, y: 0 } });
setContextMenu((prev) => ({ ...prev, visible: false }));
}, []);
const filteredLibrary = useMemo(() => {
@@ -147,7 +155,10 @@ export default function Library() {
</div>
<div className="library__controls-right">
<ViewOptions viewMode={viewMode} onViewModeChange={setViewMode} />
<ViewOptions
viewMode={viewMode}
onViewModeChange={handleViewModeChange}
/>
</div>
</div>
</div>