mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
feat: merge adjustments
This commit is contained in:
parent
3d571edccb
commit
fc003841b0
7 changed files with 10 additions and 230 deletions
|
@ -1,6 +1,5 @@
|
||||||
import { registerEvent } from "../register-event";
|
import { registerEvent } from "../register-event";
|
||||||
import { DownloadManager, HydraApi, gamesPlaytime } from "@main/services";
|
import { DownloadManager, HydraApi, gamesPlaytime } from "@main/services";
|
||||||
import { PythonRPC } from "@main/services/python-rpc";
|
|
||||||
import { db, downloadsSublevel, gamesSublevel, levelKeys } from "@main/level";
|
import { db, downloadsSublevel, gamesSublevel, levelKeys } from "@main/level";
|
||||||
|
|
||||||
const signOut = async (_event: Electron.IpcMainInvokeEvent) => {
|
const signOut = async (_event: Electron.IpcMainInvokeEvent) => {
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
import type { HydraMigration } from "@main/knex-client";
|
|
||||||
import type { Knex } from "knex";
|
|
||||||
|
|
||||||
export const AddTorBoxApiToken: HydraMigration = {
|
|
||||||
name: "AddTorBoxApiToken",
|
|
||||||
up: (knex: Knex) => {
|
|
||||||
return knex.schema.alterTable("user_preferences", (table) => {
|
|
||||||
return table.string("torBoxApiToken").nullable();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
down: async (knex: Knex) => {
|
|
||||||
return knex.schema.alterTable("user_preferences", (table) => {
|
|
||||||
return table.dropColumn("torBoxApiToken");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
|
@ -271,7 +271,7 @@ export class DownloadManager {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case Downloader.PixelDrain: {
|
case Downloader.PixelDrain: {
|
||||||
const id = game.uri!.split("/").pop();
|
const id = download.uri.split("/").pop();
|
||||||
|
|
||||||
const name = await axios
|
const name = await axios
|
||||||
.get(`https://pixeldrain.com/api/file/${id}/info`)
|
.get(`https://pixeldrain.com/api/file/${id}/info`)
|
||||||
|
@ -281,7 +281,7 @@ export class DownloadManager {
|
||||||
action: "start",
|
action: "start",
|
||||||
game_id: downloadId,
|
game_id: downloadId,
|
||||||
url: `https://pixeldrain.com/api/file/${id}?download`,
|
url: `https://pixeldrain.com/api/file/${id}?download`,
|
||||||
save_path: game.downloadPath!,
|
save_path: download.downloadPath,
|
||||||
out: name,
|
out: name,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -326,15 +326,15 @@ export class DownloadManager {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
case Downloader.TorBox: {
|
case Downloader.TorBox: {
|
||||||
const { name, url } = await TorBoxClient.getDownloadInfo(game.uri!);
|
const { name, url } = await TorBoxClient.getDownloadInfo(download.uri);
|
||||||
console.log(url, name);
|
console.log(url, name);
|
||||||
|
|
||||||
if (!url) return;
|
if (!url) return;
|
||||||
return {
|
return {
|
||||||
action: "start",
|
action: "start",
|
||||||
game_id: game.id,
|
game_id: downloadId,
|
||||||
url,
|
url,
|
||||||
save_path: game.downloadPath!,
|
save_path: download.downloadPath,
|
||||||
out: name,
|
out: name,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -285,7 +285,7 @@ const onCloseGame = (game: Game) => {
|
||||||
if (game.remoteId) {
|
if (game.remoteId) {
|
||||||
// create backup
|
// create backup
|
||||||
// todo: check for hydra cloud?
|
// todo: check for hydra cloud?
|
||||||
createBackup(game.objectID, game.shop, "");
|
createBackup(game.objectId, game.shop, "");
|
||||||
|
|
||||||
updateGamePlaytime(
|
updateGamePlaytime(
|
||||||
game,
|
game,
|
||||||
|
|
|
@ -300,7 +300,7 @@ export function DownloadGroup({
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className={styles.downloadCoverContent}>
|
<div className={styles.downloadCoverContent}>
|
||||||
{game.downloader === Downloader.TorBox ? (
|
{game.download?.downloader === Downloader.TorBox ? (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
@ -320,7 +320,9 @@ export function DownloadGroup({
|
||||||
<span style={{ fontSize: 10 }}>TorBox</span>
|
<span style={{ fontSize: 10 }}>TorBox</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<Badge>{DOWNLOADER_NAME[game.downloader]}</Badge>
|
<Badge>
|
||||||
|
{DOWNLOADER_NAME[game.download!.downloader]}
|
||||||
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,186 +0,0 @@
|
||||||
import { useContext, useEffect, useMemo, useState } from "react";
|
|
||||||
import { Trans, useTranslation } from "react-i18next";
|
|
||||||
import { Button, CheckboxField, Link, TextField } from "@renderer/components";
|
|
||||||
import * as styles from "./settings-debrid.css";
|
|
||||||
import { useAppSelector, useToast } from "@renderer/hooks";
|
|
||||||
import { SPACING_UNIT } from "@renderer/theme.css";
|
|
||||||
import { settingsContext } from "@renderer/context";
|
|
||||||
import { DebridServices } from "@types";
|
|
||||||
|
|
||||||
const REAL_DEBRID_API_TOKEN_URL = "https://real-debrid.com/apitoken";
|
|
||||||
const TORBOX_API_TOKEN_URL = "https://torbox.app/settings";
|
|
||||||
|
|
||||||
interface SettingsDebridForm {
|
|
||||||
useRealDebrid: boolean;
|
|
||||||
realDebridApiToken: string | null;
|
|
||||||
useTorBox: boolean;
|
|
||||||
torBoxApiToken: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SettingsDebridProps {
|
|
||||||
service: DebridServices;
|
|
||||||
form: SettingsDebridForm;
|
|
||||||
setForm: (SettingsDebridForm) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function SettingsDebridInput({
|
|
||||||
service,
|
|
||||||
form,
|
|
||||||
setForm,
|
|
||||||
}: SettingsDebridProps) {
|
|
||||||
const userPreferences = useAppSelector(
|
|
||||||
(state) => state.userPreferences.value
|
|
||||||
);
|
|
||||||
|
|
||||||
const { updateUserPreferences } = useContext(settingsContext);
|
|
||||||
|
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
|
||||||
|
|
||||||
const { showSuccessToast, showErrorToast } = useToast();
|
|
||||||
|
|
||||||
const { t } = useTranslation("settings");
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (userPreferences) {
|
|
||||||
setForm({
|
|
||||||
useRealDebrid: Boolean(userPreferences.realDebridApiToken),
|
|
||||||
realDebridApiToken: userPreferences.realDebridApiToken ?? null,
|
|
||||||
useTorBox: Boolean(userPreferences.torBoxApiToken),
|
|
||||||
torBoxApiToken: userPreferences.torBoxApiToken ?? null,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [userPreferences]);
|
|
||||||
|
|
||||||
const handleFormSubmit: React.FormEventHandler<HTMLFormElement> = async (
|
|
||||||
event
|
|
||||||
) => {
|
|
||||||
setIsLoading(true);
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (form.useRealDebrid) {
|
|
||||||
const user = await window.electron.authenticateRealDebrid(
|
|
||||||
form.realDebridApiToken!
|
|
||||||
);
|
|
||||||
|
|
||||||
if (user.type === "free") {
|
|
||||||
showErrorToast(
|
|
||||||
t("real_debrid_free_account_error", { username: user.username })
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
showSuccessToast(
|
|
||||||
t("real_debrid_linked_message", { username: user.username })
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
showSuccessToast(t("changes_saved"));
|
|
||||||
}
|
|
||||||
|
|
||||||
updateUserPreferences({
|
|
||||||
realDebridApiToken: form.useRealDebrid ? form.realDebridApiToken : null,
|
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
showErrorToast(t("real_debrid_invalid_token"));
|
|
||||||
} finally {
|
|
||||||
setIsLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const useDebridService = useMemo(() => {
|
|
||||||
if (service === "RealDebrid") {
|
|
||||||
return form.useRealDebrid;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service === "TorBox") {
|
|
||||||
return form.useTorBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}, [form, service]);
|
|
||||||
|
|
||||||
const debridApiToken = useMemo(() => {
|
|
||||||
if (service === "RealDebrid") {
|
|
||||||
return form.realDebridApiToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service === "TorBox") {
|
|
||||||
return form.torBoxApiToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}, [form, service]);
|
|
||||||
|
|
||||||
const onChangeCheckbox = () => {
|
|
||||||
if (service === "RealDebrid") {
|
|
||||||
setForm((prev) => ({
|
|
||||||
...prev,
|
|
||||||
useRealDebrid: !form.useRealDebrid,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service === "TorBox") {
|
|
||||||
setForm((prev) => ({
|
|
||||||
...prev,
|
|
||||||
useTorBox: !form.useTorBox,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const onChangeInput = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
if (service === "RealDebrid") {
|
|
||||||
setForm((prev) => ({
|
|
||||||
...prev,
|
|
||||||
realDebridApiToken: event.target.value,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (service === "TorBox") {
|
|
||||||
setForm((prev) => ({
|
|
||||||
...prev,
|
|
||||||
torBoxApiToken: event.target.value,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const isButtonDisabled =
|
|
||||||
(form.useRealDebrid && !form.realDebridApiToken) || isLoading;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<form className={styles.form} onSubmit={handleFormSubmit}>
|
|
||||||
<CheckboxField
|
|
||||||
label={t("enable_real_debrid")}
|
|
||||||
checked={useDebridService}
|
|
||||||
onChange={onChangeCheckbox}
|
|
||||||
/>
|
|
||||||
|
|
||||||
{useDebridService && (
|
|
||||||
<TextField
|
|
||||||
label={t("real_debrid_api_token")}
|
|
||||||
value={debridApiToken ?? ""}
|
|
||||||
type="password"
|
|
||||||
onChange={onChangeInput}
|
|
||||||
placeholder="API Token"
|
|
||||||
containerProps={{ style: { marginTop: `${SPACING_UNIT}px` } }}
|
|
||||||
rightContent={
|
|
||||||
<Button
|
|
||||||
type="submit"
|
|
||||||
style={{
|
|
||||||
alignSelf: "flex-end",
|
|
||||||
}}
|
|
||||||
disabled={isButtonDisabled}
|
|
||||||
>
|
|
||||||
{t("save")}
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
hint={
|
|
||||||
<Trans i18nKey="real_debrid_api_token_hint" ns="settings">
|
|
||||||
<Link to={REAL_DEBRID_API_TOKEN_URL} />
|
|
||||||
</Trans>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</form>
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -55,24 +55,6 @@ export interface GameRunning {
|
||||||
sessionDurationInMillis: number;
|
sessionDurationInMillis: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DownloadProgress {
|
|
||||||
downloadSpeed: number;
|
|
||||||
timeRemaining: number;
|
|
||||||
numPeers: number;
|
|
||||||
numSeeds: number;
|
|
||||||
isDownloadingMetadata: boolean;
|
|
||||||
isCheckingFiles: boolean;
|
|
||||||
progress: number;
|
|
||||||
gameId: number;
|
|
||||||
game: LibraryGame;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SeedingStatus {
|
|
||||||
gameId: number;
|
|
||||||
status: GameStatus;
|
|
||||||
uploadSpeed: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface UserPreferences {
|
export interface UserPreferences {
|
||||||
downloadsPath: string | null;
|
downloadsPath: string | null;
|
||||||
language: string;
|
language: string;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue