mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
Merge branch 'feature/add-download-sources' into feature/game-options-modal
This commit is contained in:
commit
87eaf021b4
19 changed files with 208 additions and 96 deletions
|
@ -103,7 +103,7 @@ export function Header({ onSearch, onClear, search }: HeaderProps) {
|
|||
isWindows: window.electron.platform === "win32",
|
||||
})}
|
||||
>
|
||||
<div className={styles.section}>
|
||||
<section className={styles.section}>
|
||||
<button
|
||||
type="button"
|
||||
className={styles.backButton({
|
||||
|
@ -122,7 +122,7 @@ export function Header({ onSearch, onClear, search }: HeaderProps) {
|
|||
>
|
||||
{title}
|
||||
</h3>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section className={styles.section}>
|
||||
<div className={styles.search({ focused: isFocused })}>
|
||||
|
|
1
src/renderer/src/declaration.d.ts
vendored
1
src/renderer/src/declaration.d.ts
vendored
|
@ -88,6 +88,7 @@ declare global {
|
|||
) => Promise<{ name: string; downloadCount: number }>;
|
||||
addDownloadSource: (url: string) => Promise<DownloadSource>;
|
||||
removeDownloadSource: (id: number) => Promise<void>;
|
||||
syncDownloadSources: () => Promise<void>;
|
||||
|
||||
/* Hardware */
|
||||
getDiskFreeSpace: (path: string) => Promise<DiskSpace>;
|
||||
|
|
|
@ -47,21 +47,20 @@ export function Downloads() {
|
|||
complete: [],
|
||||
};
|
||||
|
||||
const result = library
|
||||
.filter((game) => {
|
||||
return game.downloadPath;
|
||||
})
|
||||
.reduce((prev, next) => {
|
||||
if (lastPacket?.game.id === next.id) {
|
||||
return { ...prev, downloading: [...prev.downloading, next] };
|
||||
}
|
||||
const result = library.reduce((prev, next) => {
|
||||
/* Game has been manually added to the library */
|
||||
if (!next.status) return prev;
|
||||
|
||||
if (next.downloadQueue || next.status === "paused") {
|
||||
return { ...prev, queued: [...prev.queued, next] };
|
||||
}
|
||||
/* Is downloading */
|
||||
if (lastPacket?.game.id === next.id)
|
||||
return { ...prev, downloading: [...prev.downloading, next] };
|
||||
|
||||
return { ...prev, complete: [...prev.complete, next] };
|
||||
}, initialValue);
|
||||
/* Is either queued or paused */
|
||||
if (next.downloadQueue || next.status === "paused")
|
||||
return { ...prev, queued: [...prev.queued, next] };
|
||||
|
||||
return { ...prev, complete: [...prev.complete, next] };
|
||||
}, initialValue);
|
||||
|
||||
const queued = orderBy(
|
||||
result.queued,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { style } from "@vanilla-extract/css";
|
||||
import { SPACING_UNIT, vars } from "../../theme.css";
|
||||
import { recipe } from "@vanilla-extract/recipes";
|
||||
|
||||
export const downloadSourceField = style({
|
||||
display: "flex",
|
||||
|
@ -14,14 +15,24 @@ export const downloadSources = style({
|
|||
flexDirection: "column",
|
||||
});
|
||||
|
||||
export const downloadSourceItem = style({
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
backgroundColor: vars.color.darkBackground,
|
||||
borderRadius: "8px",
|
||||
padding: `${SPACING_UNIT * 2}px`,
|
||||
gap: `${SPACING_UNIT}px`,
|
||||
border: `solid 1px ${vars.color.border}`,
|
||||
export const downloadSourceItem = recipe({
|
||||
base: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
backgroundColor: vars.color.darkBackground,
|
||||
borderRadius: "8px",
|
||||
padding: `${SPACING_UNIT * 2}px`,
|
||||
gap: `${SPACING_UNIT}px`,
|
||||
border: `solid 1px ${vars.color.border}`,
|
||||
transition: "all ease 0.2s",
|
||||
},
|
||||
variants: {
|
||||
isSyncing: {
|
||||
true: {
|
||||
opacity: vars.opacity.disabled,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const downloadSourceItemHeader = style({
|
||||
|
@ -36,3 +47,10 @@ export const downloadSourcesHeader = style({
|
|||
justifyContent: "space-between",
|
||||
alignItems: "center",
|
||||
});
|
||||
|
||||
export const separator = style({
|
||||
height: "100%",
|
||||
width: "1px",
|
||||
backgroundColor: vars.color.border,
|
||||
margin: `${SPACING_UNIT}px 0`,
|
||||
});
|
||||
|
|
|
@ -9,11 +9,14 @@ import { NoEntryIcon, PlusCircleIcon, SyncIcon } from "@primer/octicons-react";
|
|||
import { AddDownloadSourceModal } from "./add-download-source-modal";
|
||||
import { useToast } from "@renderer/hooks";
|
||||
import { DownloadSourceStatus } from "@shared";
|
||||
import { SPACING_UNIT } from "@renderer/theme.css";
|
||||
|
||||
export function SettingsDownloadSources() {
|
||||
const [showAddDownloadSourceModal, setShowAddDownloadSourceModal] =
|
||||
useState(false);
|
||||
const [downloadSources, setDownloadSources] = useState<DownloadSource[]>([]);
|
||||
const [isSyncingDownloadSources, setIsSyncingDownloadSources] =
|
||||
useState(false);
|
||||
|
||||
const { t } = useTranslation("settings");
|
||||
|
||||
|
@ -41,6 +44,20 @@ export function SettingsDownloadSources() {
|
|||
showSuccessToast(t("added_download_source"));
|
||||
};
|
||||
|
||||
const syncDownloadSources = async () => {
|
||||
setIsSyncingDownloadSources(true);
|
||||
|
||||
window.electron
|
||||
.syncDownloadSources()
|
||||
.then(() => {
|
||||
showSuccessToast(t("download_sources_synced"));
|
||||
getDownloadSources();
|
||||
})
|
||||
.finally(() => {
|
||||
setIsSyncingDownloadSources(false);
|
||||
});
|
||||
};
|
||||
|
||||
const statusTitle = {
|
||||
[DownloadSourceStatus.UpToDate]: t("download_source_up_to_date"),
|
||||
[DownloadSourceStatus.Errored]: t("download_source_errored"),
|
||||
|
@ -62,25 +79,31 @@ export function SettingsDownloadSources() {
|
|||
<Button
|
||||
type="button"
|
||||
theme="outline"
|
||||
onClick={() => setShowAddDownloadSourceModal(true)}
|
||||
disabled={!downloadSources.length || isSyncingDownloadSources}
|
||||
onClick={syncDownloadSources}
|
||||
>
|
||||
<PlusCircleIcon />
|
||||
{t("add_download_source")}
|
||||
<SyncIcon />
|
||||
{t("sync_download_sources")}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="button"
|
||||
theme="outline"
|
||||
disabled={!downloadSources.length}
|
||||
onClick={() => setShowAddDownloadSourceModal(true)}
|
||||
>
|
||||
<SyncIcon />
|
||||
{t("resync_download_sources")}
|
||||
<PlusCircleIcon />
|
||||
{t("add_download_source")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<ul className={styles.downloadSources}>
|
||||
{downloadSources.map((downloadSource) => (
|
||||
<li key={downloadSource.id} className={styles.downloadSourceItem}>
|
||||
<li
|
||||
key={downloadSource.id}
|
||||
className={styles.downloadSourceItem({
|
||||
isSyncing: isSyncingDownloadSources,
|
||||
})}
|
||||
>
|
||||
<div className={styles.downloadSourceItemHeader}>
|
||||
<h2>{downloadSource.name}</h2>
|
||||
|
||||
|
@ -88,12 +111,30 @@ export function SettingsDownloadSources() {
|
|||
<Badge>{statusTitle[downloadSource.status]}</Badge>
|
||||
</div>
|
||||
|
||||
<small>
|
||||
{t("download_options", {
|
||||
count: downloadSource.repackCount,
|
||||
countFormatted: downloadSource.repackCount.toLocaleString(),
|
||||
})}
|
||||
</small>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
gap: `${SPACING_UNIT}px`,
|
||||
}}
|
||||
>
|
||||
<small>
|
||||
{t("download_count", {
|
||||
count: downloadSource.downloadCount,
|
||||
countFormatted:
|
||||
downloadSource.downloadCount.toLocaleString(),
|
||||
})}
|
||||
</small>
|
||||
|
||||
<div className={styles.separator} />
|
||||
|
||||
<small>
|
||||
{t("download_options", {
|
||||
count: downloadSource.repackCount,
|
||||
countFormatted: downloadSource.repackCount.toLocaleString(),
|
||||
})}
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.downloadSourceField}>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue