Skip to content

Commit

Permalink
feat: adding accuracy as text instead of colours
Browse files Browse the repository at this point in the history
  • Loading branch information
thegrannychaseroperation committed Apr 14, 2024
1 parent 05a31cf commit c0274ee
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 82 deletions.
1 change: 0 additions & 1 deletion .prettierrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@ module.exports = {
semi: true,
trailingComma: "all",
singleQuote: false,
tabWidth: 2,
};
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Hydra

<a href="https://discord.gg/hydralauncher" target="_blank">![Discord](https://img.shields.io/discord/1220692017311645737?style=flat&logo=discord&label=Hydra&labelColor=%231c1c1c)</a>
![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/hydralauncher/hydra/build.yml)
![GitHub package.json version](https://img.shields.io/github/package-json/v/hydralauncher/hydra)

Hydra is a game launcher with its own embedded bittorrent client and a self-managed repack scraper.
The launcher is written in TypeScript (Electron) and Python, which handles the torrenting system by using [libtorrent](https://www.libtorrent.org/).
Expand Down
7 changes: 2 additions & 5 deletions src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,9 @@
"publisher": "Published by {{publisher}}",
"copy_link_to_clipboard": "Copy link",
"copied_link_to_clipboard": "Link copied",
"main_story": "Main story",
"main_plus_sides": "Main story + sides",
"completionist": "Completionist",
"all_styles": "All styles",
"hours": "hours",
"minutes": "minutes"
"minutes": "minutes",
"accuracy": "{{accuracy}}% accuracy"
},
"activation": {
"title": "Activate Hydra",
Expand Down
7 changes: 2 additions & 5 deletions src/locales/es/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,9 @@
"publisher": "Publicado por {{publisher}}",
"copy_link_to_clipboard": "Copiar enlace",
"copied_link_to_clipboard": "Enlace copiado",
"main_story": "Historia principal",
"main_plus_sides": "Historia principal + extras",
"completionist": "Completista",
"all_styles": "Todo",
"hours": "horas",
"minutes": "minutos"
"minutes": "minutos",
"accuracy": "{{accuracy}}% precisión"
},
"activation": {
"title": "Activar Hydra",
Expand Down
7 changes: 2 additions & 5 deletions src/locales/pt/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,9 @@
"publisher": "Publicado por {{publisher}}",
"copy_link_to_clipboard": "Copiar link",
"copied_link_to_clipboard": "Link copiado",
"main_story": "História principal",
"main_plus_sides": "Historia principal + extras",
"completionist": "Completista",
"all_styles": "Tudo",
"hours": "horas",
"minutes": "minutos"
"minutes": "minutos",
"accuracy": "{{accuracy}}% de precisão"
},
"activation": {
"title": "Ativação",
Expand Down
23 changes: 9 additions & 14 deletions src/main/services/how-long-to-beat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { formatName } from "@main/helpers";
import axios from "axios";
import { JSDOM } from "jsdom";
import { requestWebPage } from "./repack-tracker/helpers";
import { HowLongToBeatCategory } from "@types";

export interface HowLongToBeatResult {
game_id: number;
Expand All @@ -27,23 +28,15 @@ export const searchHowLongToBeat = async (gameName: string) => {
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",
Referer: "https://howlongtobeat.com/",
},
}
},
);

return response.data as HowLongToBeatSearchResponse;
};

export const classNameColor = {
time_40: "#ff3a3a",
time_50: "#cc3b51",
time_60: "#824985",
time_70: "#5650a1",
time_80: "#485cab",
time_90: "#3a6db5",
time_100: "#287fc2",
};

export const getHowLongToBeatGame = async (id: string) => {
export const getHowLongToBeatGame = async (
id: string,
): Promise<HowLongToBeatCategory[]> => {
const response = await requestWebPage(`https://howlongtobeat.com/game/${id}`);

const { window } = new JSDOM(response);
Expand All @@ -54,12 +47,14 @@ export const getHowLongToBeatGame = async (id: string) => {

return $lis.map(($li) => {
const title = $li.querySelector("h4").textContent;
const [, time] = Array.from(($li as HTMLElement).classList);
const [, accuracyClassName] = Array.from(($li as HTMLElement).classList);

const accuracy = accuracyClassName.split("time_").at(1);

return {
title,
duration: $li.querySelector("h5").textContent,
color: classNameColor[time as keyof typeof classNameColor],
accuracy,
};
});
};
18 changes: 12 additions & 6 deletions src/renderer/pages/game-details/game-details.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,19 +139,19 @@ export const descriptionHeaderInfo = style({
});

export const howLongToBeatCategoriesList = style({
margin: 0,
padding: 16,
margin: "0",
padding: "16px",
display: "flex",
flexDirection: "column",
gap: 16,
gap: "16px",
});

export const howLongToBeatCategory = style({
display: "flex",
flexDirection: "column",
gap: 4,
gap: "4px",
backgroundColor: vars.color.background,
borderRadius: 8,
borderRadius: "8px",
padding: `8px 16px`,
border: `solid 1px ${vars.color.borderColor}`,
});
Expand All @@ -161,13 +161,19 @@ export const howLongToBeatCategoryLabel = style({
color: "#DADBE1",
});

export const howLongToBeatCategorySkeleton = style({
border: `solid 1px ${vars.color.borderColor}`,
borderRadius: "8px",
height: "76px",
});

globalStyle(".bb_tag", {
marginTop: `${SPACING_UNIT * 2}px`,
marginBottom: `${SPACING_UNIT * 2}px`,
});

globalStyle(`${description} img`, {
borderRadius: 5,
borderRadius: "5px",
marginTop: `${SPACING_UNIT}px`,
marginBottom: `${SPACING_UNIT}px`,
marginLeft: "auto",
Expand Down
22 changes: 13 additions & 9 deletions src/renderer/pages/game-details/game-details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ export function GameDetails() {
const [color, setColor] = useState("");
const [clipboardLock, setClipboardLock] = useState(false);
const [gameDetails, setGameDetails] = useState<ShopDetails | null>(null);
const [howLongToBeat, setHowLongToBeat] = useState<
HowLongToBeatCategory[] | null
>(null);
const [howLongToBeat, setHowLongToBeat] = useState<{
isLoading: boolean;
data: HowLongToBeatCategory[] | null;
}>({ isLoading: true, data: null });

const [game, setGame] = useState<Game | null>(null);
const [activeRequirement, setActiveRequirement] =
Expand Down Expand Up @@ -81,15 +82,15 @@ export function GameDetails() {
window.electron
.getHowLongToBeat(objectID, "steam", result.name)
.then((data) => {
setHowLongToBeat(data);
setHowLongToBeat({ isLoading: false, data });
});

setGameDetails(result);
dispatch(setHeaderTitle(result.name));
});

getGame();
setHowLongToBeat(null);
setHowLongToBeat({ isLoading: true, data: null });
setClipboardLock(false);
}, [getGame, dispatch, navigate, objectID, i18n.language]);

Expand All @@ -103,12 +104,12 @@ export function GameDetails() {
shop,
encodeURIComponent(gameDetails?.name),
i18n.language,
])
]),
),
});

