Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/locales/de/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@
"edit_game_modal_hero": "Library Hero",
"edit_game_modal_select_hero": "Select library hero image",
"edit_game_modal_hero_preview": "Library hero image preview",
"edit_game_modal_cover": "Cover",
"edit_game_modal_select_cover": "Select library cover image",
"edit_game_modal_cover_preview": "Cover image preview",
"edit_game_modal_cancel": "Cancel",
"edit_game_modal_update": "Update",
"edit_game_modal_updating": "Updating...",
Expand All @@ -91,13 +94,16 @@
"edit_game_modal_icon_resolution": "Recommended resolution: 256x256px",
"edit_game_modal_logo_resolution": "Recommended resolution: 640x360px",
"edit_game_modal_hero_resolution": "Recommended resolution: 1920x620px",
"edit_game_modal_cover_resolution": "Recommended resolution: 600x900px",
"edit_game_modal_assets": "Assets",
"edit_game_modal_drop_icon_image_here": "Drop icon image here",
"edit_game_modal_drop_logo_image_here": "Drop logo image here",
"edit_game_modal_drop_hero_image_here": "Drop hero image here",
"edit_game_modal_drop_cover_image_here": "Drop cover image here",
"edit_game_modal_drop_to_replace_icon": "Drop to replace icon",
"edit_game_modal_drop_to_replace_logo": "Drop to replace logo",
"edit_game_modal_drop_to_replace_hero": "Drop to replace hero",
"edit_game_modal_drop_to_replace_cover": "Drop to replace cover",
"install_decky_plugin": "Install Decky Plugin",
"update_decky_plugin": "Update Decky Plugin",
"decky_plugin_installed_version": "Decky Plugin (v{{version}})",
Expand Down
6 changes: 6 additions & 0 deletions src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,9 @@
"edit_game_modal_hero": "Library Hero",
"edit_game_modal_select_hero": "Select library hero image",
"edit_game_modal_hero_preview": "Library hero image preview",
"edit_game_modal_cover": "Cover",
"edit_game_modal_select_cover": "Select library cover image",
"edit_game_modal_cover_preview": "Cover image preview",
"edit_game_modal_cancel": "Cancel",
"edit_game_modal_update": "Update",
"edit_game_modal_updating": "Updating...",
Expand All @@ -91,13 +94,16 @@
"edit_game_modal_icon_resolution": "Recommended resolution: 256x256px",
"edit_game_modal_logo_resolution": "Recommended resolution: 640x360px",
"edit_game_modal_hero_resolution": "Recommended resolution: 1920x620px",
"edit_game_modal_cover_resolution": "Recommended resolution: 600x900px",
"edit_game_modal_assets": "Assets",
"edit_game_modal_drop_icon_image_here": "Drop icon image here",
"edit_game_modal_drop_logo_image_here": "Drop logo image here",
"edit_game_modal_drop_hero_image_here": "Drop hero image here",
"edit_game_modal_drop_cover_image_here": "Drop cover image here",
"edit_game_modal_drop_to_replace_icon": "Drop to replace icon",
"edit_game_modal_drop_to_replace_logo": "Drop to replace logo",
"edit_game_modal_drop_to_replace_hero": "Drop to replace hero",
"edit_game_modal_drop_to_replace_cover": "Drop to replace cover",
"install_decky_plugin": "Install Decky Plugin",
"update_decky_plugin": "Update Decky Plugin",
"decky_plugin_installed_version": "Decky Plugin (v{{version}})",
Expand Down
6 changes: 4 additions & 2 deletions src/main/events/library/add-custom-game-to-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const addCustomGameToLibrary = async (
executablePath: string,
iconUrl?: string,
logoImageUrl?: string,
libraryHeroImageUrl?: string
libraryHeroImageUrl?: string,
coverImageUrl?: string
) => {
const objectId = randomUUID();
const shop: GameShop = "custom";
Expand All @@ -36,7 +37,7 @@ const addCustomGameToLibrary = async (
libraryImageUrl: iconUrl || "",
logoImageUrl: logoImageUrl || "",
logoPosition: null,
coverImageUrl: iconUrl || "",
coverImageUrl: coverImageUrl || "",
downloadSources: [],
};
await gamesShopAssetsSublevel.put(gameKey, assets);
Expand All @@ -46,6 +47,7 @@ const addCustomGameToLibrary = async (
iconUrl: iconUrl || null,
logoImageUrl: logoImageUrl || null,
libraryHeroImageUrl: libraryHeroImageUrl || null,
coverImageUrl: coverImageUrl || null,
objectId,
shop,
remoteId: null,
Expand Down
1 change: 1 addition & 0 deletions src/main/events/library/add-game-to-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const addGameToLibrary = async (
iconUrl: gameAssets?.iconUrl ?? null,
libraryHeroImageUrl: gameAssets?.libraryHeroImageUrl ?? null,
logoImageUrl: gameAssets?.logoImageUrl ?? null,
coverImageUrl: gameAssets?.libraryImageUrl ?? null,
objectId,
shop,
remoteId: null,
Expand Down
3 changes: 3 additions & 0 deletions src/main/events/library/cleanup-unused-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ const getUsedAssetPaths = async (): Promise<Set<string>> => {
if (game.libraryHeroImageUrl?.startsWith("local:")) {
usedPaths.add(game.libraryHeroImageUrl.replace("local:", ""));
}
if (game.coverImageUrl?.startsWith("local:")) {
usedPaths.add(game.coverImageUrl.replace("local:", ""));
}
});

return usedPaths;
Expand Down
2 changes: 1 addition & 1 deletion src/main/events/library/copy-custom-game-asset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ASSETS_PATH } from "@main/constants";
const copyCustomGameAsset = async (
_event: Electron.IpcMainInvokeEvent,
sourcePath: string,
assetType: "icon" | "logo" | "hero"
assetType: "icon" | "logo" | "hero" | "cover"
): Promise<string> => {
if (!sourcePath || !fs.existsSync(sourcePath)) {
throw new Error("Source file does not exist");
Expand Down
1 change: 1 addition & 0 deletions src/main/events/library/get-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ const getLibrary = async (): Promise<LibraryGame[]> => {
customIconUrl: game.customIconUrl,
customLogoImageUrl: game.customLogoImageUrl,
customHeroImageUrl: game.customHeroImageUrl,
customCoverImageUrl: game.customCoverImageUrl,
};
})
);
Expand Down
15 changes: 13 additions & 2 deletions src/main/events/library/remove-game-from-library.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,18 @@ const collectAssetPathsToDelete = (game: Game): string[] => {

const assetUrls =
game.shop === "custom"
? [game.iconUrl, game.logoImageUrl, game.libraryHeroImageUrl]
: [game.customIconUrl, game.customLogoImageUrl, game.customHeroImageUrl];
? [
game.iconUrl,
game.logoImageUrl,
game.libraryHeroImageUrl,
game.coverImageUrl,
]
: [
game.customIconUrl,
game.customLogoImageUrl,
game.customHeroImageUrl,
game.customCoverImageUrl,
];

for (const url of assetUrls) {
if (url?.startsWith("local:")) {
Expand All @@ -33,6 +43,7 @@ const updateGameAsDeleted = async (
customIconUrl: null,
customLogoImageUrl: null,
customHeroImageUrl: null,
customCoverImageUrl: null,
}),
};

Expand Down
10 changes: 9 additions & 1 deletion src/main/events/library/update-custom-game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ interface UpdateCustomGameParams {
iconUrl?: string;
logoImageUrl?: string;
libraryHeroImageUrl?: string;
coverImageUrl?: string;
originalIconPath?: string;
originalLogoPath?: string;
originalHeroPath?: string;
originalCoverPath?: string;
}

const updateCustomGame = async (
Expand All @@ -27,9 +29,11 @@ const updateCustomGame = async (
iconUrl,
logoImageUrl,
libraryHeroImageUrl,
coverImageUrl,
originalIconPath,
originalLogoPath,
originalHeroPath,
originalCoverPath,
} = params;
const gameKey = levelKeys.game(shop, objectId);

Expand All @@ -44,6 +48,7 @@ const updateCustomGame = async (
{ existing: existingGame.iconUrl, new: iconUrl },
{ existing: existingGame.logoImageUrl, new: logoImageUrl },
{ existing: existingGame.libraryHeroImageUrl, new: libraryHeroImageUrl },
{ existing: existingGame.coverImageUrl, new: coverImageUrl },
];

for (const { existing, new: newUrl } of assetPairs) {
Expand All @@ -58,9 +63,12 @@ const updateCustomGame = async (
iconUrl: iconUrl || null,
logoImageUrl: logoImageUrl || null,
libraryHeroImageUrl: libraryHeroImageUrl || null,
coverImageUrl: coverImageUrl || null,
originalIconPath: originalIconPath || existingGame.originalIconPath || null,
originalLogoPath: originalLogoPath || existingGame.originalLogoPath || null,
originalHeroPath: originalHeroPath || existingGame.originalHeroPath || null,
originalCoverPath:
originalCoverPath || existingGame.originalCoverPath || null,
};

await gamesSublevel.put(gameKey, updatedGame);
Expand All @@ -74,7 +82,7 @@ const updateCustomGame = async (
libraryHeroImageUrl: libraryHeroImageUrl || "",
libraryImageUrl: iconUrl || "",
logoImageUrl: logoImageUrl || "",
coverImageUrl: iconUrl || "",
coverImageUrl: coverImageUrl || "",
};

await gamesShopAssetsSublevel.put(gameKey, updatedAssets);
Expand Down
19 changes: 17 additions & 2 deletions src/main/events/library/update-game-custom-assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@ const collectOldAssetPaths = (
existingGame: Game,
customIconUrl?: string | null,
customLogoImageUrl?: string | null,
customHeroImageUrl?: string | null
customHeroImageUrl?: string | null,
customCoverImageUrl?: string | null
): string[] => {
const oldAssetPaths: string[] = [];

const assetPairs = [
{ existing: existingGame.customIconUrl, new: customIconUrl },
{ existing: existingGame.customLogoImageUrl, new: customLogoImageUrl },
{ existing: existingGame.customHeroImageUrl, new: customHeroImageUrl },
{ existing: existingGame.customCoverImageUrl, new: customCoverImageUrl },
];

for (const { existing, new: newUrl } of assetPairs) {
Expand All @@ -39,9 +41,11 @@ interface UpdateGameDataParams {
customIconUrl?: string | null;
customLogoImageUrl?: string | null;
customHeroImageUrl?: string | null;
customCoverImageUrl?: string | null;
customOriginalIconPath?: string | null;
customOriginalLogoPath?: string | null;
customOriginalHeroPath?: string | null;
customOriginalCoverPath?: string | null;
}

const updateGameData = async (params: UpdateGameDataParams): Promise<Game> => {
Expand All @@ -52,19 +56,23 @@ const updateGameData = async (params: UpdateGameDataParams): Promise<Game> => {
customIconUrl,
customLogoImageUrl,
customHeroImageUrl,
customCoverImageUrl,
customOriginalIconPath,
customOriginalLogoPath,
customOriginalHeroPath,
customOriginalCoverPath,
} = params;
const updatedGame = {
...existingGame,
title,
...(customIconUrl !== undefined && { customIconUrl }),
...(customLogoImageUrl !== undefined && { customLogoImageUrl }),
...(customHeroImageUrl !== undefined && { customHeroImageUrl }),
...(customCoverImageUrl !== undefined && { customCoverImageUrl }),
...(customOriginalIconPath !== undefined && { customOriginalIconPath }),
...(customOriginalLogoPath !== undefined && { customOriginalLogoPath }),
...(customOriginalHeroPath !== undefined && { customOriginalHeroPath }),
...(customOriginalCoverPath !== undefined && { customOriginalCoverPath }),
};

await gamesSublevel.put(gameKey, updatedGame);
Expand Down Expand Up @@ -106,9 +114,11 @@ interface UpdateGameCustomAssetsParams {
customIconUrl?: string | null;
customLogoImageUrl?: string | null;
customHeroImageUrl?: string | null;
customCoverImageUrl?: string | null;
customOriginalIconPath?: string | null;
customOriginalLogoPath?: string | null;
customOriginalHeroPath?: string | null;
customOriginalCoverPath?: string | null;
}

const updateGameCustomAssets = async (
Expand All @@ -122,9 +132,11 @@ const updateGameCustomAssets = async (
customIconUrl,
customLogoImageUrl,
customHeroImageUrl,
customCoverImageUrl,
customOriginalIconPath,
customOriginalLogoPath,
customOriginalHeroPath,
customOriginalCoverPath,
} = params;
const gameKey = levelKeys.game(shop, objectId);

Expand All @@ -137,7 +149,8 @@ const updateGameCustomAssets = async (
existingGame,
customIconUrl,
customLogoImageUrl,
customHeroImageUrl
customHeroImageUrl,
customCoverImageUrl
);

const updatedGame = await updateGameData({
Expand All @@ -147,9 +160,11 @@ const updateGameCustomAssets = async (
customIconUrl,
customLogoImageUrl,
customHeroImageUrl,
customCoverImageUrl,
customOriginalIconPath,
customOriginalLogoPath,
customOriginalHeroPath,
customOriginalCoverPath,
});

await updateShopAssets(gameKey, title);
Expand Down
1 change: 1 addition & 0 deletions src/main/helpers/download-game-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const prepareGameEntry = async ({
iconUrl: gameAssets?.iconUrl ?? null,
libraryHeroImageUrl: gameAssets?.libraryHeroImageUrl ?? null,
logoImageUrl: gameAssets?.logoImageUrl ?? null,
coverImageUrl: gameAssets?.coverImageUrl ?? null,
objectId,
shop,
remoteId: null,
Expand Down
2 changes: 2 additions & 0 deletions src/main/services/library-sync/merge-with-remote-games.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export const mergeWithRemoteGames = async () => {
iconUrl: game.iconUrl,
libraryHeroImageUrl: game.libraryHeroImageUrl,
logoImageUrl: game.logoImageUrl,
coverImageUrl: game.coverImageUrl,
lastTimePlayed: game.lastTimePlayed,
playTimeInMilliseconds: game.playTimeInMilliseconds,
hasManuallyUpdatedPlaytime: game.hasManuallyUpdatedPlaytime,
Expand All @@ -114,6 +115,7 @@ export const mergeWithRemoteGames = async () => {
// Construct coverImageUrl if not provided by backend (Steam games use predictable pattern)
const coverImageUrl =
game.coverImageUrl ||
game.libraryImageUrl ||
(game.shop === "steam"
? `https://shared.steamstatic.com/store_item_assets/steam/apps/${game.objectId}/library_600x900_2x.jpg`
: null);
Expand Down
12 changes: 9 additions & 3 deletions src/preload/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,19 +167,21 @@ contextBridge.exposeInMainWorld("electron", {
executablePath: string,
iconUrl?: string,
logoImageUrl?: string,
libraryHeroImageUrl?: string
libraryHeroImageUrl?: string,
coverImageUrl?: string
) =>
ipcRenderer.invoke(
"addCustomGameToLibrary",
title,
executablePath,
iconUrl,
logoImageUrl,
libraryHeroImageUrl
libraryHeroImageUrl,
coverImageUrl
),
copyCustomGameAsset: (
sourcePath: string,
assetType: "icon" | "logo" | "hero"
assetType: "icon" | "logo" | "hero" | "cover"
) => ipcRenderer.invoke("copyCustomGameAsset", sourcePath, assetType),
saveTempFile: (fileName: string, fileData: Uint8Array) =>
ipcRenderer.invoke("saveTempFile", fileName, fileData),
Expand All @@ -193,9 +195,11 @@ contextBridge.exposeInMainWorld("electron", {
iconUrl?: string;
logoImageUrl?: string;
libraryHeroImageUrl?: string;
coverImageUrl?: string;
originalIconPath?: string;
originalLogoPath?: string;
originalHeroPath?: string;
originalCoverPath?: string;
}) => ipcRenderer.invoke("updateCustomGame", params),
updateGameCustomAssets: (params: {
shop: GameShop;
Expand All @@ -204,9 +208,11 @@ contextBridge.exposeInMainWorld("electron", {
customIconUrl?: string | null;
customLogoImageUrl?: string | null;
customHeroImageUrl?: string | null;
customCoverImageUrl?: string | null;
customOriginalIconPath?: string | null;
customOriginalLogoPath?: string | null;
customOriginalHeroPath?: string | null;
customOriginalCoverPath?: string | null;
}) => ipcRenderer.invoke("updateGameCustomAssets", params),
createGameShortcut: (
shop: GameShop,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,15 @@ export function SidebarAddingCustomGameModal({
const iconUrl = ""; // Don't use gradient for icon
const logoImageUrl = ""; // Don't use gradient for logo
const libraryHeroImageUrl = generateRandomGradient(); // Only use gradient for hero
const coverImageUrl = ""; // Don't use gradient for cover

const newGame = await window.electron.addCustomGameToLibrary(
gameNameForSeed,
executablePath,
iconUrl,
logoImageUrl,
libraryHeroImageUrl
libraryHeroImageUrl,
coverImageUrl
);

showSuccessToast(t("custom_game_modal_success"));
Expand Down
Loading
Loading