mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-03-09 15:40:26 +00:00
feat: game session start time stamp
This commit is contained in:
parent
800e99fda0
commit
188fe4537a
9 changed files with 45 additions and 34 deletions
|
@ -5,6 +5,7 @@ import { gameRepository } from "@main/repository";
|
||||||
import { getProcesses } from "@main/helpers";
|
import { getProcesses } from "@main/helpers";
|
||||||
import { WindowManager } from "./window-manager";
|
import { WindowManager } from "./window-manager";
|
||||||
import { createGame, updateGamePlaytime } from "./library-sync";
|
import { createGame, updateGamePlaytime } from "./library-sync";
|
||||||
|
import { RunningGameEvent } from "@types";
|
||||||
|
|
||||||
const gamesPlaytime = new Map<
|
const gamesPlaytime = new Map<
|
||||||
number,
|
number,
|
||||||
|
@ -96,10 +97,13 @@ export const watchProcesses = async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WindowManager.mainWindow) {
|
if (WindowManager.mainWindow) {
|
||||||
const gamesRunningIds = Array.from(gamesPlaytime.keys());
|
const runningGames = Array.from(gamesPlaytime.entries()).map((entry) => {
|
||||||
|
return { id: entry[0], sessionStartTimestamp: entry[1].firstTick };
|
||||||
|
});
|
||||||
|
|
||||||
WindowManager.mainWindow.webContents.send(
|
WindowManager.mainWindow.webContents.send(
|
||||||
"on-games-running",
|
"on-games-running",
|
||||||
gamesRunningIds
|
runningGames as RunningGameEvent
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,6 +8,7 @@ import type {
|
||||||
UserPreferences,
|
UserPreferences,
|
||||||
AppUpdaterEvent,
|
AppUpdaterEvent,
|
||||||
StartGameDownloadPayload,
|
StartGameDownloadPayload,
|
||||||
|
RunningGameEvent,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld("electron", {
|
contextBridge.exposeInMainWorld("electron", {
|
||||||
|
@ -84,9 +85,11 @@ contextBridge.exposeInMainWorld("electron", {
|
||||||
ipcRenderer.invoke("deleteGameFolder", gameId),
|
ipcRenderer.invoke("deleteGameFolder", gameId),
|
||||||
getGameByObjectID: (objectID: string) =>
|
getGameByObjectID: (objectID: string) =>
|
||||||
ipcRenderer.invoke("getGameByObjectID", objectID),
|
ipcRenderer.invoke("getGameByObjectID", objectID),
|
||||||
onGamesRunning: (cb: (gamesId: number[]) => void) => {
|
onRunningGames: (cb: (runningGames: RunningGameEvent) => void) => {
|
||||||
const listener = (_event: Electron.IpcRendererEvent, gamesId: number[]) =>
|
const listener = (
|
||||||
cb(gamesId);
|
_event: Electron.IpcRendererEvent,
|
||||||
|
runningGames: RunningGameEvent
|
||||||
|
) => cb(runningGames);
|
||||||
ipcRenderer.on("on-games-running", listener);
|
ipcRenderer.on("on-games-running", listener);
|
||||||
return () => ipcRenderer.removeListener("on-games-running", listener);
|
return () => ipcRenderer.removeListener("on-games-running", listener);
|
||||||
},
|
},
|
||||||
|
|
|
@ -97,16 +97,18 @@ export function App() {
|
||||||
}, [dispatch, fetchUserDetails]);
|
}, [dispatch, fetchUserDetails]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = window.electron.onGamesRunning((gamesIds) => {
|
const unsubscribe = window.electron.onRunningGames((runningGames) => {
|
||||||
if (gamesIds.length) {
|
if (runningGames.length) {
|
||||||
const lastGame = gamesIds.at(-1);
|
const lastGame = runningGames[runningGames.length - 1];
|
||||||
const libraryGame = library.find((library) => library.id == lastGame);
|
const libraryGame = library.find(
|
||||||
|
(library) => library.id === lastGame.id
|
||||||
|
);
|
||||||
|
|
||||||
if (libraryGame) {
|
if (libraryGame) {
|
||||||
dispatch(
|
dispatch(
|
||||||
setRunningGame({
|
setRunningGame({
|
||||||
...libraryGame,
|
...libraryGame,
|
||||||
sessionStartTimestamp: new Date().getTime(),
|
sessionStartTimestamp: lastGame.sessionStartTimestamp,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -109,20 +109,19 @@ export function GameDetailsContextProvider({
|
||||||
}, [objectID, gameTitle, dispatch]);
|
}, [objectID, gameTitle, dispatch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const listeners = [
|
const unsubscribe = window.electron.onRunningGames((gamesIds) => {
|
||||||
window.electron.onGamesRunning((gamesIds) => {
|
const updatedIsGameRunning =
|
||||||
const updatedIsGameRunning = !!game?.id && gamesIds.includes(game.id);
|
!!game?.id &&
|
||||||
|
!!gamesIds.find((runningGame) => runningGame.id == game.id);
|
||||||
|
|
||||||
if (isGameRunning != updatedIsGameRunning) {
|
if (isGameRunning != updatedIsGameRunning) {
|
||||||
updateGame();
|
updateGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
setisGameRunning(updatedIsGameRunning);
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
|
|
||||||
|
setisGameRunning(updatedIsGameRunning);
|
||||||
|
});
|
||||||
return () => {
|
return () => {
|
||||||
listeners.forEach((unsubscribe) => unsubscribe());
|
unsubscribe();
|
||||||
};
|
};
|
||||||
}, [game?.id, isGameRunning, updateGame]);
|
}, [game?.id, isGameRunning, updateGame]);
|
||||||
|
|
||||||
|
|
5
src/renderer/src/declaration.d.ts
vendored
5
src/renderer/src/declaration.d.ts
vendored
|
@ -14,6 +14,7 @@ import type {
|
||||||
RealDebridUser,
|
RealDebridUser,
|
||||||
DownloadSource,
|
DownloadSource,
|
||||||
UserProfile,
|
UserProfile,
|
||||||
|
RunningGameEvent,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
import type { DiskSpace } from "check-disk-space";
|
import type { DiskSpace } from "check-disk-space";
|
||||||
|
|
||||||
|
@ -71,8 +72,8 @@ declare global {
|
||||||
removeGame: (gameId: number) => Promise<void>;
|
removeGame: (gameId: number) => Promise<void>;
|
||||||
deleteGameFolder: (gameId: number) => Promise<unknown>;
|
deleteGameFolder: (gameId: number) => Promise<unknown>;
|
||||||
getGameByObjectID: (objectID: string) => Promise<Game | null>;
|
getGameByObjectID: (objectID: string) => Promise<Game | null>;
|
||||||
onGamesRunning: (
|
onRunningGames: (
|
||||||
cb: (gamesId: number[]) => void
|
cb: (runningGames: RunningGameEvent) => void
|
||||||
) => () => Electron.IpcRenderer;
|
) => () => Electron.IpcRenderer;
|
||||||
onLibraryBatchComplete: (cb: () => void) => () => Electron.IpcRenderer;
|
onLibraryBatchComplete: (cb: () => void) => () => Electron.IpcRenderer;
|
||||||
|
|
||||||
|
|
|
@ -43,12 +43,5 @@ export const buildGameDetailsPath = (
|
||||||
return `/game/${game.shop}/${game.objectID}?${searchParams.toString()}`;
|
return `/game/${game.shop}/${game.objectID}?${searchParams.toString()}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const darkenColor = (
|
export const darkenColor = (color: string, amount: number, alpha: number = 1) =>
|
||||||
color: string,
|
new Color(color).darken(amount).alpha(alpha).toString();
|
||||||
amount: number,
|
|
||||||
alpha: number = 1
|
|
||||||
) => {
|
|
||||||
const newColor = new Color(color).darken(amount).alpha(alpha).toString();
|
|
||||||
console.log(color, newColor);
|
|
||||||
return newColor;
|
|
||||||
};
|
|
||||||
|
|
|
@ -47,7 +47,10 @@ export function useUserDetails() {
|
||||||
const profileBackground = `#151515e6`;
|
const profileBackground = `#151515e6`;
|
||||||
dispatch(setProfileBackground(profileBackground));
|
dispatch(setProfileBackground(profileBackground));
|
||||||
|
|
||||||
window.localStorage.setItem("userDetails", JSON.stringify(userDetails));
|
window.localStorage.setItem(
|
||||||
|
"userDetails",
|
||||||
|
JSON.stringify({ ...userDetails, profileBackground })
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[dispatch]
|
[dispatch]
|
||||||
|
|
|
@ -159,7 +159,7 @@ export function UserContent({
|
||||||
{t("playing_for", {
|
{t("playing_for", {
|
||||||
amount: formatDistance(
|
amount: formatDistance(
|
||||||
runningGame.sessionStartTimestamp,
|
runningGame.sessionStartTimestamp,
|
||||||
new Date()
|
performance.now()
|
||||||
),
|
),
|
||||||
})}
|
})}
|
||||||
</small>
|
</small>
|
||||||
|
|
|
@ -127,7 +127,13 @@ export interface Game {
|
||||||
|
|
||||||
export type LibraryGame = Omit<Game, "repacks">;
|
export type LibraryGame = Omit<Game, "repacks">;
|
||||||
|
|
||||||
|
export type RunningGameEvent = {
|
||||||
|
id: number;
|
||||||
|
sessionStartTimestamp: number;
|
||||||
|
}[];
|
||||||
|
|
||||||
export interface RunningGame {
|
export interface RunningGame {
|
||||||
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
iconUrl: string;
|
iconUrl: string;
|
||||||
objectID: string;
|
objectID: string;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue