From dc31ac0831ae851185c46e4095189bb5199ff2e9 Mon Sep 17 00:00:00 2001 From: Moyasee Date: Tue, 30 Dec 2025 00:25:45 +0200 Subject: [PATCH 1/4] fix: library cards not using placeholder and icon as a game cover --- .../src/pages/library/library-game-card.scss | 20 +++++++++++ .../src/pages/library/library-game-card.tsx | 35 ++++++++++++++----- 2 files changed, 46 insertions(+), 9 deletions(-) diff --git a/src/renderer/src/pages/library/library-game-card.scss b/src/renderer/src/pages/library/library-game-card.scss index ab9a9f2a..a0ef7e29 100644 --- a/src/renderer/src/pages/library/library-game-card.scss +++ b/src/renderer/src/pages/library/library-game-card.scss @@ -221,6 +221,26 @@ left: 0; z-index: 0; } + + &__cover-placeholder { + position: relative; + width: 100%; + height: 100%; + min-width: 100%; + min-height: 100%; + background: linear-gradient( + 90deg, + rgba(255, 255, 255, 0.08) 0%, + rgba(255, 255, 255, 0.04) 50%, + rgba(255, 255, 255, 0.08) 100% + ); + border-radius: 4px; + color: rgba(255, 255, 255, 0.3); + display: flex; + align-items: center; + justify-content: center; + z-index: 0; + } } @keyframes pulse { diff --git a/src/renderer/src/pages/library/library-game-card.tsx b/src/renderer/src/pages/library/library-game-card.tsx index a91176cb..59235e9b 100644 --- a/src/renderer/src/pages/library/library-game-card.tsx +++ b/src/renderer/src/pages/library/library-game-card.tsx @@ -1,7 +1,12 @@ import { LibraryGame } from "@types"; import { useGameCard } from "@renderer/hooks"; -import { memo } from "react"; -import { ClockIcon, AlertFillIcon, TrophyIcon } from "@primer/octicons-react"; +import { memo, useState, useEffect } from "react"; +import { + ClockIcon, + AlertFillIcon, + TrophyIcon, + ImageIcon, +} from "@primer/octicons-react"; import "./library-game-card.scss"; interface LibraryGameCardProps { @@ -26,7 +31,6 @@ export const LibraryGameCard = memo(function LibraryGameCard({ useGameCard(game, onContextMenu); const coverImage = ( - game.customIconUrl ?? game.coverImageUrl ?? game.libraryImageUrl ?? game.libraryHeroImageUrl ?? @@ -34,6 +38,12 @@ export const LibraryGameCard = memo(function LibraryGameCard({ "" ).replaceAll("\\", "/"); + const [imageError, setImageError] = useState(false); + + useEffect(() => { + setImageError(false); + }, [coverImage]); + return ( ); }); From af884d3772de9acd2cc766de4b77ebee43236a0c Mon Sep 17 00:00:00 2001 From: Moyasee Date: Tue, 30 Dec 2025 14:09:04 +0200 Subject: [PATCH 2/4] refactor: simplify cover image assignment in LibraryGameCard --- src/renderer/src/pages/library/library-game-card.tsx | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/renderer/src/pages/library/library-game-card.tsx b/src/renderer/src/pages/library/library-game-card.tsx index 59235e9b..50f74e7a 100644 --- a/src/renderer/src/pages/library/library-game-card.tsx +++ b/src/renderer/src/pages/library/library-game-card.tsx @@ -30,13 +30,7 @@ export const LibraryGameCard = memo(function LibraryGameCard({ const { formatPlayTime, handleCardClick, handleContextMenuClick } = useGameCard(game, onContextMenu); - const coverImage = ( - game.coverImageUrl ?? - game.libraryImageUrl ?? - game.libraryHeroImageUrl ?? - game.iconUrl ?? - "" - ).replaceAll("\\", "/"); + const coverImage = game.coverImageUrl?.replaceAll("\\", "/") ?? ""; const [imageError, setImageError] = useState(false); From 92d87c5d332a8e70add3e168c527fcf83dc349de Mon Sep 17 00:00:00 2001 From: Moyasee Date: Wed, 31 Dec 2025 01:59:25 +0200 Subject: [PATCH 3/4] refactor: remove unnecessary useEffect in LibraryGameCard --- src/renderer/src/pages/library/library-game-card.tsx | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/renderer/src/pages/library/library-game-card.tsx b/src/renderer/src/pages/library/library-game-card.tsx index 50f74e7a..101236ae 100644 --- a/src/renderer/src/pages/library/library-game-card.tsx +++ b/src/renderer/src/pages/library/library-game-card.tsx @@ -1,6 +1,6 @@ import { LibraryGame } from "@types"; import { useGameCard } from "@renderer/hooks"; -import { memo, useState, useEffect } from "react"; +import { memo, useState } from "react"; import { ClockIcon, AlertFillIcon, @@ -34,10 +34,6 @@ export const LibraryGameCard = memo(function LibraryGameCard({ const [imageError, setImageError] = useState(false); - useEffect(() => { - setImageError(false); - }, [coverImage]); - return ( + {filter === "all" && ( + + )} + +
+ + {filter === "unread" && ( + + )} +
+ + ); + + const hasNoNotifications = mergedNotifications.length === 0; + const shouldDisableActions = isClearing || hasNoNotifications; + const renderContent = () => { - if (isLoading && mergedNotifications.length === 0) { + if (isLoading && hasNoNotifications) { return (
{t("loading")} @@ -352,36 +481,61 @@ export default function Notifications() { ); } - if (mergedNotifications.length === 0) { - return ( -
-
- -
-

{t("empty_title")}

-

{t("empty_description")}

-
- ); - } - return (
-
- - +
+ {renderFilterTabs()} +
+ + +
-
- - {displayedNotifications.map(renderNotification)} - -
+ {/* Keep AnimatePresence mounted during clearing to preserve exit animations */} + + + {hasNoNotifications && !isClearing ? ( +
+
+ +
+

{t("empty_title")}

+

+ {filter === "unread" + ? t("empty_filter_description") + : t("empty_description")} +

+
+ ) : ( +
+ + {displayedNotifications.map(renderNotification)} + +
+ )} +
+
- {pagination.hasMore && ( + {pagination.hasMore && !isClearing && (