mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-01-23 05:24:55 +03:00
Merge pull request #1311 from hydralauncher/feat/achievements-points
feat: achievements points
This commit is contained in:
commit
dfb50e9a06
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hydralauncher",
|
||||
"version": "3.0.8",
|
||||
"version": "3.1.0",
|
||||
"description": "Hydra",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "Los Broxas",
|
||||
|
@ -34,7 +34,7 @@ class HttpDownloader:
|
||||
download = self.aria2.get_download(self.download.gid)
|
||||
|
||||
response = {
|
||||
'folderName': str(download.dir) + "/" + download.name,
|
||||
'folderName': download.name,
|
||||
'fileSize': download.total_length,
|
||||
'progress': download.completed_length / download.total_length if download.total_length else 0,
|
||||
'downloadSpeed': download.download_speed,
|
||||
|
@ -124,8 +124,6 @@ def action():
|
||||
action = data.get('action')
|
||||
game_id = data.get('game_id')
|
||||
|
||||
print(data)
|
||||
|
||||
if action == 'start':
|
||||
url = data.get('url')
|
||||
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 18 KiB |
@ -1,6 +1,7 @@
|
||||
import { HydraApi } from "@main/services";
|
||||
import { registerEvent } from "../register-event";
|
||||
import type { GameArtifact, GameShop } from "@types";
|
||||
import { SubscriptionRequiredError } from "@shared";
|
||||
|
||||
const getGameArtifacts = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
@ -13,8 +14,16 @@ const getGameArtifacts = async (
|
||||
});
|
||||
|
||||
return HydraApi.get<GameArtifact[]>(
|
||||
`/profile/games/artifacts?${params.toString()}`
|
||||
);
|
||||
`/profile/games/artifacts?${params.toString()}`,
|
||||
{},
|
||||
{ needsSubscription: true }
|
||||
).catch((err) => {
|
||||
if (err instanceof SubscriptionRequiredError) {
|
||||
return [];
|
||||
}
|
||||
|
||||
throw err;
|
||||
});
|
||||
};
|
||||
|
||||
registerEvent("getGameArtifacts", getGameArtifacts);
|
||||
|
@ -9,7 +9,6 @@ import { RealDebridClient } from "./services/download/real-debrid";
|
||||
import { HydraApi } from "./services/hydra-api";
|
||||
import { uploadGamesBatch } from "./services/library-sync";
|
||||
import { Aria2 } from "./services/aria2";
|
||||
import { PythonRPC } from "./services/python-rpc";
|
||||
|
||||
const loadState = async (userPreferences: UserPreferences | null) => {
|
||||
import("./events");
|
||||
@ -43,11 +42,7 @@ const loadState = async (userPreferences: UserPreferences | null) => {
|
||||
},
|
||||
});
|
||||
|
||||
if (nextQueueItem?.game.status === "active") {
|
||||
DownloadManager.startRPC(nextQueueItem.game, seedList);
|
||||
} else {
|
||||
PythonRPC.spawn();
|
||||
}
|
||||
await DownloadManager.startRPC(nextQueueItem?.game, seedList);
|
||||
|
||||
startMainLoop();
|
||||
};
|
||||
|
@ -24,23 +24,19 @@ import { logger } from "../logger";
|
||||
export class DownloadManager {
|
||||
private static downloadingGameId: number | null = null;
|
||||
|
||||
public static startRPC(game: Game, initialSeeding?: Game[]) {
|
||||
if (game && game.status === "active") {
|
||||
PythonRPC.spawn(
|
||||
{
|
||||
game_id: game.id,
|
||||
url: game.uri!,
|
||||
save_path: game.downloadPath!,
|
||||
},
|
||||
initialSeeding?.map((game) => ({
|
||||
game_id: game.id,
|
||||
url: game.uri!,
|
||||
save_path: game.downloadPath!,
|
||||
}))
|
||||
);
|
||||
public static async startRPC(game?: Game, initialSeeding?: Game[]) {
|
||||
PythonRPC.spawn(
|
||||
game?.status === "active"
|
||||
? await this.getDownloadPayload(game).catch(() => undefined)
|
||||
: undefined,
|
||||
initialSeeding?.map((game) => ({
|
||||
game_id: game.id,
|
||||
url: game.uri!,
|
||||
save_path: game.downloadPath!,
|
||||
}))
|
||||
);
|
||||
|
||||
this.downloadingGameId = game.id;
|
||||
}
|
||||
this.downloadingGameId = game?.id ?? null;
|
||||
}
|
||||
|
||||
private static async getDownloadStatus() {
|
||||
@ -226,7 +222,9 @@ export class DownloadManager {
|
||||
|
||||
WindowManager.mainWindow?.setProgressBar(-1);
|
||||
|
||||
this.downloadingGameId = null;
|
||||
if (gameId === this.downloadingGameId) {
|
||||
this.downloadingGameId = null;
|
||||
}
|
||||
}
|
||||
|
||||
static async resumeSeeding(game: Game) {
|
||||
@ -245,7 +243,7 @@ export class DownloadManager {
|
||||
});
|
||||
}
|
||||
|
||||
static async startDownload(game: Game) {
|
||||
private static async getDownloadPayload(game: Game) {
|
||||
switch (game.downloader) {
|
||||
case Downloader.Gofile: {
|
||||
const id = game!.uri!.split("/").pop();
|
||||
@ -253,56 +251,58 @@ export class DownloadManager {
|
||||
const token = await GofileApi.authorize();
|
||||
const downloadLink = await GofileApi.getDownloadLink(id!);
|
||||
|
||||
await PythonRPC.rpc.post("/action", {
|
||||
return {
|
||||
action: "start",
|
||||
game_id: game.id,
|
||||
url: downloadLink,
|
||||
save_path: game.downloadPath,
|
||||
save_path: game.downloadPath!,
|
||||
header: `Cookie: accountToken=${token}`,
|
||||
});
|
||||
break;
|
||||
};
|
||||
}
|
||||
case Downloader.PixelDrain: {
|
||||
const id = game!.uri!.split("/").pop();
|
||||
|
||||
await PythonRPC.rpc.post("/action", {
|
||||
return {
|
||||
action: "start",
|
||||
game_id: game.id,
|
||||
url: `https://pixeldrain.com/api/file/${id}?download`,
|
||||
save_path: game.downloadPath,
|
||||
});
|
||||
break;
|
||||
save_path: game.downloadPath!,
|
||||
};
|
||||
}
|
||||
case Downloader.Qiwi: {
|
||||
const downloadUrl = await QiwiApi.getDownloadUrl(game.uri!);
|
||||
|
||||
await PythonRPC.rpc.post("/action", {
|
||||
return {
|
||||
action: "start",
|
||||
game_id: game.id,
|
||||
url: downloadUrl,
|
||||
save_path: game.downloadPath,
|
||||
});
|
||||
break;
|
||||
save_path: game.downloadPath!,
|
||||
};
|
||||
}
|
||||
case Downloader.Torrent:
|
||||
await PythonRPC.rpc.post("/action", {
|
||||
return {
|
||||
action: "start",
|
||||
game_id: game.id,
|
||||
url: game.uri,
|
||||
save_path: game.downloadPath,
|
||||
});
|
||||
break;
|
||||
url: game.uri!,
|
||||
save_path: game.downloadPath!,
|
||||
};
|
||||
case Downloader.RealDebrid: {
|
||||
const downloadUrl = await RealDebridClient.getDownloadUrl(game.uri!);
|
||||
|
||||
await PythonRPC.rpc.post("/action", {
|
||||
return {
|
||||
action: "start",
|
||||
game_id: game.id,
|
||||
url: downloadUrl,
|
||||
save_path: game.downloadPath,
|
||||
});
|
||||
url: downloadUrl!,
|
||||
save_path: game.downloadPath!,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static async startDownload(game: Game) {
|
||||
const payload = await this.getDownloadPayload(game);
|
||||
|
||||
await PythonRPC.rpc.post("/action", payload);
|
||||
|
||||
this.downloadingGameId = game.id;
|
||||
}
|
||||
|
@ -18,8 +18,12 @@ export function AchievementList({ achievements }: AchievementListProps) {
|
||||
|
||||
return (
|
||||
<ul className={styles.list}>
|
||||
{achievements.map((achievement, index) => (
|
||||
<li key={index} className={styles.listItem} style={{ display: "flex" }}>
|
||||
{achievements.map((achievement) => (
|
||||
<li
|
||||
key={achievement.name}
|
||||
className={styles.listItem}
|
||||
style={{ display: "flex" }}
|
||||
>
|
||||
<img
|
||||
className={styles.listItemImage({
|
||||
unlocked: achievement.unlocked,
|
||||
@ -72,7 +76,7 @@ export function AchievementList({ achievements }: AchievementListProps) {
|
||||
<p style={{ fontSize: "1.1em" }}>???</p>
|
||||
</button>
|
||||
)}
|
||||
{achievement.unlockTime && (
|
||||
{achievement.unlockTime != null && (
|
||||
<div
|
||||
title={t("unlocked_at", {
|
||||
date: formatDateTime(achievement.unlockTime),
|
||||
|
@ -154,7 +154,7 @@ export function Sidebar() {
|
||||
<div>
|
||||
<p>{achievement.displayName}</p>
|
||||
<small>
|
||||
{achievement.unlockTime &&
|
||||
{achievement.unlockTime != null &&
|
||||
formatDateTime(achievement.unlockTime)}
|
||||
</small>
|
||||
</div>
|
||||
@ -203,7 +203,7 @@ export function Sidebar() {
|
||||
<div>
|
||||
<p>{achievement.displayName}</p>
|
||||
<small>
|
||||
{achievement.unlockTime &&
|
||||
{achievement.unlockTime != null &&
|
||||
formatDateTime(achievement.unlockTime)}
|
||||
</small>
|
||||
</div>
|
||||
|
@ -13,8 +13,7 @@ import { settingsContext } from "@renderer/context";
|
||||
import { downloadSourcesTable } from "@renderer/dexie";
|
||||
import { downloadSourcesWorker } from "@renderer/workers";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { clearFilters } from "@renderer/features";
|
||||
import { setFilters } from "@renderer/features";
|
||||
import { setFilters, clearFilters } from "@renderer/features";
|
||||
|
||||
export function SettingsDownloadSources() {
|
||||
const [showAddDownloadSourceModal, setShowAddDownloadSourceModal] =
|
||||
|
@ -1,79 +0,0 @@
|
||||
import { SPACING_UNIT, vars } from "../../../theme.css";
|
||||
import { style } from "@vanilla-extract/css";
|
||||
|
||||
export const friendListDisplayName = style({
|
||||
fontWeight: "bold",
|
||||
fontSize: vars.size.body,
|
||||
textAlign: "left",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
whiteSpace: "nowrap",
|
||||
});
|
||||
|
||||
export const friendListContainer = style({
|
||||
display: "flex",
|
||||
gap: `${SPACING_UNIT * 3}px`,
|
||||
alignItems: "center",
|
||||
borderRadius: "4px",
|
||||
border: `solid 1px ${vars.color.border}`,
|
||||
width: "100%",
|
||||
height: "54px",
|
||||
minHeight: "54px",
|
||||
transition: "all ease 0.2s",
|
||||
position: "relative",
|
||||
":hover": {
|
||||
backgroundColor: "rgba(255, 255, 255, 0.15)",
|
||||
},
|
||||
});
|
||||
|
||||
export const friendListButton = style({
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
position: "absolute",
|
||||
cursor: "pointer",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
flexDirection: "row",
|
||||
color: vars.color.body,
|
||||
gap: `${SPACING_UNIT + SPACING_UNIT / 2}px`,
|
||||
padding: `0 ${SPACING_UNIT}px`,
|
||||
});
|
||||
|
||||
export const friendRequestItem = style({
|
||||
color: vars.color.body,
|
||||
":hover": {
|
||||
backgroundColor: "rgba(255, 255, 255, 0.15)",
|
||||
},
|
||||
});
|
||||
|
||||
export const acceptRequestButton = style({
|
||||
cursor: "pointer",
|
||||
color: vars.color.body,
|
||||
width: "28px",
|
||||
height: "28px",
|
||||
":hover": {
|
||||
color: vars.color.success,
|
||||
},
|
||||
});
|
||||
|
||||
export const cancelRequestButton = style({
|
||||
cursor: "pointer",
|
||||
color: vars.color.body,
|
||||
width: "28px",
|
||||
height: "28px",
|
||||
":hover": {
|
||||
color: vars.color.danger,
|
||||
},
|
||||
});
|
||||
|
||||
export const friendCodeButton = style({
|
||||
color: vars.color.body,
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
gap: `${SPACING_UNIT / 2}px`,
|
||||
alignItems: "center",
|
||||
transition: "all ease 0.2s",
|
||||
":hover": {
|
||||
color: vars.color.muted,
|
||||
},
|
||||
});
|
@ -13,7 +13,7 @@ export class UserNotLoggedInError extends Error {
|
||||
export class SubscriptionRequiredError extends Error {
|
||||
constructor() {
|
||||
super("user does not have hydra cloud subscription");
|
||||
this.name = "UserWithoutCloudSubscriptionError";
|
||||
this.name = "SubscriptionRequiredError";
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user