mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-10 21:36:17 +00:00
feat: adding ota updates
This commit is contained in:
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.18.0
|
||||
node-version: 20.18.3
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn --frozen-lockfile
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -17,7 +17,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.18.0
|
||||
node-version: 20.18.3
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn --frozen-lockfile
|
||||
|
||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -6,7 +6,7 @@ concurrency:
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: main
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20.18.0
|
||||
node-version: 20.18.3
|
||||
|
||||
- name: Install dependencies
|
||||
run: yarn --frozen-lockfile
|
||||
|
||||
22
package.json
22
package.json
@@ -32,13 +32,13 @@
|
||||
"protoc": "npx protoc --ts_out src/main/generated --proto_path proto proto/*.proto"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron-toolkit/preload": "^3.0.0",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"@fontsource/noto-sans": "^5.1.0",
|
||||
"@hookform/resolvers": "^3.9.1",
|
||||
"@electron-toolkit/preload": "^3.0.2",
|
||||
"@electron-toolkit/utils": "^4.0.0",
|
||||
"@fontsource/noto-sans": "^5.2.10",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@monaco-editor/react": "^4.6.0",
|
||||
"@primer/octicons-react": "^19.9.0",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.16",
|
||||
"@reduxjs/toolkit": "^2.2.3",
|
||||
"@tiptap/extension-bold": "^3.6.2",
|
||||
"@tiptap/extension-italic": "^3.6.2",
|
||||
@@ -47,8 +47,9 @@
|
||||
"@tiptap/react": "^3.6.2",
|
||||
"@tiptap/starter-kit": "^3.6.2",
|
||||
"auto-launch": "^5.0.6",
|
||||
"axios": "^1.7.9",
|
||||
"axios": "^1.12.2",
|
||||
"axios-cookiejar-support": "^5.0.5",
|
||||
"check-disk-space": "^3.4.0",
|
||||
"classic-level": "^2.0.0",
|
||||
"classnames": "^2.5.1",
|
||||
"color": "^4.2.3",
|
||||
@@ -57,8 +58,7 @@
|
||||
"create-desktop-shortcuts": "^1.11.1",
|
||||
"date-fns": "^3.6.0",
|
||||
"dexie": "^4.0.10",
|
||||
"diskusage": "^1.2.0",
|
||||
"electron-log": "^5.2.4",
|
||||
"electron-log": "^5.4.3",
|
||||
"electron-updater": "^6.6.2",
|
||||
"embla-carousel-autoplay": "^8.6.0",
|
||||
"embla-carousel-react": "^8.6.0",
|
||||
@@ -117,7 +117,7 @@
|
||||
"@types/winreg": "^1.2.36",
|
||||
"@types/ws": "^8.18.1",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"electron": "^32.3.3",
|
||||
"electron": "^33.4.11",
|
||||
"electron-builder": "^26.0.12",
|
||||
"electron-vite": "^3.0.0",
|
||||
"eslint": "^8.56.0",
|
||||
@@ -131,8 +131,8 @@
|
||||
"sass-embedded": "^1.80.6",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.3.3",
|
||||
"vite": "^5.0.12",
|
||||
"vite-plugin-svgr": "^4.2.0"
|
||||
"vite": "5.4.20",
|
||||
"vite-plugin-svgr": "^4.5.0"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import disk from "diskusage";
|
||||
|
||||
import { DiskUsage } from "@types";
|
||||
import { registerEvent } from "../register-event";
|
||||
import checkDiskSpace from "check-disk-space";
|
||||
|
||||
const getDiskFreeSpace = async (
|
||||
_event: Electron.IpcMainInvokeEvent,
|
||||
path: string
|
||||
) => disk.check(path);
|
||||
): Promise<DiskUsage> => {
|
||||
const result = await checkDiskSpace(path);
|
||||
return { free: result.free, total: result.size };
|
||||
};
|
||||
|
||||
registerEvent("getDiskFreeSpace", getDiskFreeSpace);
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
clearGamesPlaytime,
|
||||
WindowManager,
|
||||
Lock,
|
||||
Aria2,
|
||||
} from "@main/services";
|
||||
import resources from "@locales";
|
||||
import { PythonRPC } from "./services/python-rpc";
|
||||
@@ -222,6 +223,7 @@ app.on("before-quit", async (e) => {
|
||||
e.preventDefault();
|
||||
/* Disconnects libtorrent */
|
||||
PythonRPC.kill();
|
||||
Aria2.kill();
|
||||
await clearGamesPlaytime();
|
||||
canAppBeClosed = true;
|
||||
app.quit();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import path from "node:path";
|
||||
import cp from "node:child_process";
|
||||
import { app } from "electron";
|
||||
import { logger } from "./logger";
|
||||
|
||||
export class Aria2 {
|
||||
private static process: cp.ChildProcess | null = null;
|
||||
@@ -23,6 +24,9 @@ export class Aria2 {
|
||||
}
|
||||
|
||||
public static kill() {
|
||||
this.process?.kill();
|
||||
if (this.process) {
|
||||
logger.log("Killing aria2 process");
|
||||
this.process.kill();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,11 +79,18 @@ const findGamePathByProcess = async (
|
||||
const executables = gameExecutables[gameId];
|
||||
|
||||
for (const executable of executables) {
|
||||
const pathSet = processMap.get(executable.exe);
|
||||
const executablewithoutExtension = executable.exe.replace(/\.exe$/i, "");
|
||||
|
||||
const pathSet =
|
||||
processMap.get(executable.exe) ??
|
||||
processMap.get(executablewithoutExtension);
|
||||
|
||||
if (pathSet) {
|
||||
for (const path of pathSet) {
|
||||
if (path.toLowerCase().endsWith(executable.name)) {
|
||||
if (
|
||||
path.toLowerCase().endsWith(executable.name) ||
|
||||
path.toLowerCase().endsWith(executablewithoutExtension)
|
||||
) {
|
||||
const gameKey = levelKeys.game("steam", gameId);
|
||||
const game = await gamesSublevel.get(gameKey);
|
||||
|
||||
@@ -124,7 +131,6 @@ const getSystemProcessMap = async () => {
|
||||
if (!key || !value) return;
|
||||
|
||||
const STEAM_COMPAT_DATA_PATH = process.environ?.STEAM_COMPAT_DATA_PATH;
|
||||
|
||||
if (STEAM_COMPAT_DATA_PATH) {
|
||||
winePrefixMap.set(value, STEAM_COMPAT_DATA_PATH);
|
||||
}
|
||||
|
||||
@@ -8,58 +8,65 @@ import { levelKeys } from "@main/level/sublevels";
|
||||
export const getUserData = async () => {
|
||||
return HydraApi.get<UserDetails>(`/profile/me`)
|
||||
.then(async (me) => {
|
||||
db.get<string, User>(levelKeys.user, { valueEncoding: "json" }).then(
|
||||
(user) => {
|
||||
return db.put<string, User>(
|
||||
levelKeys.user,
|
||||
{
|
||||
...user,
|
||||
id: me.id,
|
||||
displayName: me.displayName,
|
||||
profileImageUrl: me.profileImageUrl,
|
||||
backgroundImageUrl: me.backgroundImageUrl,
|
||||
subscription: me.subscription,
|
||||
},
|
||||
{ valueEncoding: "json" }
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
try {
|
||||
const user = await db.get<string, User>(levelKeys.user, {
|
||||
valueEncoding: "json",
|
||||
});
|
||||
await db.put<string, User>(
|
||||
levelKeys.user,
|
||||
{
|
||||
...user,
|
||||
id: me.id,
|
||||
displayName: me.displayName,
|
||||
profileImageUrl: me.profileImageUrl,
|
||||
backgroundImageUrl: me.backgroundImageUrl,
|
||||
subscription: me.subscription,
|
||||
},
|
||||
{ valueEncoding: "json" }
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error("Failed to update user in DB", error);
|
||||
}
|
||||
return me;
|
||||
})
|
||||
.catch(async (err) => {
|
||||
if (err instanceof UserNotLoggedInError) {
|
||||
return null;
|
||||
}
|
||||
logger.error("Failed to get logged user");
|
||||
|
||||
const loggedUser = await db.get<string, User>(levelKeys.user, {
|
||||
valueEncoding: "json",
|
||||
});
|
||||
logger.error("Failed to get logged user", err);
|
||||
|
||||
if (loggedUser) {
|
||||
return {
|
||||
...loggedUser,
|
||||
username: "",
|
||||
bio: "",
|
||||
email: null,
|
||||
profileVisibility: "PUBLIC" as ProfileVisibility,
|
||||
quirks: {
|
||||
backupsPerGameLimit: 0,
|
||||
},
|
||||
subscription: loggedUser.subscription
|
||||
? {
|
||||
id: loggedUser.subscription.id,
|
||||
status: loggedUser.subscription.status,
|
||||
plan: {
|
||||
id: loggedUser.subscription.plan.id,
|
||||
name: loggedUser.subscription.plan.name,
|
||||
},
|
||||
expiresAt: loggedUser.subscription.expiresAt,
|
||||
}
|
||||
: null,
|
||||
featurebaseJwt: "",
|
||||
} as UserDetails;
|
||||
try {
|
||||
const loggedUser = await db.get<string, User>(levelKeys.user, {
|
||||
valueEncoding: "json",
|
||||
});
|
||||
|
||||
if (loggedUser) {
|
||||
return {
|
||||
...loggedUser,
|
||||
username: "",
|
||||
bio: "",
|
||||
email: null,
|
||||
profileVisibility: "PUBLIC" as ProfileVisibility,
|
||||
quirks: {
|
||||
backupsPerGameLimit: 0,
|
||||
},
|
||||
subscription: loggedUser.subscription
|
||||
? {
|
||||
id: loggedUser.subscription.id,
|
||||
status: loggedUser.subscription.status,
|
||||
plan: {
|
||||
id: loggedUser.subscription.plan.id,
|
||||
name: loggedUser.subscription.plan.name,
|
||||
},
|
||||
expiresAt: loggedUser.subscription.expiresAt,
|
||||
}
|
||||
: null,
|
||||
featurebaseJwt: "",
|
||||
} as UserDetails;
|
||||
}
|
||||
} catch (dbError) {
|
||||
logger.error("Failed to read user from DB", dbError);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
4
src/renderer/src/declaration.d.ts
vendored
4
src/renderer/src/declaration.d.ts
vendored
@@ -30,9 +30,9 @@ import type {
|
||||
AchievementCustomNotificationPosition,
|
||||
AchievementNotificationInfo,
|
||||
Game,
|
||||
DiskUsage,
|
||||
} from "@types";
|
||||
import type { AxiosProgressEvent } from "axios";
|
||||
import type disk from "diskusage";
|
||||
|
||||
declare global {
|
||||
declare module "*.svg" {
|
||||
@@ -220,7 +220,7 @@ declare global {
|
||||
>;
|
||||
|
||||
/* Hardware */
|
||||
getDiskFreeSpace: (path: string) => Promise<disk.DiskUsage>;
|
||||
getDiskFreeSpace: (path: string) => Promise<DiskUsage>;
|
||||
checkFolderWritePermission: (path: string) => Promise<boolean>;
|
||||
|
||||
/* Cloud save */
|
||||
|
||||
@@ -10,6 +10,11 @@ export type HydraCloudFeature =
|
||||
| "backup"
|
||||
| "achievements-points";
|
||||
|
||||
export interface DiskUsage {
|
||||
free: number;
|
||||
total: number;
|
||||
}
|
||||
|
||||
export interface GameRepack {
|
||||
id: number;
|
||||
title: string;
|
||||
|
||||
Reference in New Issue
Block a user