feat: optimizations

This commit is contained in:
Zamitto
2025-06-26 19:37:28 -03:00
parent cb758cceda
commit bf8fd0dacf
14 changed files with 46 additions and 51 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "hydralauncher", "name": "hydralauncher",
"version": "3.6.1", "version": "3.6.2",
"description": "Hydra", "description": "Hydra",
"main": "./out/main/index.js", "main": "./out/main/index.js",
"author": "Los Broxas", "author": "Los Broxas",

View File

@@ -101,8 +101,13 @@ def process_list():
auth_error = validate_rpc_password() auth_error = validate_rpc_password()
if auth_error: if auth_error:
return auth_error return auth_error
iter_list = ['exe', 'pid', 'name']
if sys.platform != 'win32':
iter_list.append('cwd')
iter_list.append('environ')
process_list = [proc.info for proc in psutil.process_iter(['exe', 'cwd', 'pid', 'name', 'environ'])] process_list = [proc.info for proc in psutil.process_iter(iter_list)]
return jsonify(process_list), 200 return jsonify(process_list), 200
@app.route("/profile-image", methods=["POST"]) @app.route("/profile-image", methods=["POST"])

View File

@@ -1,17 +1,38 @@
import type { GameShop, GameStats } from "@types"; import type { GameShop, GameStats } from "@types";
import { registerEvent } from "../register-event"; import { registerEvent } from "../register-event";
import { HydraApi } from "@main/services"; import { HydraApi } from "@main/services";
import { gamesStatsCacheSublevel, levelKeys } from "@main/level";
const LOCAL_CACHE_EXPIRATION = 1000 * 60 * 30; // 30 minutes
const getGameStats = async ( const getGameStats = async (
_event: Electron.IpcMainInvokeEvent, _event: Electron.IpcMainInvokeEvent,
objectId: string, objectId: string,
shop: GameShop shop: GameShop
) => { ) => {
const cachedStats = await gamesStatsCacheSublevel.get(
levelKeys.game(shop, objectId)
);
if (
cachedStats &&
cachedStats.updatedAt + LOCAL_CACHE_EXPIRATION > Date.now()
) {
return cachedStats;
}
return HydraApi.get<GameStats>( return HydraApi.get<GameStats>(
`/games/stats`, `/games/stats`,
{ objectId, shop }, { objectId, shop },
{ needsAuth: false } { needsAuth: false }
); ).then(async (data) => {
await gamesStatsCacheSublevel.put(levelKeys.game(shop, objectId), {
...data,
updatedAt: Date.now(),
});
return data;
});
}; };
registerEvent("getGameStats", getGameStats); registerEvent("getGameStats", getGameStats);

View File

@@ -20,7 +20,6 @@ import "./library/create-game-shortcut";
import "./library/close-game"; import "./library/close-game";
import "./library/delete-game-folder"; import "./library/delete-game-folder";
import "./library/get-game-by-object-id"; import "./library/get-game-by-object-id";
import "./library/sync-game-by-object-id";
import "./library/get-library"; import "./library/get-library";
import "./library/extract-game-download"; import "./library/extract-game-download";
import "./library/open-game"; import "./library/open-game";

View File

@@ -1,32 +0,0 @@
import { registerEvent } from "../register-event";
import { gamesSublevel, levelKeys } from "@main/level";
import { HydraApi } from "@main/services";
import type { GameShop, UserGameDetails } from "@types";
const syncGameByObjectId = async (
_event: Electron.IpcMainInvokeEvent,
shop: GameShop,
objectId: string
) => {
return HydraApi.get<UserGameDetails>(
`/profile/games/${shop}/${objectId}`
).then(async (res) => {
const { id, playTimeInSeconds, isFavorite, ...rest } = res;
const gameKey = levelKeys.game(shop, objectId);
const currentData = await gamesSublevel.get(gameKey);
await gamesSublevel.put(gameKey, {
...currentData,
...rest,
remoteId: id,
playTimeInMilliseconds: playTimeInSeconds * 1000,
favorite: isFavorite ?? currentData?.favorite,
});
return res;
});
};
registerEvent("syncGameByObjectId", syncGameByObjectId);

View File

@@ -0,0 +1,11 @@
import type { GameStats } from "@types";
import { db } from "../level";
import { levelKeys } from "./keys";
export const gamesStatsCacheSublevel = db.sublevel<
string,
GameStats & { updatedAt: number }
>(levelKeys.gameStatsCache, {
valueEncoding: "json",
});

