mirror of
https://github.com/hydralauncher/hydra.git
synced 2026-01-30 22:31:03 +00:00
Merge pull request #1795 from hydralauncher/feat/revert-title-and-cleanup-fix
Fix: Playtime font size and original path in edit game modal fix
This commit is contained in:
@@ -4,15 +4,33 @@ import type { GameShop } from "@types";
|
|||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
import { logger } from "@main/services";
|
import { logger } from "@main/services";
|
||||||
|
|
||||||
|
interface UpdateCustomGameParams {
|
||||||
|
shop: GameShop;
|
||||||
|
objectId: string;
|
||||||
|
title: string;
|
||||||
|
iconUrl?: string;
|
||||||
|
logoImageUrl?: string;
|
||||||
|
libraryHeroImageUrl?: string;
|
||||||
|
originalIconPath?: string;
|
||||||
|
originalLogoPath?: string;
|
||||||
|
originalHeroPath?: string;
|
||||||
|
}
|
||||||
|
|
||||||
const updateCustomGame = async (
|
const updateCustomGame = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
shop: GameShop,
|
params: UpdateCustomGameParams
|
||||||
objectId: string,
|
|
||||||
title: string,
|
|
||||||
iconUrl?: string,
|
|
||||||
logoImageUrl?: string,
|
|
||||||
libraryHeroImageUrl?: string
|
|
||||||
) => {
|
) => {
|
||||||
|
const {
|
||||||
|
shop,
|
||||||
|
objectId,
|
||||||
|
title,
|
||||||
|
iconUrl,
|
||||||
|
logoImageUrl,
|
||||||
|
libraryHeroImageUrl,
|
||||||
|
originalIconPath,
|
||||||
|
originalLogoPath,
|
||||||
|
originalHeroPath,
|
||||||
|
} = params;
|
||||||
const gameKey = levelKeys.game(shop, objectId);
|
const gameKey = levelKeys.game(shop, objectId);
|
||||||
|
|
||||||
const existingGame = await gamesSublevel.get(gameKey);
|
const existingGame = await gamesSublevel.get(gameKey);
|
||||||
@@ -40,6 +58,9 @@ const updateCustomGame = async (
|
|||||||
iconUrl: iconUrl || null,
|
iconUrl: iconUrl || null,
|
||||||
logoImageUrl: logoImageUrl || null,
|
logoImageUrl: logoImageUrl || null,
|
||||||
libraryHeroImageUrl: libraryHeroImageUrl || null,
|
libraryHeroImageUrl: libraryHeroImageUrl || null,
|
||||||
|
originalIconPath: originalIconPath || existingGame.originalIconPath || null,
|
||||||
|
originalLogoPath: originalLogoPath || existingGame.originalLogoPath || null,
|
||||||
|
originalHeroPath: originalHeroPath || existingGame.originalHeroPath || null,
|
||||||
};
|
};
|
||||||
|
|
||||||
await gamesSublevel.put(gameKey, updatedGame);
|
await gamesSublevel.put(gameKey, updatedGame);
|
||||||
|
|||||||
@@ -32,20 +32,39 @@ const collectOldAssetPaths = (
|
|||||||
return oldAssetPaths;
|
return oldAssetPaths;
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateGameData = async (
|
interface UpdateGameDataParams {
|
||||||
gameKey: string,
|
gameKey: string;
|
||||||
existingGame: Game,
|
existingGame: Game;
|
||||||
title: string,
|
title: string;
|
||||||
customIconUrl?: string | null,
|
customIconUrl?: string | null;
|
||||||
customLogoImageUrl?: string | null,
|
customLogoImageUrl?: string | null;
|
||||||
customHeroImageUrl?: string | null
|
customHeroImageUrl?: string | null;
|
||||||
): Promise<Game> => {
|
customOriginalIconPath?: string | null;
|
||||||
|
customOriginalLogoPath?: string | null;
|
||||||
|
customOriginalHeroPath?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateGameData = async (params: UpdateGameDataParams): Promise<Game> => {
|
||||||
|
const {
|
||||||
|
gameKey,
|
||||||
|
existingGame,
|
||||||
|
title,
|
||||||
|
customIconUrl,
|
||||||
|
customLogoImageUrl,
|
||||||
|
customHeroImageUrl,
|
||||||
|
customOriginalIconPath,
|
||||||
|
customOriginalLogoPath,
|
||||||
|
customOriginalHeroPath,
|
||||||
|
} = params;
|
||||||
const updatedGame = {
|
const updatedGame = {
|
||||||
...existingGame,
|
...existingGame,
|
||||||
title,
|
title,
|
||||||
...(customIconUrl !== undefined && { customIconUrl }),
|
...(customIconUrl !== undefined && { customIconUrl }),
|
||||||
...(customLogoImageUrl !== undefined && { customLogoImageUrl }),
|
...(customLogoImageUrl !== undefined && { customLogoImageUrl }),
|
||||||
...(customHeroImageUrl !== undefined && { customHeroImageUrl }),
|
...(customHeroImageUrl !== undefined && { customHeroImageUrl }),
|
||||||
|
...(customOriginalIconPath !== undefined && { customOriginalIconPath }),
|
||||||
|
...(customOriginalLogoPath !== undefined && { customOriginalLogoPath }),
|
||||||
|
...(customOriginalHeroPath !== undefined && { customOriginalHeroPath }),
|
||||||
};
|
};
|
||||||
|
|
||||||
await gamesSublevel.put(gameKey, updatedGame);
|
await gamesSublevel.put(gameKey, updatedGame);
|
||||||
@@ -80,15 +99,33 @@ const deleteOldAssetFiles = async (oldAssetPaths: string[]): Promise<void> => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface UpdateGameCustomAssetsParams {
|
||||||
|
shop: GameShop;
|
||||||
|
objectId: string;
|
||||||
|
title: string;
|
||||||
|
customIconUrl?: string | null;
|
||||||
|
customLogoImageUrl?: string | null;
|
||||||
|
customHeroImageUrl?: string | null;
|
||||||
|
customOriginalIconPath?: string | null;
|
||||||
|
customOriginalLogoPath?: string | null;
|
||||||
|
customOriginalHeroPath?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
const updateGameCustomAssets = async (
|
const updateGameCustomAssets = async (
|
||||||
_event: Electron.IpcMainInvokeEvent,
|
_event: Electron.IpcMainInvokeEvent,
|
||||||
shop: GameShop,
|
params: UpdateGameCustomAssetsParams
|
||||||
objectId: string,
|
|
||||||
title: string,
|
|
||||||
customIconUrl?: string | null,
|
|
||||||
customLogoImageUrl?: string | null,
|
|
||||||
customHeroImageUrl?: string | null
|
|
||||||
) => {
|
) => {
|
||||||
|
const {
|
||||||
|
shop,
|
||||||
|
objectId,
|
||||||
|
title,
|
||||||
|
customIconUrl,
|
||||||
|
customLogoImageUrl,
|
||||||
|
customHeroImageUrl,
|
||||||
|
customOriginalIconPath,
|
||||||
|
customOriginalLogoPath,
|
||||||
|
customOriginalHeroPath,
|
||||||
|
} = params;
|
||||||
const gameKey = levelKeys.game(shop, objectId);
|
const gameKey = levelKeys.game(shop, objectId);
|
||||||
|
|
||||||
const existingGame = await gamesSublevel.get(gameKey);
|
const existingGame = await gamesSublevel.get(gameKey);
|
||||||
@@ -103,14 +140,17 @@ const updateGameCustomAssets = async (
|
|||||||
customHeroImageUrl
|
customHeroImageUrl
|
||||||
);
|
);
|
||||||
|
|
||||||
const updatedGame = await updateGameData(
|
const updatedGame = await updateGameData({
|
||||||
gameKey,
|
gameKey,
|
||||||
existingGame,
|
existingGame,
|
||||||
title,
|
title,
|
||||||
customIconUrl,
|
customIconUrl,
|
||||||
customLogoImageUrl,
|
customLogoImageUrl,
|
||||||
customHeroImageUrl
|
customHeroImageUrl,
|
||||||
);
|
customOriginalIconPath,
|
||||||
|
customOriginalLogoPath,
|
||||||
|
customOriginalHeroPath,
|
||||||
|
});
|
||||||
|
|
||||||
await updateShopAssets(gameKey, title);
|
await updateShopAssets(gameKey, title);
|
||||||
|
|
||||||
|
|||||||
@@ -152,40 +152,28 @@ contextBridge.exposeInMainWorld("electron", {
|
|||||||
deleteTempFile: (filePath: string) =>
|
deleteTempFile: (filePath: string) =>
|
||||||
ipcRenderer.invoke("deleteTempFile", filePath),
|
ipcRenderer.invoke("deleteTempFile", filePath),
|
||||||
cleanupUnusedAssets: () => ipcRenderer.invoke("cleanupUnusedAssets"),
|
cleanupUnusedAssets: () => ipcRenderer.invoke("cleanupUnusedAssets"),
|
||||||
updateCustomGame: (
|
updateCustomGame: (params: {
|
||||||
shop: GameShop,
|
shop: GameShop;
|
||||||
objectId: string,
|
objectId: string;
|
||||||
title: string,
|
title: string;
|
||||||
iconUrl?: string,
|
iconUrl?: string;
|
||||||
logoImageUrl?: string,
|
logoImageUrl?: string;
|
||||||
libraryHeroImageUrl?: string
|
libraryHeroImageUrl?: string;
|
||||||
) =>
|
originalIconPath?: string;
|
||||||
ipcRenderer.invoke(
|
originalLogoPath?: string;
|
||||||
"updateCustomGame",
|
originalHeroPath?: string;
|
||||||
shop,
|
}) => ipcRenderer.invoke("updateCustomGame", params),
|
||||||
objectId,
|
updateGameCustomAssets: (params: {
|
||||||
title,
|
shop: GameShop;
|
||||||
iconUrl,
|
objectId: string;
|
||||||
logoImageUrl,
|
title: string;
|
||||||
libraryHeroImageUrl
|
customIconUrl?: string | null;
|
||||||
),
|
customLogoImageUrl?: string | null;
|
||||||
updateGameCustomAssets: (
|
customHeroImageUrl?: string | null;
|
||||||
shop: GameShop,
|
customOriginalIconPath?: string | null;
|
||||||
objectId: string,
|
customOriginalLogoPath?: string | null;
|
||||||
title: string,
|
customOriginalHeroPath?: string | null;
|
||||||
customIconUrl?: string | null,
|
}) => ipcRenderer.invoke("updateGameCustomAssets", params),
|
||||||
customLogoImageUrl?: string | null,
|
|
||||||
customHeroImageUrl?: string | null
|
|
||||||
) =>
|
|
||||||
ipcRenderer.invoke(
|
|
||||||
"updateGameCustomAssets",
|
|
||||||
shop,
|
|
||||||
objectId,
|
|
||||||
title,
|
|
||||||
customIconUrl,
|
|
||||||
customLogoImageUrl,
|
|
||||||
customHeroImageUrl
|
|
||||||
),
|
|
||||||
createGameShortcut: (
|
createGameShortcut: (
|
||||||
shop: GameShop,
|
shop: GameShop,
|
||||||
objectId: string,
|
objectId: string,
|
||||||
|
|||||||
38
src/renderer/src/declaration.d.ts
vendored
38
src/renderer/src/declaration.d.ts
vendored
@@ -119,14 +119,17 @@ declare global {
|
|||||||
logoImageUrl?: string,
|
logoImageUrl?: string,
|
||||||
libraryHeroImageUrl?: string
|
libraryHeroImageUrl?: string
|
||||||
) => Promise<Game>;
|
) => Promise<Game>;
|
||||||
updateCustomGame: (
|
updateCustomGame: (params: {
|
||||||
shop: GameShop,
|
shop: GameShop;
|
||||||
objectId: string,
|
objectId: string;
|
||||||
title: string,
|
title: string;
|
||||||
iconUrl?: string,
|
iconUrl?: string;
|
||||||
logoImageUrl?: string,
|
logoImageUrl?: string;
|
||||||
libraryHeroImageUrl?: string
|
libraryHeroImageUrl?: string;
|
||||||
) => Promise<Game>;
|
originalIconPath?: string;
|
||||||
|
originalLogoPath?: string;
|
||||||
|
originalHeroPath?: string;
|
||||||
|
}) => Promise<Game>;
|
||||||
copyCustomGameAsset: (
|
copyCustomGameAsset: (
|
||||||
sourcePath: string,
|
sourcePath: string,
|
||||||
assetType: "icon" | "logo" | "hero"
|
assetType: "icon" | "logo" | "hero"
|
||||||
@@ -135,14 +138,17 @@ declare global {
|
|||||||
deletedCount: number;
|
deletedCount: number;
|
||||||
errors: string[];
|
errors: string[];
|
||||||
}>;
|
}>;
|
||||||
updateGameCustomAssets: (
|
updateGameCustomAssets: (params: {
|
||||||
shop: GameShop,
|
shop: GameShop;
|
||||||
objectId: string,
|
objectId: string;
|
||||||
title: string,
|
title: string;
|
||||||
customIconUrl?: string | null,
|
customIconUrl?: string | null;
|
||||||
customLogoImageUrl?: string | null,
|
customLogoImageUrl?: string | null;
|
||||||
customHeroImageUrl?: string | null
|
customHeroImageUrl?: string | null;
|
||||||
) => Promise<Game>;
|
customOriginalIconPath?: string | null;
|
||||||
|
customOriginalLogoPath?: string | null;
|
||||||
|
customOriginalHeroPath?: string | null;
|
||||||
|
}) => Promise<Game>;
|
||||||
createGameShortcut: (
|
createGameShortcut: (
|
||||||
shop: GameShop,
|
shop: GameShop,
|
||||||
objectId: string,
|
objectId: string,
|
||||||
|
|||||||
@@ -39,6 +39,11 @@ export function EditGameModal({
|
|||||||
logo: "",
|
logo: "",
|
||||||
hero: "",
|
hero: "",
|
||||||
});
|
});
|
||||||
|
const [originalAssetPaths, setOriginalAssetPaths] = useState({
|
||||||
|
icon: "",
|
||||||
|
logo: "",
|
||||||
|
hero: "",
|
||||||
|
});
|
||||||
const [defaultUrls, setDefaultUrls] = useState({
|
const [defaultUrls, setDefaultUrls] = useState({
|
||||||
icon: null as string | null,
|
icon: null as string | null,
|
||||||
logo: null as string | null,
|
logo: null as string | null,
|
||||||
@@ -66,6 +71,14 @@ export function EditGameModal({
|
|||||||
logo: extractLocalPath(game.logoImageUrl),
|
logo: extractLocalPath(game.logoImageUrl),
|
||||||
hero: extractLocalPath(game.libraryHeroImageUrl),
|
hero: extractLocalPath(game.libraryHeroImageUrl),
|
||||||
});
|
});
|
||||||
|
setOriginalAssetPaths({
|
||||||
|
icon: (game as any).originalIconPath || extractLocalPath(game.iconUrl),
|
||||||
|
logo:
|
||||||
|
(game as any).originalLogoPath || extractLocalPath(game.logoImageUrl),
|
||||||
|
hero:
|
||||||
|
(game as any).originalHeroPath ||
|
||||||
|
extractLocalPath(game.libraryHeroImageUrl),
|
||||||
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const setNonCustomGameAssets = useCallback(
|
const setNonCustomGameAssets = useCallback(
|
||||||
@@ -80,11 +93,25 @@ export function EditGameModal({
|
|||||||
logo: extractLocalPath(game.customLogoImageUrl),
|
logo: extractLocalPath(game.customLogoImageUrl),
|
||||||
hero: extractLocalPath(game.customHeroImageUrl),
|
hero: extractLocalPath(game.customHeroImageUrl),
|
||||||
});
|
});
|
||||||
|
setOriginalAssetPaths({
|
||||||
|
icon:
|
||||||
|
(game as any).customOriginalIconPath ||
|
||||||
|
extractLocalPath(game.customIconUrl),
|
||||||
|
logo:
|
||||||
|
(game as any).customOriginalLogoPath ||
|
||||||
|
extractLocalPath(game.customLogoImageUrl),
|
||||||
|
hero:
|
||||||
|
(game as any).customOriginalHeroPath ||
|
||||||
|
extractLocalPath(game.customHeroImageUrl),
|
||||||
|
});
|
||||||
|
|
||||||
setDefaultUrls({
|
setDefaultUrls({
|
||||||
icon: shopDetails?.assets?.iconUrl || game.iconUrl || null,
|
icon: shopDetails?.assets?.iconUrl || game.iconUrl || null,
|
||||||
logo: shopDetails?.assets?.logoImageUrl || game.logoImageUrl || null,
|
logo: shopDetails?.assets?.logoImageUrl || game.logoImageUrl || null,
|
||||||
hero: shopDetails?.assets?.libraryHeroImageUrl || game.libraryHeroImageUrl || null,
|
hero:
|
||||||
|
shopDetails?.assets?.libraryHeroImageUrl ||
|
||||||
|
game.libraryHeroImageUrl ||
|
||||||
|
null,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
[shopDetails]
|
[shopDetails]
|
||||||
@@ -115,15 +142,16 @@ export function EditGameModal({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getAssetDisplayPath = (assetType: AssetType): string => {
|
const getAssetDisplayPath = (assetType: AssetType): string => {
|
||||||
return assetDisplayPaths[assetType];
|
// Use original path if available, otherwise fall back to display path
|
||||||
|
return originalAssetPaths[assetType] || assetDisplayPaths[assetType];
|
||||||
};
|
};
|
||||||
|
|
||||||
const setAssetPath = (assetType: AssetType, path: string): void => {
|
const setAssetPath = (assetType: AssetType, path: string): void => {
|
||||||
setAssetPaths(prev => ({ ...prev, [assetType]: path }));
|
setAssetPaths((prev) => ({ ...prev, [assetType]: path }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const setAssetDisplayPath = (assetType: AssetType, path: string): void => {
|
const setAssetDisplayPath = (assetType: AssetType, path: string): void => {
|
||||||
setAssetDisplayPaths(prev => ({ ...prev, [assetType]: path }));
|
setAssetDisplayPaths((prev) => ({ ...prev, [assetType]: path }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const getDefaultUrl = (assetType: AssetType): string | null => {
|
const getDefaultUrl = (assetType: AssetType): string | null => {
|
||||||
@@ -150,10 +178,19 @@ export function EditGameModal({
|
|||||||
);
|
);
|
||||||
setAssetPath(assetType, copiedAssetUrl.replace("local:", ""));
|
setAssetPath(assetType, copiedAssetUrl.replace("local:", ""));
|
||||||
setAssetDisplayPath(assetType, originalPath);
|
setAssetDisplayPath(assetType, originalPath);
|
||||||
|
// Store the original path for display purposes
|
||||||
|
setOriginalAssetPaths((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[assetType]: originalPath,
|
||||||
|
}));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`Failed to copy ${assetType} asset:`, error);
|
console.error(`Failed to copy ${assetType} asset:`, error);
|
||||||
setAssetPath(assetType, originalPath);
|
setAssetPath(assetType, originalPath);
|
||||||
setAssetDisplayPath(assetType, originalPath);
|
setAssetDisplayPath(assetType, originalPath);
|
||||||
|
setOriginalAssetPaths((prev) => ({
|
||||||
|
...prev,
|
||||||
|
[assetType]: originalPath,
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -161,6 +198,7 @@ export function EditGameModal({
|
|||||||
const handleRestoreDefault = (assetType: AssetType) => {
|
const handleRestoreDefault = (assetType: AssetType) => {
|
||||||
setAssetPath(assetType, "");
|
setAssetPath(assetType, "");
|
||||||
setAssetDisplayPath(assetType, "");
|
setAssetDisplayPath(assetType, "");
|
||||||
|
setOriginalAssetPaths((prev) => ({ ...prev, [assetType]: "" }));
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOriginalTitle = (): string => {
|
const getOriginalTitle = (): string => {
|
||||||
@@ -293,7 +331,9 @@ export function EditGameModal({
|
|||||||
// Helper function to prepare custom game assets
|
// Helper function to prepare custom game assets
|
||||||
const prepareCustomGameAssets = (game: LibraryGame | Game) => {
|
const prepareCustomGameAssets = (game: LibraryGame | Game) => {
|
||||||
const iconUrl = assetPaths.icon ? `local:${assetPaths.icon}` : game.iconUrl;
|
const iconUrl = assetPaths.icon ? `local:${assetPaths.icon}` : game.iconUrl;
|
||||||
const logoImageUrl = assetPaths.logo ? `local:${assetPaths.logo}` : game.logoImageUrl;
|
const logoImageUrl = assetPaths.logo
|
||||||
|
? `local:${assetPaths.logo}`
|
||||||
|
: game.logoImageUrl;
|
||||||
const libraryHeroImageUrl = assetPaths.hero
|
const libraryHeroImageUrl = assetPaths.hero
|
||||||
? `local:${assetPaths.hero}`
|
? `local:${assetPaths.hero}`
|
||||||
: game.libraryHeroImageUrl;
|
: game.libraryHeroImageUrl;
|
||||||
@@ -315,14 +355,17 @@ export function EditGameModal({
|
|||||||
const { iconUrl, logoImageUrl, libraryHeroImageUrl } =
|
const { iconUrl, logoImageUrl, libraryHeroImageUrl } =
|
||||||
prepareCustomGameAssets(game);
|
prepareCustomGameAssets(game);
|
||||||
|
|
||||||
return window.electron.updateCustomGame(
|
return window.electron.updateCustomGame({
|
||||||
game.shop,
|
shop: game.shop,
|
||||||
game.objectId,
|
objectId: game.objectId,
|
||||||
gameName.trim(),
|
title: gameName.trim(),
|
||||||
iconUrl || undefined,
|
iconUrl: iconUrl || undefined,
|
||||||
logoImageUrl || undefined,
|
logoImageUrl: logoImageUrl || undefined,
|
||||||
libraryHeroImageUrl || undefined
|
libraryHeroImageUrl: libraryHeroImageUrl || undefined,
|
||||||
);
|
originalIconPath: originalAssetPaths.icon || undefined,
|
||||||
|
originalLogoPath: originalAssetPaths.logo || undefined,
|
||||||
|
originalHeroPath: originalAssetPaths.hero || undefined,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper function to update non-custom game
|
// Helper function to update non-custom game
|
||||||
@@ -330,14 +373,17 @@ export function EditGameModal({
|
|||||||
const { customIconUrl, customLogoImageUrl, customHeroImageUrl } =
|
const { customIconUrl, customLogoImageUrl, customHeroImageUrl } =
|
||||||
prepareNonCustomGameAssets();
|
prepareNonCustomGameAssets();
|
||||||
|
|
||||||
return window.electron.updateGameCustomAssets(
|
return window.electron.updateGameCustomAssets({
|
||||||
game.shop,
|
shop: game.shop,
|
||||||
game.objectId,
|
objectId: game.objectId,
|
||||||
gameName.trim(),
|
title: gameName.trim(),
|
||||||
customIconUrl,
|
customIconUrl,
|
||||||
customLogoImageUrl,
|
customLogoImageUrl,
|
||||||
customHeroImageUrl
|
customHeroImageUrl,
|
||||||
);
|
customOriginalIconPath: originalAssetPaths.icon || undefined,
|
||||||
|
customOriginalLogoPath: originalAssetPaths.logo || undefined,
|
||||||
|
customOriginalHeroPath: originalAssetPaths.hero || undefined,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleUpdateGame = async () => {
|
const handleUpdateGame = async () => {
|
||||||
|
|||||||
@@ -164,10 +164,12 @@
|
|||||||
|
|
||||||
&-long {
|
&-long {
|
||||||
display: inline;
|
display: inline;
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&-short {
|
&-short {
|
||||||
display: none;
|
display: none;
|
||||||
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When the card is narrow (less than 180px), show short format
|
// When the card is narrow (less than 180px), show short format
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ export function UserLibraryGameCard({
|
|||||||
const [isTooltipHovered, setIsTooltipHovered] = useState(false);
|
const [isTooltipHovered, setIsTooltipHovered] = useState(false);
|
||||||
const [isPinning, setIsPinning] = useState(false);
|
const [isPinning, setIsPinning] = useState(false);
|
||||||
|
|
||||||
|
|
||||||
const getStatsItemCount = useCallback(() => {
|
const getStatsItemCount = useCallback(() => {
|
||||||
let statsCount = 1;
|
let statsCount = 1;
|
||||||
if (game.achievementsPointsEarnedSum > 0) statsCount++;
|
if (game.achievementsPointsEarnedSum > 0) statsCount++;
|
||||||
@@ -91,15 +90,15 @@ export function UserLibraryGameCard({
|
|||||||
|
|
||||||
const hours = minutes / 60;
|
const hours = minutes / 60;
|
||||||
const hoursKey = isShort ? "amount_hours_short" : "amount_hours";
|
const hoursKey = isShort ? "amount_hours_short" : "amount_hours";
|
||||||
const hoursAmount = isShort ? Math.floor(hours) : numberFormatter.format(hours);
|
const hoursAmount = isShort
|
||||||
|
? Math.floor(hours)
|
||||||
|
: numberFormatter.format(hours);
|
||||||
|
|
||||||
return t(hoursKey, { amount: hoursAmount });
|
return t(hoursKey, { amount: hoursAmount });
|
||||||
},
|
},
|
||||||
[numberFormatter, t]
|
[numberFormatter, t]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const toggleGamePinned = async () => {
|
const toggleGamePinned = async () => {
|
||||||
setIsPinning(true);
|
setIsPinning(true);
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,12 @@ export interface Game {
|
|||||||
customIconUrl?: string | null;
|
customIconUrl?: string | null;
|
||||||
customLogoImageUrl?: string | null;
|
customLogoImageUrl?: string | null;
|
||||||
customHeroImageUrl?: string | null;
|
customHeroImageUrl?: string | null;
|
||||||
|
originalIconPath?: string | null;
|
||||||
|
originalLogoPath?: string | null;
|
||||||
|
originalHeroPath?: string | null;
|
||||||
|
customOriginalIconPath?: string | null;
|
||||||
|
customOriginalLogoPath?: string | null;
|
||||||
|
customOriginalHeroPath?: string | null;
|
||||||
playTimeInMilliseconds: number;
|
playTimeInMilliseconds: number;
|
||||||
unsyncedDeltaPlayTimeInMilliseconds?: number;
|
unsyncedDeltaPlayTimeInMilliseconds?: number;
|
||||||
lastTimePlayed: Date | null;
|
lastTimePlayed: Date | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user