mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-18 16:53:57 +00:00
feat: achievement notification custom position and animations
This commit is contained in:
@@ -7,11 +7,16 @@ import {
|
||||
findAllAchievementFiles,
|
||||
getAlternativeObjectIds,
|
||||
} from "./find-achivement-files";
|
||||
import type { AchievementFile, Game, UnlockedAchievement } from "@types";
|
||||
import type {
|
||||
AchievementFile,
|
||||
Game,
|
||||
UnlockedAchievement,
|
||||
UserPreferences,
|
||||
} from "@types";
|
||||
import { achievementsLogger } from "../logger";
|
||||
import { Cracker } from "@shared";
|
||||
import { publishCombinedNewAchievementNotification } from "../notifications";
|
||||
import { gamesSublevel } from "@main/level";
|
||||
import { db, gamesSublevel, levelKeys } from "@main/level";
|
||||
import { WindowManager } from "../window-manager";
|
||||
import { sleep } from "@main/helpers";
|
||||
|
||||
@@ -186,7 +191,7 @@ export class AchievementWatcherManager {
|
||||
return mergeAchievements(game, unlockedAchievements, false);
|
||||
}
|
||||
|
||||
private static preSearchAchievementsWindows = async () => {
|
||||
private static async getGameAchievementFilesWindows() {
|
||||
const games = await gamesSublevel
|
||||
.values()
|
||||
.all()
|
||||
@@ -196,24 +201,24 @@ export class AchievementWatcherManager {
|
||||
|
||||
return Promise.all(
|
||||
games.map((game) => {
|
||||
const gameAchievementFiles: AchievementFile[] = [];
|
||||
const achievementFiles: AchievementFile[] = [];
|
||||
|
||||
for (const objectId of getAlternativeObjectIds(game.objectId)) {
|
||||
gameAchievementFiles.push(
|
||||
achievementFiles.push(
|
||||
...(gameAchievementFilesMap.get(objectId) || [])
|
||||
);
|
||||
|
||||
gameAchievementFiles.push(
|
||||
achievementFiles.push(
|
||||
...findAchievementFileInExecutableDirectory(game)
|
||||
);
|
||||
}
|
||||
|
||||
return this.preProcessGameAchievementFiles(game, gameAchievementFiles);
|
||||
return { game, achievementFiles };
|
||||
})
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
private static preSearchAchievementsWithWine = async () => {
|
||||
private static async getGameAchievementFilesLinux() {
|
||||
const games = await gamesSublevel
|
||||
.values()
|
||||
.all()
|
||||
@@ -221,45 +226,70 @@ export class AchievementWatcherManager {
|
||||
|
||||
return Promise.all(
|
||||
games.map((game) => {
|
||||
const gameAchievementFiles = findAchievementFiles(game);
|
||||
const achievementFiles = findAchievementFiles(game);
|
||||
const achievementFileInsideDirectory =
|
||||
findAchievementFileInExecutableDirectory(game);
|
||||
|
||||
gameAchievementFiles.push(...achievementFileInsideDirectory);
|
||||
achievementFiles.push(...achievementFileInsideDirectory);
|
||||
|
||||
return this.preProcessGameAchievementFiles(game, gameAchievementFiles);
|
||||
return { game, achievementFiles };
|
||||
})
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
public static async preSearchAchievements() {
|
||||
await sleep(5000);
|
||||
await sleep(2000);
|
||||
|
||||
try {
|
||||
const newAchievementsCount =
|
||||
const gameAchievementFiles =
|
||||
process.platform === "win32"
|
||||
? await this.preSearchAchievementsWindows()
|
||||
: await this.preSearchAchievementsWithWine();
|
||||
? await this.getGameAchievementFilesWindows()
|
||||
: await this.getGameAchievementFilesLinux();
|
||||
|
||||
const newAchievementsCount: number[] = [];
|
||||
|
||||
for (const { game, achievementFiles } of gameAchievementFiles) {
|
||||
const result = await this.preProcessGameAchievementFiles(
|
||||
game,
|
||||
achievementFiles
|
||||
);
|
||||
|
||||
newAchievementsCount.push(result);
|
||||
}
|
||||
|
||||
const totalNewGamesWithAchievements = newAchievementsCount.filter(
|
||||
(achievements) => achievements
|
||||
).length;
|
||||
|
||||
const totalNewAchievements = newAchievementsCount.reduce(
|
||||
(acc, val) => acc + val,
|
||||
0
|
||||
);
|
||||
|
||||
if (totalNewAchievements > 0) {
|
||||
WindowManager.notificationWindow?.webContents.send(
|
||||
"on-combined-achievements-unlocked",
|
||||
totalNewGamesWithAchievements,
|
||||
totalNewAchievements
|
||||
const userPreferences = await db.get<string, UserPreferences>(
|
||||
levelKeys.userPreferences,
|
||||
{
|
||||
valueEncoding: "json",
|
||||
}
|
||||
);
|
||||
|
||||
publishCombinedNewAchievementNotification(
|
||||
totalNewAchievements,
|
||||
totalNewGamesWithAchievements
|
||||
);
|
||||
if (userPreferences.achievementNotificationsEnabled) {
|
||||
if (userPreferences.achievementCustomNotificationsEnabled !== false) {
|
||||
WindowManager.notificationWindow?.webContents.send(
|
||||
"on-combined-achievements-unlocked",
|
||||
totalNewGamesWithAchievements,
|
||||
totalNewAchievements,
|
||||
userPreferences.achievementCustomNotificationPosition ??
|
||||
"top_left"
|
||||
);
|
||||
} else {
|
||||
publishCombinedNewAchievementNotification(
|
||||
totalNewAchievements,
|
||||
totalNewGamesWithAchievements
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
achievementsLogger.error("Error on preSearchAchievements", err);
|
||||
|
||||
@@ -106,20 +106,23 @@ export const mergeAchievements = async (
|
||||
};
|
||||
});
|
||||
|
||||
WindowManager.notificationWindow?.webContents.send(
|
||||
"on-achievement-unlocked",
|
||||
game.objectId,
|
||||
game.shop,
|
||||
achievementsInfo
|
||||
);
|
||||
|
||||
publishNewAchievementNotification({
|
||||
achievements: achievementsInfo,
|
||||
unlockedAchievementCount: mergedLocalAchievements.length,
|
||||
totalAchievementCount: achievementsData.length,
|
||||
gameTitle: game.title,
|
||||
gameIcon: game.iconUrl,
|
||||
});
|
||||
if (userPreferences?.achievementCustomNotificationsEnabled !== false) {
|
||||
WindowManager.notificationWindow?.webContents.send(
|
||||
"on-achievement-unlocked",
|
||||
game.objectId,
|
||||
game.shop,
|
||||
userPreferences.achievementCustomNotificationPosition ?? "top_left",
|
||||
achievementsInfo
|
||||
);
|
||||
} else {
|
||||
publishNewAchievementNotification({
|
||||
achievements: achievementsInfo,
|
||||
unlockedAchievementCount: mergedLocalAchievements.length,
|
||||
totalAchievementCount: achievementsData.length,
|
||||
gameTitle: game.title,
|
||||
gameIcon: game.iconUrl,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (game.remoteId) {
|
||||
|
||||
@@ -18,7 +18,11 @@ import { HydraApi } from "./hydra-api";
|
||||
import UserAgent from "user-agents";
|
||||
import { db, gamesSublevel, levelKeys } from "@main/level";
|
||||
import { orderBy, slice } from "lodash-es";
|
||||
import type { ScreenState, UserPreferences } from "@types";
|
||||
import type {
|
||||
AchievementCustomNotificationPosition,
|
||||
ScreenState,
|
||||
UserPreferences,
|
||||
} from "@types";
|
||||
import { AuthPage } from "@shared";
|
||||
import { isStaging } from "@main/constants";
|
||||
|
||||
@@ -276,59 +280,44 @@ export class WindowManager {
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly NOTIFICATION_WINDOW_WIDTH = 350;
|
||||
private static readonly NOTIFICATION_WINDOW_HEIGHT = 104;
|
||||
|
||||
public static async getNotificationWindowPosition() {
|
||||
const userPreferences = await db.get<string, UserPreferences>(
|
||||
levelKeys.userPreferences,
|
||||
{
|
||||
valueEncoding: "json",
|
||||
}
|
||||
);
|
||||
private static readonly NOTIFICATION_WINDOW_WIDTH = 360;
|
||||
private static readonly NOTIFICATION_WINDOW_HEIGHT = 140;
|
||||
|
||||
private static async getNotificationWindowPosition(
|
||||
position: AchievementCustomNotificationPosition | undefined
|
||||
) {
|
||||
const display = screen.getPrimaryDisplay();
|
||||
const { width, height } = display.workAreaSize;
|
||||
|
||||
if (
|
||||
userPreferences?.achievementCustomNotificationPosition === "bottom_center"
|
||||
) {
|
||||
if (position === "bottom_center") {
|
||||
return {
|
||||
x: (width - this.NOTIFICATION_WINDOW_WIDTH) / 2,
|
||||
y: height - this.NOTIFICATION_WINDOW_HEIGHT,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
userPreferences?.achievementCustomNotificationPosition === "bottom_right"
|
||||
) {
|
||||
if (position === "bottom_right") {
|
||||
return {
|
||||
x: width - this.NOTIFICATION_WINDOW_WIDTH,
|
||||
y: height - this.NOTIFICATION_WINDOW_HEIGHT,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
userPreferences?.achievementCustomNotificationPosition === "top_center"
|
||||
) {
|
||||
if (position === "top_center") {
|
||||
return {
|
||||
x: (width - this.NOTIFICATION_WINDOW_WIDTH) / 2,
|
||||
y: 0,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
userPreferences?.achievementCustomNotificationPosition === "bottom_left"
|
||||
) {
|
||||
if (position === "bottom_left") {
|
||||
return {
|
||||
x: 0,
|
||||
y: height - this.NOTIFICATION_WINDOW_HEIGHT,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
userPreferences?.achievementCustomNotificationPosition === "top_right"
|
||||
) {
|
||||
if (position === "top_right") {
|
||||
return {
|
||||
x: width - this.NOTIFICATION_WINDOW_WIDTH,
|
||||
y: 0,
|
||||
@@ -341,8 +330,16 @@ export class WindowManager {
|
||||
};
|
||||
}
|
||||
|
||||
public static async createNotificationWindow() {
|
||||
const { x, y } = await this.getNotificationWindowPosition();
|
||||
public static async createNotificationWindow(showTestNotification = false) {
|
||||
const userPreferences = await db.get<string, UserPreferences>(
|
||||
levelKeys.userPreferences,
|
||||
{
|
||||
valueEncoding: "json",
|
||||
}
|
||||
);
|
||||
const { x, y } = await this.getNotificationWindowPosition(
|
||||
userPreferences.achievementCustomNotificationPosition
|
||||
);
|
||||
|
||||
this.notificationWindow = new BrowserWindow({
|
||||
transparent: true,
|
||||
@@ -372,9 +369,25 @@ export class WindowManager {
|
||||
if (isStaging) {
|
||||
this.notificationWindow?.webContents.openDevTools();
|
||||
}
|
||||
|
||||
if (showTestNotification) {
|
||||
setTimeout(() => {
|
||||
this.notificationWindow?.webContents.send(
|
||||
"on-test-achievement-notification",
|
||||
userPreferences.achievementCustomNotificationPosition ?? "top_left"
|
||||
);
|
||||
}, 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static async closeNotificationWindow() {
|
||||
if (this.notificationWindow) {
|
||||
this.notificationWindow.close();
|
||||
this.notificationWindow = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static openEditorWindow(themeId: string) {
|
||||
if (this.mainWindow) {
|
||||
const existingWindow = this.editorWindows.get(themeId);
|
||||
|
||||
Reference in New Issue
Block a user