feat: removing publishers

This commit is contained in:
Chubby Granny Chaser 2024-12-23 00:42:08 +00:00
parent 4607665908
commit 602ee61cb6
No known key found for this signature in database
8 changed files with 65 additions and 45 deletions

View File

@ -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 }
);
};

View File

@ -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) =>

View File

@ -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<string, string> = {
"/": "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");

View File

@ -49,7 +49,10 @@ declare global {
) => () => Electron.IpcRenderer;
/* Catalogue */
searchGames: (payload: CatalogueSearchPayload) => Promise<any[]>;
searchGames: (
payload: CatalogueSearchPayload,
page: number
) => Promise<{ edges: any[]; count: number }>;
getCatalogue: (category: CatalogueCategory) => Promise<any[]>;
getGameShopDetails: (
objectId: string,

View File

@ -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<Partial<CatalogueSearchPayload>>
) => {
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;

View File

@ -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<DownloadSource[]>([]);
const [games, setGames] = useState<any[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [publishers, setPublishers] = useState<string[]>([]);
const [developers, setDevelopers] = useState<string[]>([]);
const filters = useAppSelector((state) => state.catalogueSearch.value);
const [results, setResults] = useState<any[]>([]);
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() {
))
)}
{/* <div style={{ display: "flex", gap: 8 }}>
<Button theme="outline">1</Button>
<Button theme="outline">2</Button>
</div> */}
{totalPages > 1 && (
<div style={{ display: "flex", gap: 8 }}>
{Array.from({ length: 3 }).map((_, i) => (
<Button theme="outline" key={i} onClick={() => setPage(i + 1)}>
{i + 1}
</Button>
))}
</div>
)}
</div>
<div className="catalogue__filters-container">
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<FilterSection
title={t("genres")}
onClear={() => 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() {
<FilterSection
title={t("tags")}
color={filterCategoryColors.tags}
onClear={() => 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() {
<FilterSection
title={t("developers")}
color={filterCategoryColors.developers}
onClear={() => 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() {
<FilterSection
title={t("publishers")}
color={filterCategoryColors.publishers}
onClear={() => 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] })
);
}
}}

View File

@ -45,6 +45,10 @@ export function FilterSection({
const { formatNumber } = useFormat();
if (!items.length) {
return null;
}
return (
<div>
<div style={{ display: "flex", gap: 8, alignItems: "center" }}>

View File

@ -156,6 +156,7 @@ self.onmessage = async (event: MessageEvent<Payload>) => {
const existingRepacks = await repacksTable.toArray();
for (const downloadSource of downloadSources) {
console.log(downloadSource);
if (!downloadSource.fingerprint) {
await deleteDownloadSource(downloadSource.id);
await importDownloadSource(downloadSource.url);