diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json
index 93fd5b0a..327499d0 100755
--- a/src/locales/en/translation.json
+++ b/src/locales/en/translation.json
@@ -70,7 +70,13 @@
"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_assets": "Assets"
+ "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_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"
},
"header": {
"search": "Search games",
diff --git a/src/locales/ru/translation.json b/src/locales/ru/translation.json
index 03413554..8992a4a0 100644
--- a/src/locales/ru/translation.json
+++ b/src/locales/ru/translation.json
@@ -67,7 +67,14 @@
"edit_game_modal_image_filter": "Изображение",
"edit_game_modal_icon_resolution": "Рекомендуемое разрешение: 256x256px",
"edit_game_modal_logo_resolution": "Рекомендуемое разрешение: 640x360px",
- "edit_game_modal_hero_resolution": "Рекомендуемое разрешение: 1920x620px"
+ "edit_game_modal_hero_resolution": "Рекомендуемое разрешение: 1920x620px",
+ "edit_game_modal_assets": "Ресурсы",
+ "edit_game_modal_drop_icon_image_here": "Перетащите изображение иконки сюда",
+ "edit_game_modal_drop_logo_image_here": "Перетащите изображение логотипа сюда",
+ "edit_game_modal_drop_hero_image_here": "Перетащите изображение обложки сюда",
+ "edit_game_modal_drop_to_replace_icon": "Перетащите для замены иконки",
+ "edit_game_modal_drop_to_replace_logo": "Перетащите для замены логотипа",
+ "edit_game_modal_drop_to_replace_hero": "Перетащите для замены обложки"
},
"header": {
"search": "Поиск",
diff --git a/src/renderer/src/pages/game-details/modals/edit-game-modal.tsx b/src/renderer/src/pages/game-details/modals/edit-game-modal.tsx
index 0f6df95d..a31ce400 100644
--- a/src/renderer/src/pages/game-details/modals/edit-game-modal.tsx
+++ b/src/renderer/src/pages/game-details/modals/edit-game-modal.tsx
@@ -4,6 +4,7 @@ import { ImageIcon, XIcon } from "@primer/octicons-react";
import { Modal, TextField, Button } from "@renderer/components";
import { useToast } from "@renderer/hooks";
+import { generateRandomGradient } from "@renderer/helpers";
import type { LibraryGame, Game, ShopDetailsWithAssets } from "@types";
import "./edit-game-modal.scss";
@@ -44,6 +45,11 @@ export function EditGameModal({
logo: "",
hero: "",
});
+ const [removedAssets, setRemovedAssets] = useState({
+ icon: false,
+ logo: false,
+ hero: false,
+ });
const [defaultUrls, setDefaultUrls] = useState({
icon: null as string | null,
logo: null as string | null,
@@ -158,6 +164,21 @@ export function EditGameModal({
return defaultUrls[assetType];
};
+ const getOriginalAssetUrl = (assetType: AssetType): string | null => {
+ if (!game || !isCustomGame(game)) return null;
+
+ switch (assetType) {
+ case "icon":
+ return game.iconUrl;
+ case "logo":
+ return game.logoImageUrl;
+ case "hero":
+ return game.libraryHeroImageUrl;
+ default:
+ return null;
+ }
+ };
+
const handleSelectAsset = async (assetType: AssetType) => {
const { filePaths } = await window.electron.showOpenDialog({
properties: ["openFile"],
@@ -183,6 +204,8 @@ export function EditGameModal({
...prev,
[assetType]: originalPath,
}));
+ // Clear the removed flag when a new asset is selected
+ setRemovedAssets((prev) => ({ ...prev, [assetType]: false }));
} catch (error) {
console.error(`Failed to copy ${assetType} asset:`, error);
setAssetPath(assetType, originalPath);
@@ -191,14 +214,25 @@ export function EditGameModal({
...prev,
[assetType]: originalPath,
}));
+ // Clear the removed flag when a new asset is selected
+ setRemovedAssets((prev) => ({ ...prev, [assetType]: false }));
}
}
};
const handleRestoreDefault = (assetType: AssetType) => {
- setAssetPath(assetType, "");
- setAssetDisplayPath(assetType, "");
- setOriginalAssetPaths((prev) => ({ ...prev, [assetType]: "" }));
+ if (game && isCustomGame(game)) {
+ // For custom games, mark asset as removed and clear paths
+ setRemovedAssets((prev) => ({ ...prev, [assetType]: true }));
+ setAssetPath(assetType, "");
+ setAssetDisplayPath(assetType, "");
+ setOriginalAssetPaths((prev) => ({ ...prev, [assetType]: "" }));
+ } else {
+ // For non-custom games, clear custom assets (restore to shop defaults)
+ setAssetPath(assetType, "");
+ setAssetDisplayPath(assetType, "");
+ setOriginalAssetPaths((prev) => ({ ...prev, [assetType]: "" }));
+ }
};
const getOriginalTitle = (): string => {
@@ -330,13 +364,38 @@ export function EditGameModal({
// Helper function to prepare custom game assets
const prepareCustomGameAssets = (game: LibraryGame | Game) => {
- const iconUrl = assetPaths.icon ? `local:${assetPaths.icon}` : game.iconUrl;
- const logoImageUrl = assetPaths.logo
- ? `local:${assetPaths.logo}`
- : game.logoImageUrl;
- const libraryHeroImageUrl = assetPaths.hero
- ? `local:${assetPaths.hero}`
- : game.libraryHeroImageUrl;
+ // For custom games, check if asset was explicitly removed
+ let iconUrl;
+ if (removedAssets.icon) {
+ iconUrl = null;
+ } else if (assetPaths.icon) {
+ iconUrl = `local:${assetPaths.icon}`;
+ } else {
+ iconUrl = game.iconUrl;
+ }
+
+ let logoImageUrl;
+ if (removedAssets.logo) {
+ logoImageUrl = null;
+ } else if (assetPaths.logo) {
+ logoImageUrl = `local:${assetPaths.logo}`;
+ } else {
+ logoImageUrl = game.logoImageUrl;
+ }
+
+ // For hero image, if removed, restore to the original gradient or keep the original
+ let libraryHeroImageUrl;
+ if (removedAssets.hero) {
+ // If the original hero was a gradient (data URL), keep it, otherwise generate a new one
+ const originalHero = game.libraryHeroImageUrl;
+ libraryHeroImageUrl = originalHero?.startsWith("data:image/svg+xml")
+ ? originalHero
+ : generateRandomGradient();
+ } else {
+ libraryHeroImageUrl = assetPaths.hero
+ ? `local:${assetPaths.hero}`
+ : game.libraryHeroImageUrl;
+ }
return { iconUrl, logoImageUrl, libraryHeroImageUrl };
};
@@ -418,6 +477,13 @@ export function EditGameModal({
(game: LibraryGame | Game) => {
setGameName(game.title || "");
+ // Reset removed assets state
+ setRemovedAssets({
+ icon: false,
+ logo: false,
+ hero: false,
+ });
+
if (isCustomGame(game)) {
setCustomGameAssets(game);
// Clear default URLs for custom games
@@ -481,17 +547,19 @@ export function EditGameModal({