fix: fixing download sources migration

This commit is contained in:
Chubby Granny Chaser 2024-12-22 23:38:54 +00:00
parent f37b92261f
commit 32032e1c8a
No known key found for this signature in database
7 changed files with 204 additions and 600 deletions

View File

@ -279,8 +279,11 @@
"instructions": "Verifique a forma correta de instalar algum deles no seu distro Linux, garantindo assim a execução normal do jogo" "instructions": "Verifique a forma correta de instalar algum deles no seu distro Linux, garantindo assim a execução normal do jogo"
}, },
"catalogue": { "catalogue": {
"next_page": "Próxima página", "search": "Pesquisar…",
"previous_page": "Página anterior" "developers": "Desenvolvedores",
"genres": "Gêneros",
"tags": "Tags",
"download_sources": "Fontes de download"
}, },
"modal": { "modal": {
"close": "Botão de fechar" "close": "Botão de fechar"

View File

@ -74,9 +74,18 @@ export const search = recipe({
}, },
}); });
export const searchButton = style({ export const searchButton = recipe({
base: {
WebkitAppRegion: "no-drag", WebkitAppRegion: "no-drag",
} as ComplexStyleRule); } as ComplexStyleRule,
variants: {
hidden: {
true: {
visibility: "hidden",
},
},
},
});
export const section = style({ export const section = style({
display: "flex", display: "flex",

View File

@ -35,6 +35,10 @@ export function Header() {
return t(pathTitle[location.pathname]); return t(pathTitle[location.pathname]);
}, [location.pathname, headerTitle, t]); }, [location.pathname, headerTitle, t]);
const showSearchButton = useMemo(() => {
return location.pathname.startsWith("/catalogue");
}, [location.pathname]);
const handleBackButtonClick = () => { const handleBackButtonClick = () => {
navigate(-1); navigate(-1);
}; };
@ -71,7 +75,7 @@ export function Header() {
<section className={styles.section}> <section className={styles.section}>
<Button <Button
theme="outline" theme="outline"
className={styles.searchButton} className={styles.searchButton({ hidden: showSearchButton })}
onClick={() => navigate("/catalogue?search=true")} onClick={() => navigate("/catalogue?search=true")}
> >
<SearchIcon /> <SearchIcon />

View File

@ -93,23 +93,13 @@
} }
&__filters-container { &__filters-container {
width: 250px; width: 270px;
min-width: 250px; min-width: 270px;
max-width: 250px; max-width: 270px;
background-color: globals.$dark-background-color; background-color: globals.$dark-background-color;
border-radius: 4px; border-radius: 4px;
padding: 16px; padding: 16px;
border: 1px solid globals.$border-color; border: 1px solid globals.$border-color;
align-self: flex-start; align-self: flex-start;
} }
&__ai-recommendations-button-text {
font-weight: 400;
color: #fff;
background: linear-gradient(0deg, #16b195 50%, #3e62c0 100%);
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: bold;
}
} }

View File

