mirror of
https://github.com/hydralauncher/hydra.git
synced 2025-01-23 05:24:55 +03:00
Merge pull request #1302 from hydralauncher/feat/hidden-achievement-description
feat: add description option for hidden achievements
This commit is contained in:
commit
ce2cf89fd6
@ -258,7 +258,8 @@
|
||||
"user_unblocked": "User has been unblocked",
|
||||
"enable_achievement_notifications": "When an achievement is unlocked",
|
||||
"launch_minimized": "Launch Hydra minimized",
|
||||
"disable_nsfw_alert": "Disable NSFW alert"
|
||||
"disable_nsfw_alert": "Disable NSFW alert",
|
||||
"show_hidden_achievement_description": "Show hidden achievements description before unlocking them"
|
||||
},
|
||||
"notifications": {
|
||||
"download_complete": "Download complete",
|
||||
|
@ -254,7 +254,8 @@
|
||||
"user_unblocked": "Usuário desbloqueado",
|
||||
"enable_achievement_notifications": "Quando uma conquista é desbloqueada",
|
||||
"launch_minimized": "Iniciar o Hydra minimizado",
|
||||
"disable_nsfw_alert": "Desativar alerta de conteúdo inapropriado"
|
||||
"disable_nsfw_alert": "Desativar alerta de conteúdo inapropriado",
|
||||
"show_hidden_achievement_description": "Mostrar descrição de conquistas ocultas antes de debloqueá-las"
|
||||
},
|
||||
"notifications": {
|
||||
"download_complete": "Download concluído",
|
||||
|
@ -41,6 +41,9 @@ export class UserPreferences {
|
||||
@Column("boolean", { default: false })
|
||||
disableNsfwAlert: boolean;
|
||||
|
||||
@Column("boolean", { default: false })
|
||||
showHiddenAchievementsDescription: boolean;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdAt: Date;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { registerEvent } from "../register-event";
|
||||
import type { StartGameDownloadPayload } from "@types";
|
||||
import { DownloadManager, HydraApi, logger } from "@main/services";
|
||||
import { DownloadManager, HydraApi } from "@main/services";
|
||||
|
||||
import { Not } from "typeorm";
|
||||
import { steamGamesWorker } from "@main/workers";
|
||||
@ -76,8 +76,14 @@ const startGameDownload = async (
|
||||
},
|
||||
});
|
||||
|
||||
createGame(updatedGame!).catch(() => {});
|
||||
await DownloadManager.cancelDownload(updatedGame!.id);
|
||||
await DownloadManager.startDownload(updatedGame!);
|
||||
|
||||
await downloadQueueRepository.delete({ game: { id: updatedGame!.id } });
|
||||
await downloadQueueRepository.insert({ game: { id: updatedGame!.id } });
|
||||
|
||||
await Promise.all([
|
||||
createGame(updatedGame!).catch(() => {}),
|
||||
HydraApi.post(
|
||||
"/games/download",
|
||||
{
|
||||
@ -85,15 +91,8 @@ const startGameDownload = async (
|
||||
shop: updatedGame!.shop,
|
||||
},
|
||||
{ needsAuth: false }
|
||||
).catch((err) => {
|
||||
logger.error("Failed to create game download", err);
|
||||
});
|
||||
|
||||
await DownloadManager.cancelDownload(updatedGame!.id);
|
||||
await DownloadManager.startDownload(updatedGame!);
|
||||
|
||||
await downloadQueueRepository.delete({ game: { id: updatedGame!.id } });
|
||||
await downloadQueueRepository.insert({ game: { id: updatedGame!.id } });
|
||||
).catch(() => {}),
|
||||
]);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
import type { GameShop, UnlockedAchievement, UserAchievement } from "@types";
|
||||
import { registerEvent } from "../register-event";
|
||||
import { gameAchievementRepository } from "@main/repository";
|
||||
import {
|
||||
gameAchievementRepository,
|
||||
userPreferencesRepository,
|
||||
} from "@main/repository";
|
||||
import { getGameAchievementData } from "@main/services/achievements/get-game-achievement-data";
|
||||
|
||||
export const getUnlockedAchievements = async (
|
||||
@ -12,10 +15,17 @@ export const getUnlockedAchievements = async (
|
||||
where: { objectId, shop },
|
||||
});
|
||||
|
||||
const userPreferences = await userPreferencesRepository.findOne({
|
||||
where: { id: 1 },
|
||||
});
|
||||
|
||||
const showHiddenAchievementsDescription =
|
||||
userPreferences?.showHiddenAchievementsDescription || false;
|
||||
|
||||
const achievementsData = await getGameAchievementData(
|
||||
objectId,
|
||||
shop,
|
||||
useCachedData
|
||||
useCachedData ? cachedAchievements : null
|
||||
);
|
||||
|
||||
const unlockedAchievements = JSON.parse(
|
||||
@ -50,6 +60,10 @@ export const getUnlockedAchievements = async (
|
||||
unlocked: false,
|
||||
unlockTime: null,
|
||||
icongray: icongray,
|
||||
description:
|
||||
!achievementData.hidden || showHiddenAchievementsDescription
|
||||
? achievementData.description
|
||||
: undefined,
|
||||
} as UserAchievement;
|
||||
})
|
||||
.sort((a, b) => {
|
||||
|
@ -13,6 +13,8 @@ import { AddBackgroundImageUrl } from "./migrations/20241016100249_add_backgroun
|
||||
import { AddWinePrefixToGame } from "./migrations/20241019081648_add_wine_prefix_to_game";
|
||||
import { AddStartMinimizedColumn } from "./migrations/20241030171454_add_start_minimized_column";
|
||||
import { AddDisableNsfwAlertColumn } from "./migrations/20241106053733_add_disable_nsfw_alert_column";
|
||||
import { AddHiddenAchievementDescriptionColumn } from "./migrations/20241216140633_add_hidden_achievement_description_column ";
|
||||
|
||||
export type HydraMigration = Knex.Migration & { name: string };
|
||||
|
||||
class MigrationSource implements Knex.MigrationSource<HydraMigration> {
|
||||
@ -30,6 +32,7 @@ class MigrationSource implements Knex.MigrationSource<HydraMigration> {
|
||||
AddWinePrefixToGame,
|
||||
AddStartMinimizedColumn,
|
||||
AddDisableNsfwAlertColumn,
|
||||
AddHiddenAchievementDescriptionColumn,
|
||||
]);
|
||||
}
|
||||
getMigrationName(migration: HydraMigration): string {
|
||||
|
@ -0,0 +1,20 @@
|
||||
import type { HydraMigration } from "@main/knex-client";
|
||||
import type { Knex } from "knex";
|
||||
|
||||
export const AddHiddenAchievementDescriptionColumn: HydraMigration = {
|
||||
name: "AddHiddenAchievementDescriptionColumn",
|
||||
up: (knex: Knex) => {
|
||||
return knex.schema.alterTable("user_preferences", (table) => {
|
||||
return table
|
||||
.boolean("showHiddenAchievementsDescription")
|
||||
.notNullable()
|
||||
.defaultTo(0);
|
||||
});
|
||||
},
|
||||
|
||||
down: async (knex: Knex) => {
|
||||
return knex.schema.alterTable("user_preferences", (table) => {
|
||||
return table.dropColumn("showHiddenAchievementsDescription");
|
||||
});
|
||||
},
|
||||
};
|
@ -1,40 +0,0 @@
|
||||
import path from "node:path";
|
||||
import fs from "node:fs";
|
||||
|
||||
import { getSteamGameClientIcon, logger } from "@main/services";
|
||||
import { chunk } from "lodash-es";
|
||||
import { seedsPath } from "@main/constants";
|
||||
|
||||
import type { SteamGame } from "@types";
|
||||
|
||||
const steamGamesPath = path.join(seedsPath, "steam-games.json");
|
||||
|
||||
const steamGames = JSON.parse(
|
||||
fs.readFileSync(steamGamesPath, "utf-8")
|
||||
) as SteamGame[];
|
||||
|
||||
const chunks = chunk(steamGames, 1500);
|
||||
|
||||
for (const chunk of chunks) {
|
||||
await Promise.all(
|
||||
chunk.map(async (steamGame) => {
|
||||
if (steamGame.clientIcon) return;
|
||||
|
||||
const index = steamGames.findIndex((game) => game.id === steamGame.id);
|
||||
|
||||
try {
|
||||
const clientIcon = await getSteamGameClientIcon(String(steamGame.id));
|
||||
|
||||
steamGames[index].clientIcon = clientIcon;
|
||||
|
||||
logger.log("info", `Set ${steamGame.name} client icon`);
|
||||
} catch (err) {
|
||||
steamGames[index].clientIcon = null;
|
||||
logger.log("info", `Could not set icon for ${steamGame.name}`);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
fs.writeFileSync(steamGamesPath, JSON.stringify(steamGames));
|
||||
logger.log("info", "Updated steam games");
|
||||
}
|
@ -6,21 +6,16 @@ import { HydraApi } from "../hydra-api";
|
||||
import type { AchievementData, GameShop } from "@types";
|
||||
import { UserNotLoggedInError } from "@shared";
|
||||
import { logger } from "../logger";
|
||||
import { GameAchievement } from "@main/entity";
|
||||
|
||||
export const getGameAchievementData = async (
|
||||
objectId: string,
|
||||
shop: GameShop,
|
||||
useCachedData: boolean
|
||||
cachedAchievements: GameAchievement | null
|
||||
) => {
|
||||
if (useCachedData) {
|
||||
const cachedAchievements = await gameAchievementRepository.findOne({
|
||||
where: { objectId, shop },
|
||||
});
|
||||
|
||||
if (cachedAchievements && cachedAchievements.achievements) {
|
||||
return JSON.parse(cachedAchievements.achievements) as AchievementData[];
|
||||
}
|
||||
}
|
||||
|
||||
const userPreferences = await userPreferencesRepository.findOne({
|
||||
where: { id: 1 },
|
||||
|
@ -1,7 +1,6 @@
|
||||
export * from "./logger";
|
||||
export * from "./steam";
|
||||
export * from "./steam-250";
|
||||
export * from "./steam-grid";
|
||||
export * from "./window-manager";
|
||||
export * from "./download";
|
||||
export * from "./process-watcher";
|
||||
|
@ -1,69 +0,0 @@
|
||||
import type { GameShop } from "@types";
|
||||
import axios from "axios";
|
||||
|
||||
export interface SteamGridResponse {
|
||||
success: boolean;
|
||||
data: {
|
||||
id: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SteamGridGameResponse {
|
||||
data: {
|
||||
platforms: {
|
||||
steam: {
|
||||
metadata: {
|
||||
clienticon: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export const getSteamGridData = async (
|
||||
objectId: string,
|
||||
path: string,
|
||||
shop: GameShop,
|
||||
params: Record<string, string> = {}
|
||||
): Promise<SteamGridResponse> => {
|
||||
const searchParams = new URLSearchParams(params);
|
||||
|
||||
if (!import.meta.env.MAIN_VITE_STEAMGRIDDB_API_KEY) {
|
||||
throw new Error("MAIN_VITE_STEAMGRIDDB_API_KEY is not set");
|
||||
}
|
||||
|
||||
const response = await axios.get(
|
||||
`https://www.steamgriddb.com/api/v2/${path}/${shop}/${objectId}?${searchParams.toString()}`,
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${import.meta.env.MAIN_VITE_STEAMGRIDDB_API_KEY}`,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getSteamGridGameById = async (
|
||||
id: number
|
||||
): Promise<SteamGridGameResponse> => {
|
||||
const response = await axios.get(
|
||||
`https://www.steamgriddb.com/api/public/game/${id}`,
|
||||
{
|
||||
headers: {
|
||||
Referer: "https://www.steamgriddb.com/",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
return response.data;
|
||||
};
|
||||
|
||||
export const getSteamGameClientIcon = async (objectId: string) => {
|
||||
const {
|
||||
data: { id: steamGridGameId },
|
||||
} = await getSteamGridData(objectId, "games", "steam");
|
||||
|
||||
const steamGridGame = await getSteamGridGameById(steamGridGameId);
|
||||
return steamGridGame.data.platforms.steam.metadata.clienticon;
|
||||
};
|
@ -11,10 +11,10 @@ import type {
|
||||
GameRunning,
|
||||
FriendRequestAction,
|
||||
UpdateProfileRequest,
|
||||
GameAchievement,
|
||||
} from "@types";
|
||||
import type { CatalogueCategory } from "@shared";
|
||||
import type { AxiosProgressEvent } from "axios";
|
||||
import { GameAchievement } from "@main/entity";
|
||||
|
||||
contextBridge.exposeInMainWorld("electron", {
|
||||
/* Torrenting */
|
||||
|
@ -19,6 +19,7 @@ export function SettingsBehavior() {
|
||||
runAtStartup: false,
|
||||
startMinimized: false,
|
||||
disableNsfwAlert: false,
|
||||
showHiddenAchievementsDescription: false,
|
||||
});
|
||||
|
||||
const { t } = useTranslation("settings");
|
||||
@ -30,6 +31,8 @@ export function SettingsBehavior() {
|
||||
runAtStartup: userPreferences.runAtStartup,
|
||||
startMinimized: userPreferences.startMinimized,
|
||||
disableNsfwAlert: userPreferences.disableNsfwAlert,
|
||||
showHiddenAchievementsDescription:
|
||||
userPreferences.showHiddenAchievementsDescription,
|
||||
});
|
||||
}
|
||||
}, [userPreferences]);
|
||||
@ -96,6 +99,17 @@ export function SettingsBehavior() {
|
||||
handleChange({ disableNsfwAlert: !form.disableNsfwAlert })
|
||||
}
|
||||
/>
|
||||
|
||||
<CheckboxField
|
||||
label={t("show_hidden_achievement_description")}
|
||||
checked={form.showHiddenAchievementsDescription}
|
||||
onChange={() =>
|
||||
handleChange({
|
||||
showHiddenAchievementsDescription:
|
||||
!form.showHiddenAchievementsDescription,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -162,6 +162,7 @@ export interface UserPreferences {
|
||||
runAtStartup: boolean;
|
||||
startMinimized: boolean;
|
||||
disableNsfwAlert: boolean;
|
||||
showHiddenAchievementsDescription: boolean;
|
||||
}
|
||||
|
||||
export interface Steam250Game {
|
||||
|
Loading…
Reference in New Issue
Block a user