mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
feat: adding icon parser to download notification
This commit is contained in:
parent
6b8ab895e3
commit
4a4a800b07
17 changed files with 343 additions and 146 deletions
|
@ -40,8 +40,6 @@ export function Sidebar() {
|
|||
updateLibrary();
|
||||
}, [lastPacket?.game.id, updateLibrary]);
|
||||
|
||||
console.log(library);
|
||||
|
||||
const isDownloading = library.some(
|
||||
(game) => game.status === "active" && game.progress !== 1
|
||||
);
|
||||
|
|
|
@ -41,12 +41,6 @@ export function useDownload() {
|
|||
return updateLibrary();
|
||||
};
|
||||
|
||||
const cancelDownload = async (gameId: number) => {
|
||||
await window.electron.cancelGameDownload(gameId);
|
||||
dispatch(clearDownload());
|
||||
updateLibrary();
|
||||
};
|
||||
|
||||
const removeGameInstaller = async (gameId: number) => {
|
||||
dispatch(setGameDeleting(gameId));
|
||||
|
||||
|
@ -58,6 +52,14 @@ export function useDownload() {
|
|||
}
|
||||
};
|
||||
|
||||
const cancelDownload = async (gameId: number) => {
|
||||
await window.electron.cancelGameDownload(gameId);
|
||||
dispatch(clearDownload());
|
||||
updateLibrary();
|
||||
|
||||
removeGameInstaller(gameId);
|
||||
};
|
||||
|
||||
const removeGameFromLibrary = (gameId: number) =>
|
||||
window.electron.removeGameFromLibrary(gameId).then(() => {
|
||||
updateLibrary();
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import { SPACING_UNIT, vars } from "../../theme.css";
|
||||
import { style } from "@vanilla-extract/css";
|
||||
import { recipe } from "@vanilla-extract/recipes";
|
||||
|
||||
export const downloadTitleWrapper = style({
|
||||
display: "flex",
|
||||
|
@ -28,6 +27,7 @@ export const downloads = style({
|
|||
flexDirection: "column",
|
||||
margin: "0",
|
||||
padding: "0",
|
||||
marginTop: `${SPACING_UNIT}px`,
|
||||
});
|
||||
|
||||
export const downloadCover = style({
|
||||
|
@ -64,30 +64,18 @@ export const downloadCoverImage = style({
|
|||
zIndex: "-1",
|
||||
});
|
||||
|
||||
export const download = recipe({
|
||||
base: {
|
||||
width: "100%",
|
||||
backgroundColor: vars.color.background,
|
||||
display: "flex",
|
||||
borderRadius: "8px",
|
||||
border: `solid 1px ${vars.color.border}`,
|
||||
overflow: "hidden",
|
||||
boxShadow: "0px 0px 15px 0px #000000",
|
||||
transition: "all ease 0.2s",
|
||||
height: "140px",
|
||||
minHeight: "140px",
|
||||
maxHeight: "140px",
|
||||
},
|
||||
variants: {
|
||||
cancelled: {
|
||||
true: {
|
||||
opacity: vars.opacity.disabled,
|
||||
":hover": {
|
||||
opacity: "1",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
export const download = style({
|
||||
width: "100%",
|
||||
backgroundColor: vars.color.background,
|
||||
display: "flex",
|
||||
borderRadius: "8px",
|
||||
border: `solid 1px ${vars.color.border}`,
|
||||
overflow: "hidden",
|
||||
boxShadow: "0px 0px 15px 0px #000000",
|
||||
transition: "all ease 0.2s",
|
||||
height: "140px",
|
||||
minHeight: "140px",
|
||||
maxHeight: "140px",
|
||||
});
|
||||
|
||||
export const downloadDetails = style({
|
||||
|
|
|
@ -15,6 +15,7 @@ import { useAppSelector, useDownload } from "@renderer/hooks";
|
|||
|
||||
import * as styles from "./download-group.css";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { SPACING_UNIT, vars } from "@renderer/theme.css";
|
||||
|
||||
export interface DownloadGroupProps {
|
||||
library: LibraryGame[];
|
||||
|
@ -42,7 +43,6 @@ export function DownloadGroup({
|
|||
progress,
|
||||
pauseDownload,
|
||||
resumeDownload,
|
||||
removeGameFromLibrary,
|
||||
cancelDownload,
|
||||
isGameDeleting,
|
||||
} = useDownload();
|
||||
|
@ -149,42 +149,20 @@ export function DownloadGroup({
|
|||
);
|
||||
}
|
||||
|
||||
if (game.status === "paused") {
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => resumeDownload(game.id)}
|
||||
theme="outline"
|
||||
disabled={
|
||||
game.downloader === Downloader.RealDebrid &&
|
||||
!userPreferences?.realDebridApiToken
|
||||
}
|
||||
>
|
||||
{t("resume")}
|
||||
</Button>
|
||||
<Button onClick={() => cancelDownload(game.id)} theme="outline">
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button
|
||||
onClick={() => navigate(buildGameDetailsPath(game))}
|
||||
onClick={() => resumeDownload(game.id)}
|
||||
theme="outline"
|
||||
disabled={deleting}
|
||||
disabled={
|
||||
game.downloader === Downloader.RealDebrid &&
|
||||
!userPreferences?.realDebridApiToken
|
||||
}
|
||||
>
|
||||
{t("download_again")}
|
||||
{t("resume")}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => removeGameFromLibrary(game.id)}
|
||||
theme="outline"
|
||||
disabled={deleting}
|
||||
>
|
||||
{t("remove_from_list")}
|
||||
<Button onClick={() => cancelDownload(game.id)} theme="outline">
|
||||
{t("cancel")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
|
@ -194,17 +172,30 @@ export function DownloadGroup({
|
|||
|
||||
return (
|
||||
<div className={styles.downloadGroup}>
|
||||
<h2>{title}</h2>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
gap: `${SPACING_UNIT * 2}px`,
|
||||
}}
|
||||
>
|
||||
<h2>{title}</h2>
|
||||
|
||||
<div
|
||||
style={{
|
||||
flex: 1,
|
||||
backgroundColor: vars.color.border,
|
||||
height: "1px",
|
||||
}}
|
||||
/>
|
||||
<h3 style={{ fontWeight: "400" }}>{library.length}</h3>
|
||||
</div>
|
||||
|
||||
<ul className={styles.downloads}>
|
||||
{library.map((game) => {
|
||||
return (
|
||||
<li
|
||||
key={game.id}
|
||||
className={styles.download({
|
||||
cancelled: game.status === "removed",
|
||||
})}
|
||||
>
|
||||
<li key={game.id} className={styles.download}>
|
||||
<div className={styles.downloadCover}>
|
||||
<div className={styles.downloadCoverBackdrop}>
|
||||
<img
|
||||
|
|
|
@ -13,3 +13,24 @@ export const downloadGroups = style({
|
|||
gap: `${SPACING_UNIT * 3}px`,
|
||||
flexDirection: "column",
|
||||
});
|
||||
|
||||
export const arrowIcon = style({
|
||||
width: "60px",
|
||||
height: "60px",
|
||||
borderRadius: "50%",
|
||||
backgroundColor: "rgba(255, 255, 255, 0.06)",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
marginBottom: `${SPACING_UNIT * 2}px`,
|
||||
});
|
||||
|
||||
export const noDownloads = style({
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
flexDirection: "column",
|
||||
gap: `${SPACING_UNIT}px`,
|
||||
});
|
||||
|
|
|
@ -9,6 +9,7 @@ import { DeleteGameModal } from "./delete-game-modal";
|
|||
import { DownloadGroup } from "./download-group";
|
||||
import { LibraryGame } from "@types";
|
||||
import { orderBy } from "lodash-es";
|
||||
import { ArrowDownIcon } from "@primer/octicons-react";
|
||||
|
||||
export function Downloads() {
|
||||
const { library, updateLibrary } = useLibrary();
|
||||
|
@ -48,8 +49,8 @@ export function Downloads() {
|
|||
};
|
||||
|
||||
const result = library.reduce((prev, next) => {
|
||||
/* Game has been manually added to the library */
|
||||
if (!next.status) return prev;
|
||||
/* Game has been manually added to the library or has been canceled */
|
||||
if (!next.status || next.status === "removed") return prev;
|
||||
|
||||
/* Is downloading */
|
||||
if (lastPacket?.game.id === next.id)
|
||||
|
@ -94,8 +95,12 @@ export function Downloads() {
|
|||
},
|
||||
];
|
||||
|
||||
const hasItemsInLibrary = useMemo(() => {
|
||||
return Object.values(libraryGroup).some((group) => group.length > 0);
|
||||
}, [libraryGroup]);
|
||||
|
||||
return (
|
||||
<section className={styles.downloadsContainer}>
|
||||
<>
|
||||
<BinaryNotFoundModal
|
||||
visible={showBinaryNotFoundModal}
|
||||
onClose={() => setShowBinaryNotFoundModal(false)}
|
||||
|
@ -107,17 +112,31 @@ export function Downloads() {
|
|||
deleteGame={handleDeleteGame}
|
||||
/>
|
||||
|
||||
<div className={styles.downloadGroups}>
|
||||
{downloadGroups.map((group) => (
|
||||
<DownloadGroup
|
||||
key={group.title}
|
||||
title={group.title}
|
||||
library={group.library}
|
||||
openDeleteGameModal={handleOpenDeleteGameModal}
|
||||
openGameInstaller={handleOpenGameInstaller}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
{hasItemsInLibrary ? (
|
||||
<section className={styles.downloadsContainer}>
|
||||
<div className={styles.downloadGroups}>
|
||||
{downloadGroups.map((group) => (
|
||||
<DownloadGroup
|
||||
key={group.title}
|
||||
title={group.title}
|
||||
library={group.library}
|
||||
openDeleteGameModal={handleOpenDeleteGameModal}
|
||||
openGameInstaller={handleOpenGameInstaller}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
) : (
|
||||
<div className={styles.noDownloads}>
|
||||
<div className={styles.arrowIcon}>
|
||||
<ArrowDownIcon size={24} />
|
||||
</div>
|
||||
<h2>{t("no_downloads_title")}</h2>
|
||||
<p style={{ fontFamily: "Fira Sans" }}>
|
||||
{t("no_downloads_description")}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ export const contentSidebar = style({
|
|||
borderLeft: `solid 1px ${vars.color.border};`,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
position: "relative",
|
||||
"@media": {
|
||||
"(min-width: 768px)": {
|
||||
width: "100%",
|
||||
|
@ -87,14 +86,6 @@ export const howLongToBeatCategorySkeleton = style({
|
|||
height: "76px",
|
||||
});
|
||||
|
||||
export const technicalDetailsContainer = style({
|
||||
padding: `0 ${SPACING_UNIT * 2}px`,
|
||||
color: vars.color.body,
|
||||
userSelect: "text",
|
||||
position: "absolute",
|
||||
bottom: `${SPACING_UNIT}px`,
|
||||
});
|
||||
|
||||
globalStyle(`${requirementsDetails} a`, {
|
||||
display: "flex",
|
||||
color: vars.color.body,
|
||||
|
|
|
@ -16,8 +16,7 @@ export function Sidebar() {
|
|||
const [activeRequirement, setActiveRequirement] =
|
||||
useState<keyof SteamAppDetails["pc_requirements"]>("minimum");
|
||||
|
||||
const { gameTitle, shopDetails, shop, objectID } =
|
||||
useContext(gameDetailsContext);
|
||||
const { gameTitle, shopDetails, objectID } = useContext(gameDetailsContext);
|
||||
|
||||
const { t } = useTranslation("game_details");
|
||||
|
||||
|
@ -75,15 +74,6 @@ export function Sidebar() {
|
|||
}),
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className={styles.technicalDetailsContainer}>
|
||||
<p>
|
||||
<small>shop: "{shop}"</small>
|
||||
</p>
|
||||
<p>
|
||||
<small>objectID: "{objectID}"</small>
|
||||
</p>
|
||||
</div>
|
||||
</aside>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -18,5 +18,6 @@ export const [themeClass, vars] = createTheme({
|
|||
},
|
||||
size: {
|
||||
body: "14px",
|
||||
small: "12px",
|
||||
},
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue