feat: browser window for notification

This commit is contained in:
Zamitto 2024-09-27 14:59:08 -03:00
parent 753a293cd7
commit bdba3dd29c
6 changed files with 150 additions and 17 deletions

View File

@ -49,27 +49,43 @@ export const mergeAchievements = async (
});
if (newAchievements.length) {
WindowManager.mainWindow?.webContents.send(
"on-achievement-unlocked",
objectId,
shop
);
}
if (newAchievements.length > 0 && publishNotification) {
const achievement = newAchievements.pop()!;
const achievement = newAchievements.at(-1)!;
const achievementInfo = JSON.parse(
localGameAchievement?.achievements || "[]"
).find((steamAchievement) => {
return achievement.name === steamAchievement.name;
});
publishNewAchievementNotification(
game.title ?? "",
WindowManager.mainWindow?.webContents.send(
"on-achievement-unlocked",
objectId,
shop,
achievementInfo.displayName,
achievementInfo.icon,
newAchievements.length
achievementInfo.icon
);
if (publishNotification) {
WindowManager.notificationWindow?.webContents.send(
"on-achievement-unlocked",
objectId,
shop,
achievementInfo.displayName,
achievementInfo.icon
);
WindowManager.notificationWindow?.setBounds({ y: 50 });
setTimeout(() => {
WindowManager.notificationWindow?.setBounds({ y: -100 });
}, 4000);
publishNewAchievementNotification(
game.title ?? "",
achievementInfo.displayName,
achievementInfo.icon,
newAchievements.length
);
}
}
const mergedLocalAchievements = unlockedAchievements.concat(newAchievements);

View File

@ -19,6 +19,7 @@ import { HydraApi } from "./hydra-api";
export class WindowManager {
public static mainWindow: Electron.BrowserWindow | null = null;
public static notificationWindow: Electron.BrowserWindow | null = null;
private static loadURL(hash = "") {
// HMR for renderer base on electron-vite cli.
@ -78,7 +79,45 @@ export class WindowManager {
app.quit();
}
WindowManager.mainWindow?.setProgressBar(-1);
WindowManager.mainWindow = null;
});
this.notificationWindow = new BrowserWindow({
transparent: true,
maximizable: false,
minimizable: false,
focusable: true,
skipTaskbar: true,
frame: false,
width: 240,
height: 60,
x: 25,
y: -100,
webPreferences: {
preload: path.join(__dirname, "../preload/index.mjs"),
sandbox: false,
},
});
if (!app.isPackaged)
WindowManager.notificationWindow?.webContents.openDevTools();
this.notificationWindow.setVisibleOnAllWorkspaces(true, {
visibleOnFullScreen: true,
});
this.notificationWindow.setAlwaysOnTop(true, "screen-saver", 1);
if (is.dev && process.env["ELECTRON_RENDERER_URL"]) {
this.notificationWindow.loadURL(
`${process.env["ELECTRON_RENDERER_URL"]}#/achievement-notification`
);
} else {
this.notificationWindow.loadFile(
path.join(__dirname, "../renderer/index.html"),
{
hash: "achievement-notification",
}
);
}
}
public static openAuthWindow() {

View File

@ -51,12 +51,21 @@ contextBridge.exposeInMainWorld("electron", {
getTrendingGames: () => ipcRenderer.invoke("getTrendingGames"),
getGameAchievements: (objectId: string, shop: GameShop) =>
ipcRenderer.invoke("getGameAchievements", objectId, shop),
onAchievementUnlocked: (cb: (objectId: string, shop: GameShop) => void) => {
onAchievementUnlocked: (
cb: (
objectId: string,
shop: GameShop,
displayName: string,
iconUrl: string
) => void
) => {
const listener = (
_event: Electron.IpcRendererEvent,
objectId: string,
shop: GameShop
) => cb(objectId, shop);
shop: GameShop,
displayName: string,
iconUrl: string
) => cb(objectId, shop, displayName, iconUrl);
ipcRenderer.on("on-achievement-unlocked", listener);
return () =>
ipcRenderer.removeListener("on-achievement-unlocked", listener);

View File

@ -71,7 +71,12 @@ declare global {
shop: GameShop
) => Promise<GameAchievement[]>;
onAchievementUnlocked: (
cb: (objectId: string, shop: GameShop) => void
cb: (
objectId: string,
shop: GameShop,
displayName: string,
iconUrl: string
) => void
) => () => Electron.IpcRenderer;
/* Library */

View File

@ -28,6 +28,7 @@ import {
import { store } from "./store";
import resources from "@locales";
import { Achievemnt } from "./pages/achievement/achievement";
Sentry.init({});
@ -65,6 +66,7 @@ ReactDOM.createRoot(document.getElementById("root")!).render(
<Route path="/settings" Component={Settings} />
<Route path="/profile/:userId" Component={Profile} />
</Route>
<Route path="/achievement-notification" Component={Achievemnt} />
</Routes>
</HashRouter>
</Provider>

View File

@ -0,0 +1,62 @@
import { useEffect, useState } from "react";
export function Achievemnt() {
const [achievementInfo, setAchievementInfo] = useState<{
displayName: string;
icon: string;
} | null>(null);
const [audio, setAudio] = useState<string | null>(null);
useEffect(() => {
const unsubscribe = window.electron.onAchievementUnlocked(
(_object, _shop, displayName, icon) => {
console.log("Achievement unlocked", displayName, icon);
setAudio(
"https://us-tuna-sounds-files.voicemod.net/ade71f0d-a41b-4e3a-8097-9f1cc585745c-1646035604239.mp3"
);
setAchievementInfo({
displayName,
icon,
});
}
);
return () => {
unsubscribe();
};
}, []);
useEffect(() => {
if (audio) {
const audioElement = new Audio(audio);
audioElement.volume = 1.0;
audioElement.play();
setAudio(null);
}
}, [audio]);
if (!achievementInfo) return <p>Nada</p>;
return (
<div
style={{
display: "flex",
flexDirection: "row",
gap: "8px",
alignItems: "center",
}}
>
<img
src={achievementInfo.icon}
alt={achievementInfo.displayName}
style={{ width: 60, height: 60 }}
/>
<div>
<p>Achievement unlocked</p>
<p>{achievementInfo.displayName}</p>
</div>
</div>
);
}