diff --git a/src/renderer/src/components/search-dropdown/highlight-text.tsx b/src/renderer/src/components/search-dropdown/highlight-text.tsx index 9950c8a1..0d5f0fe4 100644 --- a/src/renderer/src/components/search-dropdown/highlight-text.tsx +++ b/src/renderer/src/components/search-dropdown/highlight-text.tsx @@ -1,11 +1,11 @@ import React from "react"; interface HighlightTextProps { - text: string; - query: string; + readonly text: string; + readonly query: string; } -export function HighlightText({ text, query }: HighlightTextProps) { +export function HighlightText({ text, query }: Readonly) { if (!query.trim()) { return <>{text}; } @@ -20,7 +20,7 @@ export function HighlightText({ text, query }: HighlightTextProps) { } const textWords = text.split(/\b/); - const matches: Array<{ start: number; end: number; text: string }> = []; + const matches: { start: number; end: number; text: string }[] = []; let currentIndex = 0; textWords.forEach((word) => { @@ -45,7 +45,7 @@ export function HighlightText({ text, query }: HighlightTextProps) { matches.sort((a, b) => a.start - b.start); - const mergedMatches: Array<{ start: number; end: number }> = []; + const mergedMatches: { start: number; end: number }[] = []; if (matches.length === 0) { return <>{text}; @@ -63,7 +63,7 @@ export function HighlightText({ text, query }: HighlightTextProps) { } mergedMatches.push(current); - const parts: Array<{ text: string; highlight: boolean }> = []; + const parts: { text: string; highlight: boolean; key: string }[] = []; let lastIndex = 0; mergedMatches.forEach((match) => { @@ -71,12 +71,14 @@ export function HighlightText({ text, query }: HighlightTextProps) { parts.push({ text: text.slice(lastIndex, match.start), highlight: false, + key: `${lastIndex}-${match.start}`, }); } parts.push({ text: text.slice(match.start, match.end), highlight: true, + key: `${match.start}-${match.end}`, }); lastIndex = match.end; @@ -86,18 +88,19 @@ export function HighlightText({ text, query }: HighlightTextProps) { parts.push({ text: text.slice(lastIndex), highlight: false, + key: `${lastIndex}-${text.length}`, }); } return ( <> - {parts.map((part, index) => + {parts.map((part) => part.highlight ? ( - + {part.text} ) : ( - {part.text} + {part.text} ) )} diff --git a/src/renderer/src/components/search-dropdown/search-dropdown.scss b/src/renderer/src/components/search-dropdown/search-dropdown.scss index 78a6fac1..d09b3663 100644 --- a/src/renderer/src/components/search-dropdown/search-dropdown.scss +++ b/src/renderer/src/components/search-dropdown/search-dropdown.scss @@ -46,8 +46,8 @@ justify-content: center; &:hover { - color: #dadbe1; - background-color: rgba(255, 255, 255, 0.1); + color: #ffffff; + background-color: rgba(255, 255, 255, 0.15); } } @@ -83,8 +83,8 @@ background-color: transparent; &:hover { - color: #ff5555; - background-color: rgba(255, 85, 85, 0.1); + color: #ff3333; + background-color: rgba(255, 85, 85, 0.2); } } @@ -144,8 +144,8 @@ } &__highlight { - background-color: rgba(255, 193, 7, 0.3); - color: #ffc107; + background-color: rgba(255, 193, 7, 0.4); + color: #ffa000; font-weight: 600; padding: 0 2px; border-radius: 2px; diff --git a/src/renderer/src/context/game-details/game-details.context.tsx b/src/renderer/src/context/game-details/game-details.context.tsx index 49dcb3d0..29feabf5 100644 --- a/src/renderer/src/context/game-details/game-details.context.tsx +++ b/src/renderer/src/context/game-details/game-details.context.tsx @@ -3,7 +3,6 @@ import { createContext, useCallback, useEffect, useRef, useState } from "react"; import { setHeaderTitle } from "@renderer/features"; import { levelDBService } from "@renderer/services/leveldb.service"; import { orderBy } from "lodash-es"; -import type { DownloadSource } from "@types"; import { getSteamLanguage } from "@renderer/helpers"; import { useAppDispatch, @@ -13,6 +12,7 @@ import { } from "@renderer/hooks"; import type { + DownloadSource, GameRepack, GameShop, GameStats, diff --git a/src/renderer/src/hooks/use-search-suggestions.ts b/src/renderer/src/hooks/use-search-suggestions.ts index f2baa8db..b5c3a67b 100644 --- a/src/renderer/src/hooks/use-search-suggestions.ts +++ b/src/renderer/src/hooks/use-search-suggestions.ts @@ -1,6 +1,7 @@ import { useState, useEffect, useCallback, useRef } from "react"; import { useAppSelector } from "./redux"; import { debounce } from "lodash-es"; +import { logger } from "@renderer/logger"; export interface SearchSuggestion { title: string; @@ -74,13 +75,13 @@ export function useSearchSuggestions( setIsLoading(true); try { - const response = await window.electron.hydraApi.get< - Array<{ + const response = await globalThis.electron.hydraApi.get< + { title: string; objectId: string; shop: string; iconUrl: string | null; - }> + }[] >("/catalogue/search/suggestions", { params: { query: searchQuery, @@ -102,6 +103,7 @@ export function useSearchSuggestions( } catch (error) { if (!abortController.signal.aborted) { setSuggestions([]); + logger.error("Failed to fetch catalogue suggestions", error); } } finally { if (!abortController.signal.aborted) { diff --git a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx index 84541728..387c2356 100644 --- a/src/renderer/src/pages/game-details/modals/game-options-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/game-options-modal.tsx @@ -1,7 +1,7 @@ import { useContext, useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { Button, CheckboxField, Modal, TextField } from "@renderer/components"; -import type { LibraryGame, ShortcutLocation } from "@types"; +import type { Game, LibraryGame, ShortcutLocation } from "@types"; import { gameDetailsContext } from "@renderer/context"; import { DeleteGameModal } from "@renderer/pages/downloads/delete-game-modal"; import { useDownload, useToast, useUserDetails } from "@renderer/hooks"; @@ -13,7 +13,6 @@ import SteamLogo from "@renderer/assets/steam-logo.svg?react"; import { debounce } from "lodash-es"; import { levelDBService } from "@renderer/services/leveldb.service"; import { getGameKey } from "@renderer/helpers"; -import type { Game } from "@types"; import "./game-options-modal.scss"; import { logger } from "@renderer/logger"; @@ -84,9 +83,10 @@ export function GameOptionsModal({ "games" )) as Game | null; if (gameData) { + const trimmedValue = value.trim(); const updated = { ...gameData, - launchOptions: value.trim() !== "" ? value : null, + launchOptions: trimmedValue ? trimmedValue : null, }; await levelDBService.put(gameKey, updated, "games"); } diff --git a/src/renderer/src/pages/game-details/modals/repacks-modal.tsx b/src/renderer/src/pages/game-details/modals/repacks-modal.tsx index 71bdf780..f350222a 100644 --- a/src/renderer/src/pages/game-details/modals/repacks-modal.tsx +++ b/src/renderer/src/pages/game-details/modals/repacks-modal.tsx @@ -15,7 +15,7 @@ import { TextField, CheckboxField, } from "@renderer/components"; -import type { DownloadSource, GameRepack } from "@types"; +import type { DownloadSource, Game, GameRepack } from "@types"; import { DownloadSettingsModal } from "./download-settings-modal"; import { gameDetailsContext } from "@renderer/context"; @@ -25,7 +25,6 @@ import { useDate, useFeature, useAppDispatch } from "@renderer/hooks"; import { clearNewDownloadOptions } from "@renderer/features"; import { levelDBService } from "@renderer/services/leveldb.service"; import { getGameKey } from "@renderer/helpers"; -import type { Game } from "@types"; import "./repacks-modal.scss"; export interface RepacksModalProps { @@ -152,7 +151,6 @@ export function RepacksModal({ }; return levelDBService.put(gameKey, updated, "games"); } - return Promise.resolve(); }) .catch(() => {}); diff --git a/src/renderer/src/pages/home/home.tsx b/src/renderer/src/pages/home/home.tsx index b285da0e..91c9b2ff 100644 --- a/src/renderer/src/pages/home/home.tsx +++ b/src/renderer/src/pages/home/home.tsx @@ -2,13 +2,12 @@ import { useCallback, useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { levelDBService } from "@renderer/services/leveldb.service"; import { orderBy } from "lodash-es"; -import type { DownloadSource } from "@types"; import { useNavigate } from "react-router-dom"; import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; import { Button, GameCard, Hero } from "@renderer/components"; -import type { ShopAssets, Steam250Game } from "@types"; +import type { DownloadSource, ShopAssets, Steam250Game } from "@types"; import flameIconStatic from "@renderer/assets/icons/flame-static.png"; import flameIconAnimated from "@renderer/assets/icons/flame-animated.gif";