View File

@@ -2,6 +2,7 @@ export * from "./downloads";
export * from "./games"; export * from "./games";
export * from "./game-shop-assets"; export * from "./game-shop-assets";
export * from "./game-shop-cache"; export * from "./game-shop-cache";
export * from "./game-stats-cache";
export * from "./game-achievements"; export * from "./game-achievements";
export * from "./keys"; export * from "./keys";
export * from "./themes"; export * from "./themes";

View File

@@ -7,6 +7,7 @@ export const levelKeys = {
auth: "auth", auth: "auth",
themes: "themes", themes: "themes",
gameShopAssets: "gameShopAssets", gameShopAssets: "gameShopAssets",
gameStatsCache: "gameStatsAssets",
gameShopCache: "gameShopCache", gameShopCache: "gameShopCache",
gameShopCacheItem: (shop: GameShop, objectId: string, language: string) => gameShopCacheItem: (shop: GameShop, objectId: string, language: string) =>
`${shop}:${objectId}:${language}`, `${shop}:${objectId}:${language}`,

View File

@@ -5,7 +5,7 @@ import { logger } from "../logger";
import { db, gameAchievementsSublevel, levelKeys } from "@main/level"; import { db, gameAchievementsSublevel, levelKeys } from "@main/level";
import { AxiosError } from "axios"; import { AxiosError } from "axios";
const LOCAL_CACHE_EXPIRATION = 1000 * 60 * 30; // 30 minutes const LOCAL_CACHE_EXPIRATION = 1000 * 60 * 60; // 1 hour
const getModifiedSinceHeader = ( const getModifiedSinceHeader = (
cachedAchievements: GameAchievement | undefined cachedAchievements: GameAchievement | undefined

View File

@@ -31,8 +31,8 @@ export interface ProcessPayload {
exe: string | null; exe: string | null;
pid: number; pid: number;
name: string; name: string;
environ: Record<string, string> | null; environ?: Record<string, string> | null;
cwd: string | null; cwd?: string | null;
} }
export interface PauseSeedingPayload { export interface PauseSeedingPayload {

View File

@@ -25,7 +25,7 @@ interface GameExecutables {
[key: string]: ExecutableInfo[]; [key: string]: ExecutableInfo[];
} }
const TICKS_TO_UPDATE_API = 80; const TICKS_TO_UPDATE_API = 120;
let currentTick = 1; let currentTick = 1;
const platform = process.platform; const platform = process.platform;

View File

@@ -187,8 +187,6 @@ contextBridge.exposeInMainWorld("electron", {
ipcRenderer.invoke("deleteGameFolder", shop, objectId), ipcRenderer.invoke("deleteGameFolder", shop, objectId),
getGameByObjectId: (shop: GameShop, objectId: string) => getGameByObjectId: (shop: GameShop, objectId: string) =>
ipcRenderer.invoke("getGameByObjectId", shop, objectId), ipcRenderer.invoke("getGameByObjectId", shop, objectId),
syncGameByObjectId: (shop: GameShop, objectId: string) =>
ipcRenderer.invoke("syncGameByObjectId", shop, objectId),
resetGameAchievements: (shop: GameShop, objectId: string) => resetGameAchievements: (shop: GameShop, objectId: string) =>
ipcRenderer.invoke("resetGameAchievements", shop, objectId), ipcRenderer.invoke("resetGameAchievements", shop, objectId),
extractGameDownload: (shop: GameShop, objectId: string) => extractGameDownload: (shop: GameShop, objectId: string) =>

View File

@@ -182,14 +182,6 @@ export function GameDetailsContextProvider({
}) })
.catch(() => {}); .catch(() => {});
} }
window.electron
.syncGameByObjectId(shop, objectId)
.then(() => {
if (abortController.signal.aborted) return;
updateGame();
})
.catch(() => {});
}, [ }, [
updateGame, updateGame,
dispatch, dispatch,

View File

@@ -155,7 +155,6 @@ declare global {
shop: GameShop, shop: GameShop,
objectId: string objectId: string
) => Promise<LibraryGame | null>; ) => Promise<LibraryGame | null>;
syncGameByObjectId: (shop: GameShop, objectId: string) => Promise<void>;
onGamesRunning: ( onGamesRunning: (
cb: ( cb: (
gamesRunning: Pick<GameRunning, "id" | "sessionDurationInMillis">[] gamesRunning: Pick<GameRunning, "id" | "sessionDurationInMillis">[]