@ -1,4 +1,4 @@
import { Badge, Button } from "@renderer/components"; import { Badge } from "@renderer/components";
import type { DownloadSource } from "@types"; import type { DownloadSource } from "@types";
@ -6,7 +6,7 @@ import cn from "classnames";
import { useAppDispatch, useAppSelector, useRepacks } from "@renderer/hooks"; import { useAppDispatch, useAppSelector, useRepacks } from "@renderer/hooks";
import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { LightBulbIcon, SearchIcon, XIcon } from "@primer/octicons-react"; import { SearchIcon, XIcon } from "@primer/octicons-react";
import "./catalogue.scss"; import "./catalogue.scss";
@ -18,7 +18,8 @@ import { useNavigate, useSearchParams } from "react-router-dom";
import { FilterSection } from "./filter-section"; import { FilterSection } from "./filter-section";
import { setSearch } from "@renderer/features"; import { setSearch } from "@renderer/features";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { steamUserTags } from "./steam-user-tags"; import axios from "axios";
import Skeleton, { SkeletonTheme } from "react-loading-skeleton";
const filterCategoryColors = { const filterCategoryColors = {
genres: "hsl(262deg 50% 47%)", genres: "hsl(262deg 50% 47%)",
@ -35,6 +36,8 @@ export default function Catalogue() {
const [focused, setFocused] = useState(false); const [focused, setFocused] = useState(false);
const [steamUserTags, setSteamUserTags] = useState<any>({});
const [searchParams] = useSearchParams(); const [searchParams] = useSearchParams();
const search = searchParams.get("search"); const search = searchParams.get("search");
@ -42,6 +45,7 @@ export default function Catalogue() {
const [downloadSources, setDownloadSources] = useState<DownloadSource[]>([]); const [downloadSources, setDownloadSources] = useState<DownloadSource[]>([]);
const [games, setGames] = useState<any[]>([]); const [games, setGames] = useState<any[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [publishers, setPublishers] = useState<string[]>([]); const [publishers, setPublishers] = useState<string[]>([]);
const [developers, setDevelopers] = useState<string[]>([]); const [developers, setDevelopers] = useState<string[]>([]);
@ -49,23 +53,29 @@ export default function Catalogue() {
const dispatch = useAppDispatch(); const dispatch = useAppDispatch();
const { t } = useTranslation("catalogue"); const { t, i18n } = useTranslation("catalogue");
const { getRepacksForObjectId } = useRepacks(); const { getRepacksForObjectId } = useRepacks();
useEffect(() => { useEffect(() => {
setGames([]); setGames([]);
setIsLoading(true);
abortControllerRef.current?.abort(); abortControllerRef.current?.abort();
const abortController = new AbortController(); const abortController = new AbortController();
abortControllerRef.current = abortController; abortControllerRef.current = abortController;
window.electron.searchGames(filters).then((games) => { window.electron
.searchGames(filters)
.then((games) => {
if (abortController.signal.aborted) { if (abortController.signal.aborted) {
return; return;
} }
setGames(games); setGames(games);
})
.finally(() => {
setIsLoading(false);
}); });
}, [filters]); }, [filters]);
@ -91,7 +101,7 @@ export default function Catalogue() {
useEffect(() => { useEffect(() => {
downloadSourcesTable.toArray().then((sources) => { downloadSourcesTable.toArray().then((sources) => {
setDownloadSources(sources); setDownloadSources(sources.filter((source) => !!source.fingerprint));
}); });
}, [getRepacksForObjectId]); }, [getRepacksForObjectId]);
@ -107,6 +117,22 @@ export default function Catalogue() {
[dispatch] [dispatch]
); );
useEffect(() => {
axios
.get(
`${import.meta.env.RENDERER_VITE_EXTERNAL_RESOURCES_URL}/steam-user-tags.json`
)
.then((response) => {
const language = i18n.language.split("-")[0];
if (response.data[language]) {
setSteamUserTags(response.data[language]);
} else {
setSteamUserTags(response.data["en"]);
}
});
}, [i18n.language]);
useEffect(() => { useEffect(() => {
if (search) { if (search) {
focusInput(); focusInput();
@ -124,7 +150,8 @@ export default function Catalogue() {
> >
<div <div
className={cn("catalogue__search-container", { className={cn("catalogue__search-container", {
["catalogue__search-container--focused"]: focused, ["catalogue__search-container--focused"]:
focused || !!filters.title,
})} })}
> >
<button <button
@ -185,35 +212,42 @@ export default function Catalogue() {
</Badge> </Badge>
))} ))}
{filters.tags.map((tag) => ( <li
<Badge key={tag}> style={{
<div style={{ display: "flex", gap: 4, alignItems: "center" }}> display: "flex",
{tag} alignItems: "center",
</div> color: vars.color.body,
</Badge> backgroundColor: vars.color.darkBackground,
))} padding: "6px 12px",
borderRadius: 4,
{filters.downloadSourceFingerprints.map((fingerprint) => ( border: `solid 1px ${vars.color.border}`,
<Badge key={fingerprint}> fontSize: 12,
<div style={{ display: "flex", gap: 4, alignItems: "center" }}> }}
>
<div <div
style={{ style={{
width: 10, width: 10,
height: 10, height: 10,
backgroundColor: backgroundColor: filterCategoryColors.genres,
filterCategoryColors.downloadSourceFingerprints,
borderRadius: "50%", borderRadius: "50%",
marginRight: 8,
}} }}
/> />
Action
{ <button
downloadSources.find( type="button"
(source) => source.fingerprint === fingerprint style={{
)?.name color: vars.color.body,
} marginLeft: 4,
</div> display: "flex",
</Badge> alignItems: "center",
))} justifyContent: "center",
cursor: "pointer",
}}
>
<XIcon size={13} />
</button>
</li>
</div> </div>
{/* <Button theme="outline"> {/* <Button theme="outline">
@ -237,7 +271,24 @@ export default function Catalogue() {
gap: 8, gap: 8,
}} }}
> >
{gamesWithRepacks.map((game, i) => ( {isLoading ? (
<SkeletonTheme
baseColor={vars.color.darkBackground}
highlightColor={vars.color.background}
>
{Array.from({ length: 24 }).map((_, i) => (
<Skeleton
key={i}
style={{
height: 105,
borderRadius: 4,
border: `solid 1px ${vars.color.border}`,
}}
/>
))}
</SkeletonTheme>
) : (
gamesWithRepacks.map((game, i) => (
<button <button
type="button" type="button"
key={i} key={i}
@ -282,29 +333,19 @@ export default function Catalogue() {
</div> </div>
</div> </div>
</button> </button>
))} ))
)}
<div style={{ display: "flex", gap: 8 }}> {/* <div style={{ display: "flex", gap: 8 }}>
<Button theme="outline">1</Button> <Button theme="outline">1</Button>
<Button theme="outline">2</Button> <Button theme="outline">2</Button>
</div> </div> */}
</div> </div>
<div className="catalogue__filters-container"> <div className="catalogue__filters-container">
<Button
style={{ width: "100%", marginBottom: 16 }}
theme="outline"
className="catalogue__ai-recommendations-button"
>
<span className="catalogue__ai-recommendations-button-text">
<LightBulbIcon size={14} />
Recomendações por AI
</span>
</Button>
<div style={{ display: "flex", flexDirection: "column", gap: 16 }}> <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>
<FilterSection <FilterSection
title="Genres" title={t("genres")}
onClear={() => dispatch(setSearch({ genres: [] }))} onClear={() => dispatch(setSearch({ genres: [] }))}
color={filterCategoryColors.genres} color={filterCategoryColors.genres}
onSelect={(value) => { onSelect={(value) => {
@ -358,7 +399,7 @@ export default function Catalogue() {
/> />
<FilterSection <FilterSection
title="User tags" title={t("tags")}
color={filterCategoryColors.tags} color={filterCategoryColors.tags}
onClear={() => dispatch(setSearch({ tags: [] }))} onClear={() => dispatch(setSearch({ tags: [] }))}
onSelect={(value) => { onSelect={(value) => {
@ -382,7 +423,7 @@ export default function Catalogue() {
/> />
<FilterSection <FilterSection
title="Download sources" title={t("download_sources")}
color={filterCategoryColors.downloadSourceFingerprints} color={filterCategoryColors.downloadSourceFingerprints}
onClear={() => onClear={() =>
dispatch(setSearch({ downloadSourceFingerprints: [] })) dispatch(setSearch({ downloadSourceFingerprints: [] }))
@ -418,7 +459,7 @@ export default function Catalogue() {
/> />
<FilterSection <FilterSection
title="Developers" title={t("developers")}
color={filterCategoryColors.developers} color={filterCategoryColors.developers}
onClear={() => dispatch(setSearch({ developers: [] }))} onClear={() => dispatch(setSearch({ developers: [] }))}
onSelect={(value) => { onSelect={(value) => {
@ -444,7 +485,7 @@ export default function Catalogue() {
/> />
<FilterSection <FilterSection
title="Publishers" title={t("publishers")}
color={filterCategoryColors.publishers} color={filterCategoryColors.publishers}
onClear={() => dispatch(setSearch({ publishers: [] }))} onClear={() => dispatch(setSearch({ publishers: [] }))}
onSelect={(value) => { onSelect={(value) => {

View File

@ -1,452 +0,0 @@
export const steamUserTags = {
Atmospheric: 4166,
Fantasy: 1684,
Relaxing: 1654,
Funny: 4136,
"Sci-fi": 3942,
Horror: 1667,
"Family Friendly": 5350,
Retro: 4004,
Survival: 1662,
Mystery: 5716,
Dark: 4342,
Comedy: 1719,
"Psychological Horror": 1721,
Sports: 701,
"Old School": 3916,
Medieval: 4172,
Magic: 4057,
Racing: 699,
Building: 1643,
Management: 12472,
Space: 1755,
Tactical: 1708,
Drama: 5984,
Futuristic: 4295,
Logic: 6129,
Romance: 4947,
Crafting: 1702,
"Dark Fantasy": 4604,
Emotional: 5608,
"Survival Horror": 3978,
"1980s": 7743,
Nature: 30358,
Education: 1036,
"1990's": 6691,
Surreal: 1710,
"Post-apocalyptic": 3835,
War: 1678,
Zombies: 1659,
Historical: 3987,
Stealth: 1687,
Investigation: 8369,
Military: 4168,
"LGBTQ+": 44868,
Cyberpunk: 4115,
"Lore-Rich": 3854,
Detective: 5613,
Aliens: 1673,
Thriller: 4064,
Economy: 4695,
Robots: 5752,
Demons: 9541,
"Dark Humor": 5923,
Psychological: 5186,
Driving: 1644,
Supernatural: 10808,
"Comic Book": 1751,
Modern: 5673,
Psychedelic: 1714,
Dystopian: 5030,
Flight: 15045,
"Artificial Intelligence": 7926,
Loot: 4236,
Memes: 10397,
"Alternate History": 4598,
Cats: 17894,
Parkour: 4036,
Mythology: 16094,
Crime: 6378,
"Game Development": 13906,
Destruction: 5363,
Philosophical: 15277,
Capitalism: 4845,
"Dark Comedy": 19995,
Automation: 255534,
Lovecraftian: 7432,
Noir: 6052,
Swordplay: 4608,
Science: 5794,
Cooking: 3920,
America: 13190,
Dragons: 4046,
"World War II": 4150,
Parody: 4878,
Agriculture: 22602,
Conspiracy: 5372,
Gothic: 3952,
"Martial Arts": 6915,
Mechs: 4821,
Underground: 21006,
Satire: 1651,
Pirates: 1681,
Steampunk: 1777,
Dog: 1638,
"Time Travel": 10679,
Mining: 5981,
Transportation: 10383,
Ninja: 1688,
Vampire: 4018,
Tanks: 13276,
Political: 4853,
Otome: 31579,
Underwater: 9157,
Hunting: 9564,
Fishing: 15564,
Trains: 1616,
Dinosaurs: 5160,
Western: 1647,
Hacking: 5502,
Faith: 180368,
Programming: 5432,
Superhero: 1671,
Politics: 4754,
Assassin: 4376,
Gambling: 16250,
Naval: 6910,
Diplomacy: 6310,
Heist: 1680,
Snow: 9803,
Archery: 13382,
"Cold War": 5179,
Sailing: 13577,
"Football (Soccer)": 1254546,
Foreign: 51306,
Offroad: 7622,
Horses: 6041,
Illuminati: 7478,
Sniper: 7423,
Transhumanism: 4137,
Werewolves: 17015,
Mars: 6702,
Boxing: 12190,
Jet: 92092,
Motorbike: 198913,
Golf: 7038,
Bikes: 123332,
"World War I": 5382,
Rome: 6948,
Submarine: 19780,
Basketball: 1746,
Baseball: 5727,
LEGO: 1736,
Skateboarding: 1753,
"Mini Golf": 22955,
Wrestling: 47827,
"Football (American)": 1254552,
Tennis: 5914,
Pool: 17927,
Skating: 96359,
Cycling: 19568,
Motocross: 15868,
"Warhammer 40K": 12286,
Lemmings: 17337,
Hockey: 324176,
Bowling: 7328,
Snowboarding: 28444,
Skiing: 7309,
BMX: 252854,
ATV: 129761,
Indie: 492,
Action: 19,
Casual: 597,
Adventure: 21,
Simulation: 599,
RPG: 122,
Strategy: 9,
"Action-Adventure": 4106,
Software: 8013,
"2D": 3871,
"3D": 4191,
Colorful: 4305,
"Pixel Graphics": 3964,
Cute: 4726,
"First-Person": 3839,
Anime: 4085,
"Third Person": 1697,
Stylized: 4252,
"Top-Down": 4791,
Realistic: 4175,
Cartoony: 4195,
Minimalist: 4094,
"Hand-drawn": 6815,
VR: 21978,
Cartoon: 4562,
"Text-Based": 31275,
Cinematic: 4145,
"2.5D": 4975,
Isometric: 5851,
Abstract: 4400,
"Split Screen": 10816,
"3D Vision": 29363,
Voxel: 1732,
Beautiful: 5411,
FMV: 18594,
"360 Video": 776177,
"Story Rich": 1742,
Combat: 3993,
Controller: 7481,
"Female Protagonist": 7208,
"Choices Matter": 6426,
"Open World": 1695,
PvP: 1775,
PvE: 6730,
Linear: 7250,
"Multiple Endings": 6971,
Physics: 3968,
"Character Customization": 4747,
"Procedural Generation": 5125,
Tabletop: 17389,
"Turn-Based Combat": 4325,
"Turn-Based Tactics": 14139,
"Hack and Slash": 1646,
"Resource Management": 8945,
"Base-Building": 7332,
"Score Attack": 5154,
Narration: 5094,
Conversation: 15172,
Nonlinear: 6869,
Tutorial: 12057,
"Perma Death": 1759,
"Team-Based": 5711,
Deckbuilding: 32322,
"Inventory Management": 6276,
"Level Editor": 8122,
"Grid-Based Movement": 7569,
Moddable: 1669,
"Class-Based": 4155,
"Vehicular Combat": 11104,
"Gun Customization": 5765,
"6DOF": 4835,
Trading: 4202,
"Bullet Time": 5796,
"Time Manipulation": 6625,
"Quick-Time Events": 4559,
"Dynamic Narration": 9592,
"Hex Grid": 1717,
"Naval Combat": 4994,
"Music-Based Procedural Generation": 8253,
"Asymmetric VR": 856791,
Puzzle: 1664,
Arcade: 1773,
Shooter: 1774,
Platformer: 1625,
"Visual Novel": 3799,
Sandbox: 3810,
"Rogue-like": 1716,
"Action RPG": 4231,
"Point & Click": 1698,
"Action Roguelike": 42804,
"Interactive Fiction": 11014,
"Turn-Based Strategy": 1741,
"Dating Sim": 9551,
JRPG: 4434,
"Party-Based RPG": 10695,
"Walking Simulator": 5900,
"Design & Illustration": 84,
"Card Game": 1666,
"Life Sim": 10235,
Utilities: 87,
"Strategy RPG": 17305,
"Board Game": 1770,
RTS: 1676,
"Tower Defense": 1645,
"Web Publishing": 1038,
"City Builder": 4328,
"Beat 'em up": 4158,
"Automobile Sim": 1100687,
"2D Fighter": 4736,
Rhythm: 1752,
"3D Fighter": 6506,
"Farming Sim": 87918,
"Animation & Modeling": 872,
"e-sports": 5055,
"Grand Strategy": 4364,
"Space Sim": 16598,
"Colony Sim": 220585,
"Word Game": 24003,
"Battle Royale": 176981,
MMORPG: 1754,
"Auto Battler": 1084988,
"Audio Production": 1027,
"Video Production": 784,
"God Game": 5300,
"4X": 1670,
MOBA: 1718,
"Photo Editing": 809,
Trivia: 10437,
"Immersive Sim": 9204,
"Political Sim": 26921,
"Outbreak Sim": 1100686,
"Medical Sim": 1100688,
Short: 4234,
Movie: 4700,
Episodic: 4242,
Gaming: 150626,
Documentary: 15339,
Exploration: 3834,
"2D Platformer": 5379,
FPS: 1663,
"Rogue-lite": 3959,
"Shoot 'Em Up": 4255,
"3D Platformer": 5395,
"Side Scroller": 3798,
"Choose Your Own Adventure": 4486,
"Puzzle-Platformer": 5537,
"Hidden Object": 1738,
"Bullet Hell": 4885,
"Dungeon Crawler": 1720,
"Top-Down Shooter": 4637,
Clicker: 379975,
"Third-Person Shooter": 3814,
"Precision Platformer": 3877,
"Time Management": 16689,
"Real Time Tactics": 3813,
"Arena Shooter": 5547,
Collectathon: 5652,
"Tactical RPG": 21725,
Idler: 615955,
Wargame: 4684,
Metroidvania: 1628,
Runner: 8666,
"Card Battler": 791774,
"Souls-like": 29482,
CRPG: 4474,
"Creature Collector": 916648,
"Twin Stick Shooter": 4758,
"Match 3": 1665,
"Mystery Dungeon": 198631,
"Hero Shooter": 620519,
"Spectacle fighter": 4777,
"Looter Shooter": 353880,
Solitaire: 13070,
"Combat Racing": 4102,
"Action RTS": 1723,
Sokoban: 1730,
"Trading Card Game": 9271,
Typing: 1674,
"Boomer Shooter": 1023537,
"Traditional Roguelike": 454187,
"On-Rails Shooter": 56690,
Spelling: 71389,
Roguevania: 922563,
Singleplayer: 4182,
Multiplayer: 3859,
"Co-op": 1685,
"Online Co-Op": 3843,
"Massively Multiplayer": 128,
"Local Multiplayer": 7368,
"Local Co-Op": 3841,
"4 Player Local": 4840,
"Co-op Campaign": 4508,
"Asynchronous Multiplayer": 17770,
"Profile Features Limited": 1003823,
"Demo Available": 21491,
"Adult Content": 65443,
Hentai: 9130,
Fighting: 1743,
Classic: 1693,
Cozy: 97376,
"Open World Survival Craft": 1100689,
Wholesome: 552282,
"Roguelike Deckbuilder": 1091588,
Narrative: 7702,
Immersive: 3934,
"Party Game": 7178,
Party: 7108,
"Escape Room": 769306,
Addictive: 4190,
Nostalgia: 14720,
Farming: 4520,
"Cult Classic": 7782,
Spaceships: 4291,
"Electronic Music": 61357,
Pinball: 6621,
"Social Deduction": 745697,
Ambient: 29855,
Dwarf: 7918,
"Job Simulator": 35079,
Epic: 3965,
"Instrumental Music": 189941,
"Jump Scare": 42089,
"Boss Rush": 11095,
"Rock Music": 337964,
"Tile-Matching": 176733,
Vikings: 11634,
"Extraction Shooter": 1199779,
"8-bit Music": 117648,
"Well-Written": 8461,
Mahjong: 33572,
"Shop Keeper": 91114,
Electronic: 143739,
Birds: 6214,
Dice: 7556,
Musou: 323922,
Fox: 30927,
Coding: 42329,
Elf: 102530,
"Hobby Sim": 1220528,
Cricket: 158638,
Rugby: 49213,
Volleyball: 847164,
Snooker: 363767,
Reboot: 5941,
"Based On A Novel": 3796,
"Free to Play": 113,
"Early Access": 493,
Experimental: 13782,
"Software Training": 1445,
Minigames: 8093,
Remake: 5708,
Sequel: 5230,
Experience: 9994,
Kickstarter: 5153,
Crowdfunded: 7113,
Benchmark: 5407,
"Feature Film": 233824,
Difficult: 4026,
Competitive: 3878,
Unforgiving: 1733,
"Turn-Based": 1677,
"Replay Value": 4711,
"Fast-Paced": 1734,
"Real-Time": 4161,
"Real-Time with Pause": 7107,
"Time Attack": 5390,
"Sexual Content": 12095,
Nudity: 6650,
Mature: 5611,
NSFW: 24904,
"Character Action Game": 3955,
"Villain Protagonist": 11333,
"Silent Protagonist": 15954,
Chess: 4184,
Violent: 4667,
Gore: 4345,
Blood: 5228,
Soundtrack: 7948,
"Great Soundtrack": 1756,
Music: 1621,
"Mouse only": 11123,
"Touch-Friendly": 25085,
"Intentionally Awkward Controls": 14906,
"Voice Control": 27758,
Mod: 5348,
RPGMaker: 5577,
GameMaker: 1649,
"Dungeons & Dragons": 14153,
"Games Workshop": 5310,
TrackIR: 8075,
Hardware: 603297,
"Steam Machine": 348922,
};

View File

@ -83,6 +83,37 @@ const getSteamGames = async () => {
return response.data; return response.data;
}; };
const importDownloadSource = async (url: string) => {
const response = await axios.get<z.infer<typeof downloadSourceSchema>>(url);
const steamGames = await getSteamGames();
await db.transaction("rw", repacksTable, downloadSourcesTable, async () => {
const now = new Date();
const id = await downloadSourcesTable.add({
url,
name: response.data.name,
etag: response.headers["etag"],
status: DownloadSourceStatus.UpToDate,
downloadCount: response.data.downloads.length,
createdAt: now,
updatedAt: now,
});
const downloadSource = await downloadSourcesTable.get(id);
await addNewDownloads(downloadSource, response.data.downloads, steamGames);
});
};
const deleteDownloadSource = async (id: number) => {
await db.transaction("rw", repacksTable, downloadSourcesTable, async () => {
await repacksTable.where({ downloadSourceId: id }).delete();
await downloadSourcesTable.where({ id }).delete();
});
};
self.onmessage = async (event: MessageEvent<Payload>) => { self.onmessage = async (event: MessageEvent<Payload>) => {
const [type, data] = event.data; const [type, data] = event.data;
@ -102,10 +133,7 @@ self.onmessage = async (event: MessageEvent<Payload>) => {
} }
if (type === "DELETE_DOWNLOAD_SOURCE") { if (type === "DELETE_DOWNLOAD_SOURCE") {
await db.transaction("rw", repacksTable, downloadSourcesTable, async () => { await deleteDownloadSource(data);
await repacksTable.where({ downloadSourceId: data }).delete();
await downloadSourcesTable.where({ id: data }).delete();
});
const channel = new BroadcastChannel(`download_sources:delete:${data}`); const channel = new BroadcastChannel(`download_sources:delete:${data}`);
@ -113,32 +141,7 @@ self.onmessage = async (event: MessageEvent<Payload>) => {
} }
if (type === "IMPORT_DOWNLOAD_SOURCE") { if (type === "IMPORT_DOWNLOAD_SOURCE") {
const response = await importDownloadSource(data);
await axios.get<z.infer<typeof downloadSourceSchema>>(data);
const steamGames = await getSteamGames();
await db.transaction("rw", repacksTable, downloadSourcesTable, async () => {
const now = new Date();
const id = await downloadSourcesTable.add({
url: data,
name: response.data.name,
etag: response.headers["etag"],
status: DownloadSourceStatus.UpToDate,
downloadCount: response.data.downloads.length,
createdAt: now,
updatedAt: now,
});
const downloadSource = await downloadSourcesTable.get(id);
await addNewDownloads(
downloadSource,
response.data.downloads,
steamGames
);
});
const channel = new BroadcastChannel(`download_sources:import:${data}`); const channel = new BroadcastChannel(`download_sources:import:${data}`);
channel.postMessage(true); channel.postMessage(true);
@ -153,6 +156,12 @@ self.onmessage = async (event: MessageEvent<Payload>) => {
const existingRepacks = await repacksTable.toArray(); const existingRepacks = await repacksTable.toArray();
for (const downloadSource of downloadSources) { for (const downloadSource of downloadSources) {
if (!downloadSource.fingerprint) {
await deleteDownloadSource(downloadSource.id);
await importDownloadSource(downloadSource.url);
continue;
}
const headers = new AxiosHeaders(); const headers = new AxiosHeaders();
if (downloadSource.etag) { if (downloadSource.etag) {