navigator.clipboard.writeText(
OPEN_HYDRA_URL + `/?${searchParams.toString()}`
OPEN_HYDRA_URL + `/?${searchParams.toString()}`,
);

const zero = performance.now();
Expand All @@ -134,7 +135,7 @@ export function GameDetails() {
repackId,
gameDetails.objectID,
gameDetails.name,
shop as GameShop
shop as GameShop,
).then(() => {
getGame();
setShowRepacksModal(false);
Expand Down Expand Up @@ -217,7 +218,10 @@ export function GameDetails() {
</div>

<div className={styles.contentSidebar}>
<HowLongToBeatSection howLongToBeatData={howLongToBeat} />
<HowLongToBeatSection
howLongToBeatData={howLongToBeat.data}
isLoading={howLongToBeat.isLoading}
/>

<div
className={styles.contentSidebarTitle}
Expand Down
72 changes: 38 additions & 34 deletions src/renderer/pages/game-details/how-long-to-beat-section.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,8 @@
import Skeleton, { SkeletonTheme } from "react-loading-skeleton";
import type { HowLongToBeatCategory } from "@types";
import * as styles from "./game-details.css";
import { vars } from "@renderer/theme.css";
import { useTranslation } from "react-i18next";

const titleTranslation: Record<string, string> = {
"Main Story": "main_story",
"Main + Sides": "main_plus_sides",
Completionist: "completionist",
"All Styles": "all_styles",
};
import { vars } from "@renderer/theme.css";
import * as styles from "./game-details.css";

const durationTranslation: Record<string, string> = {
Hours: "hours",
Expand All @@ -17,49 +11,59 @@ const durationTranslation: Record<string, string> = {

export interface HowLongToBeatSectionProps {
howLongToBeatData: HowLongToBeatCategory[] | null;
isLoading: boolean;
}

export function HowLongToBeatSection({
howLongToBeatData,
isLoading,
}: HowLongToBeatSectionProps) {
const { t } = useTranslation("game_details");

if (!howLongToBeatData) return null;

const getDuration = (duration: string) => {
const [value, unit] = duration.split(" ");
return `${value} ${t(durationTranslation[unit])}`;
};

if (!howLongToBeatData && !isLoading) return null;

return (
<>
<SkeletonTheme baseColor={vars.color.background} highlightColor="#444">
<div className={styles.contentSidebarTitle}>
<h3>HowLongToBeat</h3>
</div>

<ul className={styles.howLongToBeatCategoriesList}>
{howLongToBeatData.map((category) => (
<li
key={category.title}
className={styles.howLongToBeatCategory}
style={{ backgroundColor: category.color ?? vars.color.background }}
>
<p
className={styles.howLongToBeatCategoryLabel}
style={{
fontWeight: "bold",
}}
>
{titleTranslation[category.title]
? t(titleTranslation[category.title])
: category.title}
</p>
<p className={styles.howLongToBeatCategoryLabel}>
{getDuration(category.duration)}
</p>
</li>
))}
{howLongToBeatData
? howLongToBeatData.map((category) => (
<li key={category.title} className={styles.howLongToBeatCategory}>
<p
className={styles.howLongToBeatCategoryLabel}
style={{
fontWeight: "bold",
}}
>
{category.title}
</p>

<p className={styles.howLongToBeatCategoryLabel}>
{getDuration(category.duration)}
</p>

{category.accuracy !== "00" && (
<small>
{t("accuracy", { accuracy: category.accuracy })}
</small>
)}
</li>
))
: Array.from({ length: 4 }).map((_, index) => (
<Skeleton
key={index}
className={styles.howLongToBeatCategorySkeleton}
/>
))}
</ul>
</>
</SkeletonTheme>
);
}
4 changes: 2 additions & 2 deletions src/renderer/pages/game-details/repacks-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ export function RepacksModal({
gameDetails.repacks.filter((repack) =>
repack.title
.toLowerCase()
.includes(event.target.value.toLocaleLowerCase())
)
.includes(event.target.value.toLocaleLowerCase()),
),
);
};

Expand Down
2 changes: 1 addition & 1 deletion src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,5 @@ export interface UserPreferences {
export interface HowLongToBeatCategory {
title: string;
duration: string;
color: string;
accuracy: string;
}

0 comments on commit c0274ee

Please sign in to comment.