Skip to content

Commit

Permalink
Merge branch 'feature/seed-completed-downloads' of github.com:hydrala…
Browse files Browse the repository at this point in the history
…uncher/hydra into feature/seed-completed-downloads
  • Loading branch information
thegrannychaseroperation committed Nov 28, 2024
2 parents 6259cf4 + f2cc20c commit 2d8b63c
Show file tree
Hide file tree
Showing 12 changed files with 585 additions and 79 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"@hookform/resolvers": "^3.9.0",
"@intercom/messenger-js-sdk": "^0.0.14",
"@primer/octicons-react": "^19.9.0",
"@radix-ui/react-dropdown-menu": "^2.1.2",
"@reduxjs/toolkit": "^2.2.3",
"@vanilla-extract/css": "^1.14.2",
"@vanilla-extract/dynamic": "^2.1.1",
Expand Down
3 changes: 2 additions & 1 deletion src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,8 @@
"checking_files": "Checking files…",
"seeding": "Seeding",
"stop_seeding": "Stop seeding",
"resume_seeding": "Resume seeding"
"resume_seeding": "Resume seeding",
"options": "Manage"
},
"settings": {
"downloads_path": "Downloads path",
Expand Down
3 changes: 2 additions & 1 deletion src/locales/pt-BR/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,8 @@
"checking_files": "Verificando arquivos…",
"seeding": "Semeando",
"stop_seeding": "Parar semeio",
"resume_seeding": "Retomar semeio"
"resume_seeding": "Retomar semeio",
"options": "Gerenciar"
},
"settings": {
"downloads_path": "Diretório dos downloads",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export const AddShouldSeedColumn: HydraMigration = {
name: "AddShouldSeedColumn",
up: (knex: Knex) => {
return knex.schema.alterTable("game", (table) => {
return table.boolean("shouldSeed").notNullable().defaultTo(false);
return table.boolean("shouldSeed").notNullable().defaultTo(true);
});
},

Expand Down
26 changes: 26 additions & 0 deletions src/main/services/download/download-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import type { DownloadProgress } from "@types";
import { GofileApi, QiwiApi } from "../hosters";
import { GenericHttpDownloader } from "./generic-http-downloader";
import { In, Not } from "typeorm";
import path from "path";
import fs from "fs";

export class DownloadManager {
private static currentDownloader: Downloader | null = null;
Expand Down Expand Up @@ -85,6 +87,30 @@ export class DownloadManager {
}

const gameIds = seedStatus.map((status) => status.gameId);

for (const gameId of gameIds) {
const game = await gameRepository.findOne({
where: { id: gameId },
});

if (game) {
const isNotDeleted = fs.existsSync(
path.join(game.downloadPath!, game.folderName!)
);

if (!isNotDeleted) {
await this.pauseSeeding(game.id);

await gameRepository.update(game.id, {
status: "complete",
shouldSeed: false,
});

WindowManager.mainWindow?.webContents.send("on-hard-delete");
}
}
}

const updateList = await gameRepository.find({
where: {
id: In(gameIds),
Expand Down
5 changes: 5 additions & 0 deletions src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ contextBridge.exposeInMainWorld("electron", {
ipcRenderer.on("on-download-progress", listener);
return () => ipcRenderer.removeListener("on-download-progress", listener);
},
onHardDelete: (cb: () => void) => {
const listener = (_event: Electron.IpcRendererEvent) => cb();
ipcRenderer.on("on-hard-delete", listener);
return () => ipcRenderer.removeListener("on-hard-delete", listener);
},
onSeedingStatus: (cb: (value: SeedingStatus[]) => void) => {
const listener = (
_event: Electron.IpcRendererEvent,
Expand Down
8 changes: 8 additions & 0 deletions src/renderer/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,14 @@ export function App() {
};
}, [clearDownload, setLastPacket, updateLibrary]);

useEffect(() => {
const unsubscribe = window.electron.onHardDelete(() => {
updateLibrary();
});

return () => unsubscribe();
}, [updateLibrary]);

useEffect(() => {
const cachedUserDetails = window.localStorage.getItem("userDetails");

Expand Down
68 changes: 68 additions & 0 deletions src/renderer/src/components/dropdown-menu/dropdown-menu.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
@use "../../scss/globals.scss";

.dropdown-menu {
&__content {
background-color: globals.$dark-background-color;
border: 1px solid globals.$border-color;
border-radius: 4px;
min-width: 200px;
flex-direction: column;
align-items: center;
}

&__group {
width: 100%;
padding: 4px;
}

&__title-bar {
width: 100%;
padding: 4px 12px;
font-size: 14px;
font-weight: 500;
color: globals.$muted-color;
}

&__separator {
width: 100%;
height: 1px;
background-color: globals.$border-color;
}

&__item {
width: 100%;
display: flex;
flex-direction: row;
align-items: center;
justify-content: flex-start;
gap: 8px;
border-radius: 4px;
padding: 5px 12px;
cursor: pointer;
transition: background-color 0.1s ease-in-out;
font-size: 14px;
}

&__item--disabled {
cursor: default;
opacity: 0.6;
}

&:not(&__item--disabled) &__item:hover {
background-color: globals.$background-color;
color: globals.$muted-color;
}

&__item:focus {
background-color: globals.$background-color;
outline: none;
}

&__item-icon {
width: 16px;
height: 16px;
display: flex;
align-items: center;
justify-content: center;
}
}
81 changes: 81 additions & 0 deletions src/renderer/src/components/dropdown-menu/dropdown-menu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import "./dropdown-menu.scss";

export interface DropdownMenuItem {
icon?: React.ReactNode;
label: string;
disabled?: boolean;
show?: boolean;
onClick?: () => void;
}

interface DropdownMenuProps {
children: React.ReactNode;
title?: string;
loop?: boolean;
items: DropdownMenuItem[];
sideOffset?: number;
side?: "top" | "bottom" | "left" | "right";
align?: "start" | "center" | "end";
alignOffset?: number;
}

export function DropdownMenu({
children,
title,
items,
sideOffset = 5,
side = "bottom",
loop = true,
align = "center",
alignOffset = 0,
}: DropdownMenuProps) {
return (
<DropdownMenuPrimitive.Root>
<DropdownMenuPrimitive.Trigger asChild>
<button aria-label={title}>{children}</button>
</DropdownMenuPrimitive.Trigger>

<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
sideOffset={sideOffset}
side={side}
loop={loop}
align={align}
alignOffset={alignOffset}
className="dropdown-menu__content"
>
{title && (
<DropdownMenuPrimitive.Group className="dropdown-menu__group">
<div className="dropdown-menu__title-bar">{title}</div>
</DropdownMenuPrimitive.Group>
)}

<DropdownMenuPrimitive.Separator className="dropdown-menu__separator" />

<DropdownMenuPrimitive.Group className="dropdown-menu__group">
{items.map(
(item) =>
item.show !== false && (
<DropdownMenuPrimitive.Item
key={item.label}
aria-label={item.label}
onSelect={item.onClick}
className={`dropdown-menu__item ${item.disabled ? "dropdown-menu__item--disabled" : ""}`}
disabled={item.disabled}
>
{item.icon && (
<div className="dropdown-menu__item-icon">
{item.icon}
</div>
)}
{item.label}
</DropdownMenuPrimitive.Item>
)
)}
</DropdownMenuPrimitive.Group>
</DropdownMenuPrimitive.Content>
</DropdownMenuPrimitive.Portal>
</DropdownMenuPrimitive.Root>
);
}
1 change: 1 addition & 0 deletions src/renderer/src/declaration.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ declare global {
onSeedingStatus: (
cb: (value: SeedingStatus[]) => void
) => () => Electron.IpcRenderer;
onHardDelete: (cb: () => void) => () => Electron.IpcRenderer;

/* Catalogue */
searchGames: (query: string) => Promise<CatalogueEntry[]>;
Expand Down
Loading

0 comments on commit 2d8b63c

Please sign in to comment.