From 602ee61cb6dee359685dfe8a23f088e46d163b8b Mon Sep 17 00:00:00 2001 From: Chubby Granny Chaser Date: Mon, 23 Dec 2024 00:42:08 +0000 Subject: [PATCH] feat: removing publishers --- src/main/events/catalogue/search-games.ts | 7 +- src/preload/index.ts | 4 +- src/renderer/src/components/header/header.tsx | 6 +- src/renderer/src/declaration.d.ts | 5 +- src/renderer/src/features/catalogue-search.ts | 14 ++-- .../src/pages/catalogue/catalogue.tsx | 69 +++++++++++-------- .../src/pages/catalogue/filter-section.tsx | 4 ++ .../src/workers/download-sources.worker.ts | 1 + 8 files changed, 65 insertions(+), 45 deletions(-) diff --git a/src/main/events/catalogue/search-games.ts b/src/main/events/catalogue/search-games.ts index 40b3b033..09ac2cee 100644 --- a/src/main/events/catalogue/search-games.ts +++ b/src/main/events/catalogue/search-games.ts @@ -2,13 +2,16 @@ import type { CatalogueSearchPayload } from "@types"; import { registerEvent } from "../register-event"; import { HydraApi } from "@main/services"; +const PAGE_SIZE = 12; + const searchGames = async ( _event: Electron.IpcMainInvokeEvent, - payload: CatalogueSearchPayload + payload: CatalogueSearchPayload, + page: number ) => { return HydraApi.post( "/catalogue/search", - { ...payload, take: 24, skip: 0 }, + { ...payload, take: page * PAGE_SIZE, skip: (page - 1) * PAGE_SIZE }, { needsAuth: false } ); }; diff --git a/src/preload/index.ts b/src/preload/index.ts index 86414e1a..86158bf9 100644 --- a/src/preload/index.ts +++ b/src/preload/index.ts @@ -37,8 +37,8 @@ contextBridge.exposeInMainWorld("electron", { }, /* Catalogue */ - searchGames: (payload: CatalogueSearchPayload) => - ipcRenderer.invoke("searchGames", payload), + searchGames: (payload: CatalogueSearchPayload, page: number) => + ipcRenderer.invoke("searchGames", payload, page), getCatalogue: (category: CatalogueCategory) => ipcRenderer.invoke("getCatalogue", category), getGameShopDetails: (objectId: string, shop: GameShop, language: string) => diff --git a/src/renderer/src/components/header/header.tsx b/src/renderer/src/components/header/header.tsx index 97ecbdc2..739ddd1d 100644 --- a/src/renderer/src/components/header/header.tsx +++ b/src/renderer/src/components/header/header.tsx @@ -7,7 +7,7 @@ import { useAppDispatch, useAppSelector } from "@renderer/hooks"; import * as styles from "./header.css"; import { AutoUpdateSubHeader } from "./auto-update-sub-header"; -import { setSearch } from "@renderer/features"; +import { setFilters } from "@renderer/features"; const pathTitle: Record = { "/": "home", @@ -27,7 +27,7 @@ export function Header() { ); const searchValue = useAppSelector( - (state) => state.catalogueSearch.value.title + (state) => state.catalogueSearch.filters.title ); const dispatch = useAppDispatch(); @@ -59,7 +59,7 @@ export function Header() { }; const handleSearch = (value: string) => { - dispatch(setSearch({ title: value })); + dispatch(setFilters({ title: value })); if (!location.pathname.startsWith("/catalogue")) { navigate("/catalogue"); diff --git a/src/renderer/src/declaration.d.ts b/src/renderer/src/declaration.d.ts index c8033d7e..b1a911f7 100644 --- a/src/renderer/src/declaration.d.ts +++ b/src/renderer/src/declaration.d.ts @@ -49,7 +49,10 @@ declare global { ) => () => Electron.IpcRenderer; /* Catalogue */ - searchGames: (payload: CatalogueSearchPayload) => Promise; + searchGames: ( + payload: CatalogueSearchPayload, + page: number + ) => Promise<{ edges: any[]; count: number }>; getCatalogue: (category: CatalogueCategory) => Promise; getGameShopDetails: ( objectId: string, diff --git a/src/renderer/src/features/catalogue-search.ts b/src/renderer/src/features/catalogue-search.ts index a6318a26..9cddd038 100644 --- a/src/renderer/src/features/catalogue-search.ts +++ b/src/renderer/src/features/catalogue-search.ts @@ -4,11 +4,11 @@ import type { PayloadAction } from "@reduxjs/toolkit"; import type { CatalogueSearchPayload } from "@types"; export interface CatalogueSearchState { - value: CatalogueSearchPayload; + filters: CatalogueSearchPayload; } const initialState: CatalogueSearchState = { - value: { + filters: { title: "", downloadSourceFingerprints: [], tags: [], @@ -22,16 +22,16 @@ export const catalogueSearchSlice = createSlice({ name: "catalogueSearch", initialState, reducers: { - setSearch: ( + setFilters: ( state, action: PayloadAction> ) => { - state.value = { ...state.value, ...action.payload }; + state.filters = { ...state.filters, ...action.payload }; }, - clearSearch: (state) => { - state.value = initialState.value; + clearFilters: (state) => { + state.filters = initialState.filters; }, }, }); -export const { setSearch, clearSearch } = catalogueSearchSlice.actions; +export const { setFilters, clearFilters } = catalogueSearchSlice.actions; diff --git a/src/renderer/src/pages/catalogue/catalogue.tsx b/src/renderer/src/pages/catalogue/catalogue.tsx index 2a120b05..82457f7d 100644 --- a/src/renderer/src/pages/catalogue/catalogue.tsx +++ b/src/renderer/src/pages/catalogue/catalogue.tsx @@ -1,4 +1,4 @@ -import { Badge } from "@renderer/components"; +import { Badge, Button } from "@renderer/components"; import type { DownloadSource } from "@types"; @@ -14,7 +14,7 @@ import { steamUrlBuilder } from "@shared"; import { buildGameDetailsPath } from "@renderer/helpers"; import { useNavigate } from "react-router-dom"; import { FilterSection } from "./filter-section"; -import { setSearch } from "@renderer/features"; +import { setFilters } from "@renderer/features"; import { useTranslation } from "react-i18next"; import axios from "axios"; import Skeleton, { SkeletonTheme } from "react-loading-skeleton"; @@ -35,12 +35,15 @@ export default function Catalogue() { const navigate = useNavigate(); const [downloadSources, setDownloadSources] = useState([]); - const [games, setGames] = useState([]); const [isLoading, setIsLoading] = useState(true); const [publishers, setPublishers] = useState([]); const [developers, setDevelopers] = useState([]); - const filters = useAppSelector((state) => state.catalogueSearch.value); + const [results, setResults] = useState([]); + const [page, setPage] = useState(1); + const [totalPages, setTotalPages] = useState(1); + + const { filters } = useAppSelector((state) => state.catalogueSearch); const dispatch = useAppDispatch(); @@ -49,7 +52,7 @@ export default function Catalogue() { const { getRepacksForObjectId } = useRepacks(); useEffect(() => { - setGames([]); + setResults([]); setIsLoading(true); abortControllerRef.current?.abort(); @@ -57,18 +60,19 @@ export default function Catalogue() { abortControllerRef.current = abortController; window.electron - .searchGames(filters) - .then((games) => { + .searchGames(filters, page) + .then((response) => { if (abortController.signal.aborted) { return; } - setGames(games); + setResults(response.edges); + setTotalPages(Math.ceil(response.count / 12)); }) .finally(() => { setIsLoading(false); }); - }, [filters]); + }, [filters, page, dispatch]); useEffect(() => { window.electron.getDevelopers().then((developers) => { @@ -81,14 +85,14 @@ export default function Catalogue() { }, []); const gamesWithRepacks = useMemo(() => { - return games.map((game) => { + return results.map((game) => { const repacks = getRepacksForObjectId(game.objectId); const uniqueRepackers = Array.from( new Set(repacks.map((repack) => repack.repacker)) ); return { ...game, repacks: uniqueRepackers }; }); - }, [games, getRepacksForObjectId]); + }, [results, getRepacksForObjectId]); useEffect(() => { downloadSourcesTable.toArray().then((sources) => { @@ -264,27 +268,32 @@ export default function Catalogue() { )) )} - {/*
- - -
*/} + {totalPages > 1 && ( +
+ {Array.from({ length: 3 }).map((_, i) => ( + + ))} +
+ )}
dispatch(setSearch({ genres: [] }))} + onClear={() => dispatch(setFilters({ genres: [] }))} color={filterCategoryColors.genres} onSelect={(value) => { if (filters.genres.includes(value)) { dispatch( - setSearch({ + setFilters({ genres: filters.genres.filter((genre) => genre !== value), }) ); } else { - dispatch(setSearch({ genres: [...filters.genres, value] })); + dispatch(setFilters({ genres: [...filters.genres, value] })); } }} items={[ @@ -329,17 +338,17 @@ export default function Catalogue() { dispatch(setSearch({ tags: [] }))} + onClear={() => dispatch(setFilters({ tags: [] }))} onSelect={(value) => { if (filters.tags.includes(Number(value))) { dispatch( - setSearch({ + setFilters({ tags: filters.tags.filter((tag) => tag !== Number(value)), }) ); } else { dispatch( - setSearch({ tags: [...filters.tags, Number(value)] }) + setFilters({ tags: [...filters.tags, Number(value)] }) ); } }} @@ -358,12 +367,12 @@ export default function Catalogue() { title={t("download_sources")} color={filterCategoryColors.downloadSourceFingerprints} onClear={() => - dispatch(setSearch({ downloadSourceFingerprints: [] })) + dispatch(setFilters({ downloadSourceFingerprints: [] })) } onSelect={(value) => { if (filters.downloadSourceFingerprints.includes(value)) { dispatch( - setSearch({ + setFilters({ downloadSourceFingerprints: filters.downloadSourceFingerprints.filter( (fingerprint) => fingerprint !== value @@ -372,7 +381,7 @@ export default function Catalogue() { ); } else { dispatch( - setSearch({ + setFilters({ downloadSourceFingerprints: [ ...filters.downloadSourceFingerprints, value, @@ -393,11 +402,11 @@ export default function Catalogue() { dispatch(setSearch({ developers: [] }))} + onClear={() => dispatch(setFilters({ developers: [] }))} onSelect={(value) => { if (filters.developers.includes(value)) { dispatch( - setSearch({ + setFilters({ developers: filters.developers.filter( (developer) => developer !== value ), @@ -405,7 +414,7 @@ export default function Catalogue() { ); } else { dispatch( - setSearch({ developers: [...filters.developers, value] }) + setFilters({ developers: [...filters.developers, value] }) ); } }} @@ -419,11 +428,11 @@ export default function Catalogue() { dispatch(setSearch({ publishers: [] }))} + onClear={() => dispatch(setFilters({ publishers: [] }))} onSelect={(value) => { if (filters.publishers.includes(value)) { dispatch( - setSearch({ + setFilters({ publishers: filters.publishers.filter( (publisher) => publisher !== value ), @@ -431,7 +440,7 @@ export default function Catalogue() { ); } else { dispatch( - setSearch({ publishers: [...filters.publishers, value] }) + setFilters({ publishers: [...filters.publishers, value] }) ); } }} diff --git a/src/renderer/src/pages/catalogue/filter-section.tsx b/src/renderer/src/pages/catalogue/filter-section.tsx index e82b9ded..4039ab59 100644 --- a/src/renderer/src/pages/catalogue/filter-section.tsx +++ b/src/renderer/src/pages/catalogue/filter-section.tsx @@ -45,6 +45,10 @@ export function FilterSection({ const { formatNumber } = useFormat(); + if (!items.length) { + return null; + } + return (
diff --git a/src/renderer/src/workers/download-sources.worker.ts b/src/renderer/src/workers/download-sources.worker.ts index 185afed5..dd43b682 100644 --- a/src/renderer/src/workers/download-sources.worker.ts +++ b/src/renderer/src/workers/download-sources.worker.ts @@ -156,6 +156,7 @@ self.onmessage = async (event: MessageEvent) => { const existingRepacks = await repacksTable.toArray(); for (const downloadSource of downloadSources) { + console.log(downloadSource); if (!downloadSource.fingerprint) { await deleteDownloadSource(downloadSource.id); await importDownloadSource(downloadSource.url);