mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-01-23 13:34:54 +03:00
feat: signout modal text
This commit is contained in:
parent
468af807b0
commit
adcb505ab7
@ -5,7 +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";
|
import { GameRunning } from "@types";
|
||||||
|
|
||||||
const gamesPlaytime = new Map<
|
const gamesPlaytime = new Map<
|
||||||
number,
|
number,
|
||||||
@ -93,7 +93,7 @@ export const watchProcesses = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (WindowManager.mainWindow) {
|
if (WindowManager.mainWindow) {
|
||||||
const runningGames = Array.from(gamesPlaytime.entries()).map((entry) => {
|
const gamesRunning = Array.from(gamesPlaytime.entries()).map((entry) => {
|
||||||
return {
|
return {
|
||||||
id: entry[0],
|
id: entry[0],
|
||||||
sessionDurationInMillis: performance.now() - entry[1].firstTick,
|
sessionDurationInMillis: performance.now() - entry[1].firstTick,
|
||||||
@ -102,7 +102,7 @@ export const watchProcesses = async () => {
|
|||||||
|
|
||||||
WindowManager.mainWindow.webContents.send(
|
WindowManager.mainWindow.webContents.send(
|
||||||
"on-games-running",
|
"on-games-running",
|
||||||
runningGames as RunningGameEvent
|
gamesRunning as Pick<GameRunning, "id" | "sessionDurationInMillis">[]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,7 @@ import type {
|
|||||||
UserPreferences,
|
UserPreferences,
|
||||||
AppUpdaterEvent,
|
AppUpdaterEvent,
|
||||||
StartGameDownloadPayload,
|
StartGameDownloadPayload,
|
||||||
RunningGameEvent,
|
GameRunning,
|
||||||
} from "@types";
|
} from "@types";
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld("electron", {
|
contextBridge.exposeInMainWorld("electron", {
|
||||||
@ -85,11 +85,13 @@ 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),
|
||||||
onRunningGames: (cb: (runningGames: RunningGameEvent) => void) => {
|
onGamesRunning: (
|
||||||
const listener = (
|
cb: (
|
||||||
_event: Electron.IpcRendererEvent,
|
gamesRunning: Pick<GameRunning, "id" | "sessionDurationInMillis">[]
|
||||||
runningGames: RunningGameEvent
|
) => void
|
||||||
) => cb(runningGames);
|
) => {
|
||||||
|
const listener = (_event: Electron.IpcRendererEvent, gamesRunning) =>
|
||||||
|
cb(gamesRunning);
|
||||||
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);
|
||||||
},
|
},
|
||||||
|
@ -21,7 +21,7 @@ import {
|
|||||||
closeToast,
|
closeToast,
|
||||||
setUserDetails,
|
setUserDetails,
|
||||||
setProfileBackground,
|
setProfileBackground,
|
||||||
setRunningGame,
|
setGameRunning,
|
||||||
} from "@renderer/features";
|
} from "@renderer/features";
|
||||||
|
|
||||||
export interface AppProps {
|
export interface AppProps {
|
||||||
@ -97,16 +97,16 @@ export function App() {
|
|||||||
}, [dispatch, fetchUserDetails]);
|
}, [dispatch, fetchUserDetails]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = window.electron.onRunningGames((runningGames) => {
|
const unsubscribe = window.electron.onGamesRunning((gamesRunning) => {
|
||||||
if (runningGames.length) {
|
if (gamesRunning.length) {
|
||||||
const lastGame = runningGames[runningGames.length - 1];
|
const lastGame = gamesRunning[gamesRunning.length - 1];
|
||||||
const libraryGame = library.find(
|
const libraryGame = library.find(
|
||||||
(library) => library.id === lastGame.id
|
(library) => library.id === lastGame.id
|
||||||
);
|
);
|
||||||
|
|
||||||
if (libraryGame) {
|
if (libraryGame) {
|
||||||
dispatch(
|
dispatch(
|
||||||
setRunningGame({
|
setGameRunning({
|
||||||
...libraryGame,
|
...libraryGame,
|
||||||
sessionDurationInMillis: lastGame.sessionDurationInMillis,
|
sessionDurationInMillis: lastGame.sessionDurationInMillis,
|
||||||
})
|
})
|
||||||
@ -114,7 +114,7 @@ export function App() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dispatch(setRunningGame(null));
|
dispatch(setGameRunning(null));
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -13,7 +13,7 @@ export function SidebarProfile() {
|
|||||||
|
|
||||||
const { userDetails, profileBackground } = useUserDetails();
|
const { userDetails, profileBackground } = useUserDetails();
|
||||||
|
|
||||||
const { runningGame } = useAppSelector((state) => state.runningGame);
|
const { gameRunning } = useAppSelector((state) => state.gameRunning);
|
||||||
|
|
||||||
const handleButtonClick = () => {
|
const handleButtonClick = () => {
|
||||||
if (userDetails === null) {
|
if (userDetails === null) {
|
||||||
@ -54,19 +54,19 @@ export function SidebarProfile() {
|
|||||||
{userDetails ? userDetails.displayName : t("sign_in")}
|
{userDetails ? userDetails.displayName : t("sign_in")}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{userDetails && runningGame && (
|
{userDetails && gameRunning && (
|
||||||
<div>
|
<div>
|
||||||
<small>{runningGame.title}</small>
|
<small>{gameRunning.title}</small>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{userDetails && runningGame && (
|
{userDetails && gameRunning && (
|
||||||
<img
|
<img
|
||||||
alt={runningGame.title}
|
alt={gameRunning.title}
|
||||||
width={24}
|
width={24}
|
||||||
style={{ borderRadius: 4 }}
|
style={{ borderRadius: 4 }}
|
||||||
src={runningGame.iconUrl}
|
src={gameRunning.iconUrl}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -109,10 +109,10 @@ export function GameDetailsContextProvider({
|
|||||||
}, [objectID, gameTitle, dispatch]);
|
}, [objectID, gameTitle, dispatch]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const unsubscribe = window.electron.onRunningGames((gamesIds) => {
|
const unsubscribe = window.electron.onGamesRunning((gamesIds) => {
|
||||||
const updatedIsGameRunning =
|
const updatedIsGameRunning =
|
||||||
!!game?.id &&
|
!!game?.id &&
|
||||||
!!gamesIds.find((runningGame) => runningGame.id == game.id);
|
!!gamesIds.find((gameRunning) => gameRunning.id == game.id);
|
||||||
|
|
||||||
if (isGameRunning != updatedIsGameRunning) {
|
if (isGameRunning != updatedIsGameRunning) {
|
||||||
updateGame();
|
updateGame();
|
||||||
|
7
src/renderer/src/declaration.d.ts
vendored
7
src/renderer/src/declaration.d.ts
vendored
@ -14,7 +14,6 @@ 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";
|
||||||
|
|
||||||
@ -72,8 +71,10 @@ 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>;
|
||||||
onRunningGames: (
|
onGamesRunning: (
|
||||||
cb: (runningGames: RunningGameEvent) => void
|
cb: (
|
||||||
|
gamesRunning: Pick<GameRunning, "id" | "sessionDurationInMillis">[]
|
||||||
|
) => void
|
||||||
) => () => Electron.IpcRenderer;
|
) => () => Electron.IpcRenderer;
|
||||||
onLibraryBatchComplete: (cb: () => void) => () => Electron.IpcRenderer;
|
onLibraryBatchComplete: (cb: () => void) => () => Electron.IpcRenderer;
|
||||||
|
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
import { PayloadAction, createSlice } from "@reduxjs/toolkit";
|
||||||
import { RunningGame } from "@types";
|
import { GameRunning } from "@types";
|
||||||
|
|
||||||
export interface RunningGameState {
|
export interface GameRunningState {
|
||||||
runningGame: RunningGame | null;
|
gameRunning: GameRunning | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: RunningGameState = {
|
const initialState: GameRunningState = {
|
||||||
runningGame: null,
|
gameRunning: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const runningGameSlice = createSlice({
|
export const gameRunningSlice = createSlice({
|
||||||
name: "running-game",
|
name: "running-game",
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
setRunningGame: (state, action: PayloadAction<RunningGame | null>) => {
|
setGameRunning: (state, action: PayloadAction<GameRunning | null>) => {
|
||||||
state.runningGame = action.payload;
|
state.gameRunning = action.payload;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { setRunningGame } = runningGameSlice.actions;
|
export const { setGameRunning } = gameRunningSlice.actions;
|
||||||
|
@ -32,7 +32,7 @@ export function UserContent({
|
|||||||
const [showEditProfileModal, setShowEditProfileModal] = useState(false);
|
const [showEditProfileModal, setShowEditProfileModal] = useState(false);
|
||||||
const [showSignOutModal, setShowSignOutModal] = useState(false);
|
const [showSignOutModal, setShowSignOutModal] = useState(false);
|
||||||
|
|
||||||
const { runningGame } = useAppSelector((state) => state.runningGame);
|
const { gameRunning } = useAppSelector((state) => state.gameRunning);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -104,10 +104,10 @@ export function UserContent({
|
|||||||
position: "relative",
|
position: "relative",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{runningGame && isMe && (
|
{gameRunning && isMe && (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `url(${steamUrlBuilder.libraryHero(runningGame.objectID)})`,
|
backgroundImage: `url(${steamUrlBuilder.libraryHero(gameRunning.objectID)})`,
|
||||||
backgroundPosition: "top",
|
backgroundPosition: "top",
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
inset: 0,
|
inset: 0,
|
||||||
@ -140,7 +140,7 @@ export function UserContent({
|
|||||||
|
|
||||||
<div className={styles.profileInformation}>
|
<div className={styles.profileInformation}>
|
||||||
<h2 style={{ fontWeight: "bold" }}>{userProfile.displayName}</h2>
|
<h2 style={{ fontWeight: "bold" }}>{userProfile.displayName}</h2>
|
||||||
{isMe && runningGame && (
|
{isMe && gameRunning && (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "flex",
|
display: "flex",
|
||||||
@ -156,12 +156,12 @@ export function UserContent({
|
|||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<p>{runningGame.title}</p>
|
<p>{gameRunning.title}</p>
|
||||||
</div>
|
</div>
|
||||||
<small>
|
<small>
|
||||||
{t("playing_for", {
|
{t("playing_for", {
|
||||||
amount: formatDiffInMillis(
|
amount: formatDiffInMillis(
|
||||||
runningGame.sessionDurationInMillis,
|
gameRunning.sessionDurationInMillis,
|
||||||
new Date()
|
new Date()
|
||||||
),
|
),
|
||||||
})}
|
})}
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
userPreferencesSlice,
|
userPreferencesSlice,
|
||||||
toastSlice,
|
toastSlice,
|
||||||
userDetailsSlice,
|
userDetailsSlice,
|
||||||
runningGameSlice,
|
gameRunningSlice,
|
||||||
} from "@renderer/features";
|
} from "@renderer/features";
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
@ -19,7 +19,7 @@ export const store = configureStore({
|
|||||||
download: downloadSlice.reducer,
|
download: downloadSlice.reducer,
|
||||||
toast: toastSlice.reducer,
|
toast: toastSlice.reducer,
|
||||||
userDetails: userDetailsSlice.reducer,
|
userDetails: userDetailsSlice.reducer,
|
||||||
runningGame: runningGameSlice.reducer,
|
gameRunning: gameRunningSlice.reducer,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -127,12 +127,7 @@ export interface Game {
|
|||||||
|
|
||||||
export type LibraryGame = Omit<Game, "repacks">;
|
export type LibraryGame = Omit<Game, "repacks">;
|
||||||
|
|
||||||
export type RunningGameEvent = {
|
export interface GameRunning {
|
||||||
id: number;
|
|
||||||
sessionDurationInMillis: number;
|
|
||||||
}[];
|
|
||||||
|
|
||||||
export interface RunningGame {
|
|
||||||
id: number;
|
id: number;
|
||||||
title: string;
|
title: string;
|
||||||
iconUrl: string;
|
iconUrl: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user