feat: custom achievement notification position

This commit is contained in:
Zamitto
2025-05-14 17:42:30 -03:00
parent 96cfa8c015
commit 96385d90d8
9 changed files with 242 additions and 54 deletions

View File

@@ -175,16 +175,6 @@ declare global {
minimized: boolean;
}) => Promise<void>;
extractGameDownload: (shop: GameShop, objectId: string) => Promise<boolean>;
onAchievementUnlocked: (
cb: (
objectId: string,
shop: GameShop,
achievements?: { displayName: string; iconUrl: string }[]
) => void
) => () => Electron.IpcRenderer;
onCombinedAchievementsUnlocked: (
cb: (gameCount: number, achievementCount: number) => void
) => () => Electron.IpcRenderer;
onExtractionComplete: (
cb: (shop: GameShop, objectId: string) => void
) => () => Electron.IpcRenderer;
@@ -331,6 +321,18 @@ declare global {
/* Notifications */
publishNewRepacksNotification: (newRepacksCount: number) => Promise<void>;
onAchievementUnlocked: (
cb: (
objectId: string,
shop: GameShop,
achievements?: { displayName: string; iconUrl: string }[]
) => void
) => () => Electron.IpcRenderer;
onCombinedAchievementsUnlocked: (
cb: (gameCount: number, achievementCount: number) => void
) => () => Electron.IpcRenderer;
onTestAchievementNotification: (cb: () => void) => Electron.IpcRenderer;
updateAchievementCustomNotificationWindowPosition: () => Promise<void>;
/* Themes */
addCustomTheme: (theme: Theme) => Promise<void>;

View File

@@ -72,6 +72,26 @@ export function AchievementNotification() {
};
}, [playAudio]);
useEffect(() => {
const unsubscribe = window.electron.onTestAchievementNotification(() => {
setAchievements((ach) =>
ach.concat([
{
displayName: "Test Achievement",
iconUrl:
"https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Fc.tenor.com%2FRwKr7hVnXREAAAAC%2Fnyan-cat.gif&f=1&nofb=1&ipt=706fd8b00cbfb5b2d2621603834d5f32c0f34cce7113de228d2fcc2247a80318",
},
])
);
playAudio();
});
return () => {
unsubscribe();
};
}, [playAudio]);
const hasAchievementsPending = achievements.length > 0;
const startAnimateClosing = useCallback(() => {

View File

@@ -1,4 +1,4 @@
import { useContext, useEffect, useState } from "react";
import { useContext, useEffect, useMemo, useState } from "react";
import {
TextField,
Button,
@@ -14,6 +14,7 @@ import { settingsContext } from "@renderer/context";
import "./settings-general.scss";
import { DesktopDownloadIcon } from "@primer/octicons-react";
import { logger } from "@renderer/logger";
import { AchievementCustomNotificationPosition } from "@types";
interface LanguageOption {
option: string;
@@ -36,10 +37,12 @@ export function SettingsGeneral() {
downloadsPath: "",
downloadNotificationsEnabled: false,
repackUpdatesNotificationsEnabled: false,
achievementNotificationsEnabled: false,
friendRequestNotificationsEnabled: false,
achievementNotificationsEnabled: false,
achievementCustomNotificationsEnabled: true,
achievementCustomNotificationPosition:
"top_left" as AchievementCustomNotificationPosition,
language: "",
customStyles: window.localStorage.getItem("customStyles") || "",
});
@@ -102,6 +105,10 @@ export function SettingsGeneral() {
userPreferences.repackUpdatesNotificationsEnabled ?? false,
achievementNotificationsEnabled:
userPreferences.achievementNotificationsEnabled ?? false,
achievementCustomNotificationsEnabled:
userPreferences.achievementCustomNotificationsEnabled ?? true,
achievementCustomNotificationPosition:
userPreferences.achievementCustomNotificationPosition ?? "top_left",
friendRequestNotificationsEnabled:
userPreferences.friendRequestNotificationsEnabled ?? false,
language: language ?? "en",
@@ -109,6 +116,21 @@ export function SettingsGeneral() {
}
}, [userPreferences, defaultDownloadsPath]);
const achievementCustomNotificationPositionOptions = useMemo(() => {
return [
"top_left",
"top_right",
"bottom_left",
"bottom_right",
"top_center",
"bottom_center",
].map((position) => ({
key: position,
value: position,
label: t(position),
}));
}, [t]);
const handleLanguageChange = (
event: React.ChangeEvent<HTMLSelectElement>
) => {
@@ -118,9 +140,19 @@ export function SettingsGeneral() {
changeLanguage(value);
};
const handleChange = (values: Partial<typeof form>) => {
const handleChange = async (values: Partial<typeof form>) => {
setForm((prev) => ({ ...prev, ...values }));
updateUserPreferences(values);
await updateUserPreferences(values);
};
const handleChangeAchievementCustomNotificationPosition = async (
event: React.ChangeEvent<HTMLSelectElement>
) => {
const value = event.target.value as AchievementCustomNotificationPosition;
await handleChange({ achievementCustomNotificationPosition: value });
window.electron.updateAchievementCustomNotificationWindowPosition();
};
const handleChooseDownloadsPath = async () => {
@@ -205,6 +237,17 @@ export function SettingsGeneral() {
}
/>
<CheckboxField
label={t("enable_friend_request_notifications")}
checked={form.friendRequestNotificationsEnabled}
onChange={() =>
handleChange({
friendRequestNotificationsEnabled:
!form.friendRequestNotificationsEnabled,
})
}
/>
<CheckboxField
label={t("enable_achievement_notifications")}
checked={form.achievementNotificationsEnabled}
@@ -217,16 +260,27 @@ export function SettingsGeneral() {
/>
<CheckboxField
label={t("enable_friend_request_notifications")}
checked={form.friendRequestNotificationsEnabled}
label={t("enable_achievement_custom_notifications")}
checked={form.achievementCustomNotificationsEnabled}
disabled={!form.achievementNotificationsEnabled}
onChange={() =>
handleChange({
friendRequestNotificationsEnabled:
!form.friendRequestNotificationsEnabled,
achievementCustomNotificationsEnabled:
!form.achievementCustomNotificationsEnabled,
})
}
/>
{form.achievementNotificationsEnabled &&
form.achievementCustomNotificationsEnabled && (
<SelectField
label={t("achievement_custom_notification_position")}
value={form.achievementCustomNotificationPosition}
onChange={handleChangeAchievementCustomNotificationPosition}
options={achievementCustomNotificationPositionOptions}
/>
)}
<h2 className="settings-general__section-title">{t("common_redist")}</h2>
<p className="settings-general__common-redist-description">