mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-18 00:33:59 +00:00
Merge pull request #1748 from v1ctorsales/quick-add-to-library-button
feature: Add button to quickly add games to library
This commit is contained in:
@@ -89,6 +89,7 @@
|
||||
"amount_minutes": "{{amount}} minutes",
|
||||
"accuracy": "{{accuracy}}% accuracy",
|
||||
"add_to_library": "Add to library",
|
||||
"already_in_library": "Already in library",
|
||||
"remove_from_library": "Remove from library",
|
||||
"no_downloads": "No downloads available",
|
||||
"play_time": "Played for {{amount}}",
|
||||
|
||||
@@ -76,6 +76,7 @@
|
||||
"amount_minutes": "{{amount}} minutos",
|
||||
"accuracy": "{{accuracy}}% de precisão",
|
||||
"add_to_library": "Adicionar à biblioteca",
|
||||
"already_in_library": "Já está na biblioteca",
|
||||
"remove_from_library": "Remover da biblioteca",
|
||||
"no_downloads": "Nenhum download disponível",
|
||||
"play_time": "Jogou por {{amount}}",
|
||||
|
||||
@@ -16,6 +16,25 @@
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(255, 255, 255, 0.05);
|
||||
|
||||
.game-item__plus-wrapper {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&__plus-wrapper {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&__plus-wrapper--added {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
&__cover {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { Badge } from "@renderer/components";
|
||||
import { buildGameDetailsPath } from "@renderer/helpers";
|
||||
import { useAppSelector, useRepacks } from "@renderer/hooks";
|
||||
import { useMemo } from "react";
|
||||
import { useAppSelector, useRepacks, useLibrary } from "@renderer/hooks";
|
||||
import { useMemo, useState, useEffect } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
import "./game-item.scss";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { CatalogueSearchResult } from "@types";
|
||||
import { QuestionIcon } from "@primer/octicons-react";
|
||||
import { QuestionIcon, PlusIcon, CheckIcon } from "@primer/octicons-react";
|
||||
import cn from "classnames";
|
||||
|
||||
export interface GameItemProps {
|
||||
game: CatalogueSearchResult;
|
||||
@@ -16,7 +17,9 @@ export interface GameItemProps {
|
||||
export function GameItem({ game }: GameItemProps) {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { i18n } = useTranslation();
|
||||
const { i18n, t } = useTranslation("game_details");
|
||||
|
||||
const language = i18n.language.split("-")[0];
|
||||
|
||||
const { steamGenres } = useAppSelector((state) => state.catalogueSearch);
|
||||
|
||||
@@ -24,7 +27,39 @@ export function GameItem({ game }: GameItemProps) {
|
||||
|
||||
const repacks = getRepacksForObjectId(game.objectId);
|
||||
|
||||
const language = i18n.language.split("-")[0];
|
||||
const [isAddingToLibrary, setIsAddingToLibrary] = useState(false);
|
||||
|
||||
const [added, setAdded] = useState(false);
|
||||
|
||||
const { library, updateLibrary } = useLibrary();
|
||||
|
||||
useEffect(() => {
|
||||
const exists = library.some(
|
||||
(libItem) =>
|
||||
libItem.shop === game.shop && libItem.objectId === game.objectId
|
||||
);
|
||||
setAdded(exists);
|
||||
}, [library, game.shop, game.objectId]);
|
||||
|
||||
const addGameToLibrary = async (event: React.MouseEvent | React.KeyboardEvent) => {
|
||||
event.stopPropagation();
|
||||
if (added || isAddingToLibrary) return;
|
||||
|
||||
setIsAddingToLibrary(true);
|
||||
|
||||
try {
|
||||
await window.electron.addGameToLibrary(
|
||||
game.shop,
|
||||
game.objectId,
|
||||
game.title
|
||||
);
|
||||
updateLibrary();
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
} finally {
|
||||
setIsAddingToLibrary(false);
|
||||
}
|
||||
};
|
||||
|
||||
const uniqueRepackers = useMemo(() => {
|
||||
return Array.from(new Set(repacks.map((repack) => repack.repacker)));
|
||||
@@ -85,6 +120,23 @@ export function GameItem({ game }: GameItemProps) {
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={cn("game-item__plus-wrapper", {
|
||||
"game-item__plus-wrapper--added": added,
|
||||
})}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={addGameToLibrary}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
e.preventDefault();
|
||||
addGameToLibrary(e);
|
||||
}
|
||||
}}
|
||||
title={added ? t("already_in_library") : t("add_to_library")}
|
||||
>
|
||||
{added ? <CheckIcon size={16} /> : <PlusIcon size={16} />}
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user