feat: add isMainWindowOpen functionality and enhance game launcher UI

This commit is contained in:
Moyasee
2026-01-25 08:33:53 +02:00
parent 82f3dd8268
commit e0bae9072c
5 changed files with 70 additions and 12 deletions

View File

@@ -7,6 +7,7 @@ import "./get-hydra-decky-plugin-info";
import "./hydra-api-call";
import "./install-common-redist";
import "./install-hydra-decky-plugin";
import "./is-main-window-open";
import "./open-checkout";
import "./open-external";
import "./open-main-window";

View File

@@ -0,0 +1,12 @@
import { registerEvent } from "../register-event";
import { WindowManager } from "@main/services";
const isMainWindowOpen = async () => {
return (
WindowManager.mainWindow !== null &&
!WindowManager.mainWindow.isDestroyed() &&
WindowManager.mainWindow.isVisible()
);
};
registerEvent("isMainWindowOpen", isMainWindowOpen);

View File

@@ -679,6 +679,7 @@ contextBridge.exposeInMainWorld("electron", {
showGameLauncherWindow: () => ipcRenderer.invoke("showGameLauncherWindow"),
closeGameLauncherWindow: () => ipcRenderer.invoke("closeGameLauncherWindow"),
openMainWindow: () => ipcRenderer.invoke("openMainWindow"),
isMainWindowOpen: () => ipcRenderer.invoke("isMainWindowOpen"),
/* LevelDB Generic CRUD */
leveldb: {

View File

@@ -12,6 +12,36 @@
position: relative;
overflow: hidden;
&__background {
position: absolute;
top: -20px;
left: -20px;
right: -20px;
bottom: -20px;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
filter: blur(20px);
transform: scale(1.1);
z-index: 0;
}
&__overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
135deg,
rgba(0, 0, 0, 0.75) 0%,
rgba(0, 0, 0, 0.85) 50%,
rgba(0, 0, 0, 0.9) 100%
);
pointer-events: none;
z-index: 1;
}
&__glow {
position: absolute;
top: 0;
@@ -24,14 +54,14 @@
transparent 50%
);
pointer-events: none;
z-index: 0;
z-index: 2;
}
&__logo-badge {
position: absolute;
top: calc(globals.$spacing-unit * 2);
right: calc(globals.$spacing-unit * 2);
z-index: 3;
z-index: 10;
svg {
width: 28px;
@@ -48,7 +78,7 @@
-webkit-app-region: no-drag;
min-height: 0;
position: relative;
z-index: 1;
z-index: 5;
}
&__cover {
@@ -85,7 +115,7 @@
flex-direction: column;
justify-content: center;
flex: 1;
gap: calc(globals.$spacing-unit / 2);
gap: calc(globals.$spacing-unit);
}
&__title {
@@ -167,7 +197,7 @@
display: flex;
align-items: center;
justify-content: center;
margin-top: calc(globals.$spacing-unit);
margin-top: calc(globals.$spacing-unit * 2);
&:hover {
background-color: #dadbe1;

View File

@@ -25,6 +25,7 @@ export default function GameLauncher() {
const [colorExtracted, setColorExtracted] = useState(false);
const [colorError, setColorError] = useState(false);
const [windowShown, setWindowShown] = useState(false);
const [isMainWindowOpen, setIsMainWindowOpen] = useState(false);
const formatPlayTime = useCallback(
(playTimeInMilliseconds = 0) => {
@@ -50,6 +51,10 @@ export default function GameLauncher() {
setGameAssets(assets);
});
}
window.electron.isMainWindowOpen().then((isOpen) => {
setIsMainWindowOpen(isOpen);
});
}, [shop, objectId]);
useEffect(() => {
@@ -128,6 +133,13 @@ export default function GameLauncher() {
return (
<div className="game-launcher" style={backgroundStyle}>
{coverImage && (
<div
className="game-launcher__background"
style={{ backgroundImage: `url(${coverImage})` }}
/>
)}
<div className="game-launcher__overlay" />
<div className="game-launcher__glow" style={glowStyle} />
<div className="game-launcher__logo-badge">
@@ -166,13 +178,15 @@ export default function GameLauncher() {
<span className="game-launcher__dots" />
</p>
<button
type="button"
className="game-launcher__button"
onClick={handleOpenHydra}
>
{t("open_hydra")}
</button>
{!isMainWindowOpen && (
<button
type="button"
className="game-launcher__button"
onClick={handleOpenHydra}
>
{t("open_hydra")}
</button>
)}
</div>
{(playTime > 0 || achievementCount > 0) && (