deleted duplicate file, fixed assertions

This commit is contained in:
Moyasee
2025-09-19 17:56:44 +03:00
parent 04be5c754e
commit ea792d0409
7 changed files with 38 additions and 414 deletions

View File

@@ -110,6 +110,7 @@ app.whenReady().then(async () => {
x2 = "0%";
y2 = "0%";
}
// Note: "135deg" case removed as it uses all default values
const svgContent = `
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="300" viewBox="0 0 400 300">

View File

@@ -17,10 +17,10 @@ export interface SidebarAddingCustomGameModalProps {
onClose: () => void;
}
export function SidebarAddingCustomGameModal ({
export function SidebarAddingCustomGameModal({
visible,
onClose,
}: Readonly<SidebarAddingCustomGameModalProps>) {
}: Readonly<SidebarAddingCustomGameModalProps>) {
const { t } = useTranslation("sidebar");
const { updateLibrary } = useLibrary();
const { showSuccessToast, showErrorToast } = useToast();

View File

@@ -7,7 +7,7 @@ import { HeroPanel } from "./hero";
import { DescriptionHeader } from "./description-header/description-header";
import { GallerySlider } from "./gallery-slider/gallery-slider";
import { Sidebar } from "./sidebar/sidebar";
import { EditCustomGameModal, EditGameModal } from "./modals";
import { EditGameModal } from "./modals";
import { useTranslation } from "react-i18next";
import { cloudSyncContext, gameDetailsContext } from "@renderer/context";
@@ -65,7 +65,6 @@ export function GameDetailsContent() {
}, [shopDetails, t, game?.shop]);
const [backdropOpacity, setBackdropOpacity] = useState(1);
const [showEditCustomGameModal, setShowEditCustomGameModal] = useState(false);
const [showEditGameModal, setShowEditGameModal] = useState(false);
const handleHeroLoad = async () => {
@@ -102,10 +101,6 @@ export function GameDetailsContent() {
setShowCloudSyncModal(true);
};
const handleEditCustomGameClick = () => {
setShowEditCustomGameModal(true);
};
const handleEditGameClick = () => {
setShowEditGameModal(true);
};
@@ -181,11 +176,7 @@ export function GameDetailsContent() {
<button
type="button"
className="game-details__edit-custom-game-button"
onClick={
game?.shop === "custom"
? handleEditCustomGameClick
: handleEditGameClick
}
onClick={handleEditGameClick}
title={t("edit_custom_game")}
>
<PencilIcon size={16} />
@@ -231,23 +222,12 @@ export function GameDetailsContent() {
</div>
</section>
{game?.shop === "custom" && (
<EditCustomGameModal
visible={showEditCustomGameModal}
onClose={() => setShowEditCustomGameModal(false)}
game={game}
onGameUpdated={handleGameUpdated}
/>
)}
{game?.shop !== "custom" && (
<EditGameModal
visible={showEditGameModal}
onClose={() => setShowEditGameModal(false)}
game={game}
onGameUpdated={handleGameUpdated}
/>
)}
<EditGameModal
visible={showEditGameModal}
onClose={() => setShowEditGameModal(false)}
game={game}
onGameUpdated={handleGameUpdated}
/>
</div>
);
}

View File

@@ -1,46 +0,0 @@
@use "../../../scss/globals.scss";
.edit-custom-game-modal {
&__container {
display: flex;
flex-direction: column;
gap: calc(globals.$spacing-unit * 2);
}
&__form {
display: flex;
flex-direction: column;
gap: calc(globals.$spacing-unit * 2);
}
&__image-section {
display: flex;
flex-direction: column;
gap: globals.$spacing-unit;
}
&__image-preview {
display: flex;
justify-content: center;
align-items: center;
padding: globals.$spacing-unit;
border: 1px dashed globals.$border-color;
border-radius: 8px;
background-color: rgba(255, 255, 255, 0.05);
}
&__preview-image {
max-width: 120px;
max-height: 80px;
border-radius: 8px;
object-fit: cover;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
}
&__actions {
display: flex;
gap: globals.$spacing-unit;
justify-content: flex-end;
margin-top: globals.$spacing-unit;
}
}

View File

@@ -1,315 +0,0 @@
import { useState, useEffect } from "react";
import { useTranslation } from "react-i18next";
import { ImageIcon } from "@primer/octicons-react";
import { Modal, TextField, Button } from "@renderer/components";
import { useToast } from "@renderer/hooks";
import type { Game } from "@types";
import "./edit-custom-game-modal.scss";
export interface EditCustomGameModalProps {
visible: boolean;
onClose: () => void;
game: Game;
onGameUpdated: (updatedGame: Game) => void;
}
export function EditCustomGameModal({
visible,
onClose,
game,
onGameUpdated,
}: Readonly<EditCustomGameModalProps>) {
const { t } = useTranslation("sidebar");
const { showSuccessToast, showErrorToast } = useToast();
const [gameName, setGameName] = useState("");
const [iconPath, setIconPath] = useState("");
const [logoPath, setLogoPath] = useState("");
const [heroPath, setHeroPath] = useState("");
const [isUpdating, setIsUpdating] = useState(false);
useEffect(() => {
if (game && visible) {
setGameName(game.title || "");
const currentIconPath = game.iconUrl?.startsWith("local:")
? game.iconUrl.replace("local:", "")
: "";
const currentLogoPath = game.logoImageUrl?.startsWith("local:")
? game.logoImageUrl.replace("local:", "")
: "";
const currentHeroPath = game.libraryHeroImageUrl?.startsWith("local:")
? game.libraryHeroImageUrl.replace("local:", "")
: "";
setIconPath(currentIconPath);
setLogoPath(currentLogoPath);
setHeroPath(currentHeroPath);
}
}, [game, visible]);
const handleGameNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setGameName(event.target.value);
};
const handleSelectIcon = async () => {
const { filePaths } = await window.electron.showOpenDialog({
properties: ["openFile"],
filters: [
{
name: t("edit_custom_game_modal_image_filter"),
extensions: ["jpg", "jpeg", "png", "gif", "webp"],
},
],
});
if (filePaths && filePaths.length > 0) {
setIconPath(filePaths[0]);
}
};
const handleSelectLogo = async () => {
const { filePaths } = await window.electron.showOpenDialog({
properties: ["openFile"],
filters: [
{
name: t("edit_custom_game_modal_image_filter"),
extensions: ["jpg", "jpeg", "png", "gif", "webp"],
},
],
});
if (filePaths && filePaths.length > 0) {
setLogoPath(filePaths[0]);
}
};
const handleSelectHero = async () => {
const { filePaths } = await window.electron.showOpenDialog({
properties: ["openFile"],
filters: [
{
name: t("edit_custom_game_modal_image_filter"),
extensions: ["jpg", "jpeg", "png", "gif", "webp"],
},
],
});
if (filePaths && filePaths.length > 0) {
setHeroPath(filePaths[0]);
}
};
const handleUpdateGame = async () => {
if (!gameName.trim()) {
showErrorToast(t("edit_custom_game_modal_fill_required"));
return;
}
setIsUpdating(true);
try {
// Preserve existing image URLs if not changed
const iconUrl = iconPath ? `local:${iconPath}` : game.iconUrl;
const logoImageUrl = logoPath ? `local:${logoPath}` : game.logoImageUrl;
const libraryHeroImageUrl = heroPath
? `local:${heroPath}`
: game.libraryHeroImageUrl;
const updatedGame = await window.electron.updateCustomGame(
game.shop,
game.objectId,
gameName.trim(),
iconUrl || undefined,
logoImageUrl || undefined,
libraryHeroImageUrl || undefined
);
showSuccessToast(t("edit_custom_game_modal_success"));
onGameUpdated(updatedGame);
onClose();
} catch (error) {
console.error("Failed to update custom game:", error);
showErrorToast(
error instanceof Error
? error.message
: t("edit_custom_game_modal_failed")
);
} finally {
setIsUpdating(false);
}
};
const handleClose = () => {
if (!isUpdating) {
setGameName(game?.title || "");
const currentIconPath = game?.iconUrl?.startsWith("local:")
? game.iconUrl.replace("local:", "")
: "";
const currentLogoPath = game?.logoImageUrl?.startsWith("local:")
? game.logoImageUrl.replace("local:", "")
: "";
const currentHeroPath = game?.libraryHeroImageUrl?.startsWith("local:")
? game.libraryHeroImageUrl.replace("local:", "")
: "";
setIconPath(currentIconPath);
setLogoPath(currentLogoPath);
setHeroPath(currentHeroPath);
onClose();
}
};
const isFormValid = gameName.trim();
const getIconPreviewUrl = () => {
return iconPath ? `local:${iconPath}` : null;
};
const getLogoPreviewUrl = () => {
return logoPath ? `local:${logoPath}` : null;
};
const getHeroPreviewUrl = () => {
return heroPath ? `local:${heroPath}` : null;
};
return (
<Modal
visible={visible}
title={t("edit_custom_game_modal")}
description={t("edit_custom_game_modal_description")}
onClose={handleClose}
>
<div className="edit-custom-game-modal__container">
<div className="edit-custom-game-modal__form">
<TextField
label={t("edit_custom_game_modal_game_name")}
placeholder={t("edit_custom_game_modal_enter_name")}
value={gameName}
onChange={handleGameNameChange}
theme="dark"
disabled={isUpdating}
/>
<div className="edit-custom-game-modal__image-section">
<TextField
label={t("edit_custom_game_modal_icon")}
placeholder={t("edit_custom_game_modal_select_icon")}
value={iconPath}
readOnly
theme="dark"
rightContent={
<Button
type="button"
theme="outline"
onClick={handleSelectIcon}
disabled={isUpdating}
>
<ImageIcon />
{t("edit_custom_game_modal_browse")}
</Button>
}
/>
{iconPath && (
<div className="edit-custom-game-modal__image-preview">
<img
src={getIconPreviewUrl()!}
alt={t("edit_custom_game_modal_icon_preview")}
className="edit-custom-game-modal__preview-image"
/>
</div>
)}
</div>
<div className="edit-custom-game-modal__image-section">
<TextField
label={t("edit_custom_game_modal_logo")}
placeholder={t("edit_custom_game_modal_select_logo")}
value={logoPath}
readOnly
theme="dark"
rightContent={
<Button
type="button"
theme="outline"
onClick={handleSelectLogo}
disabled={isUpdating}
>
<ImageIcon />
{t("edit_custom_game_modal_browse")}
</Button>
}
/>
{logoPath && (
<div className="edit-custom-game-modal__image-preview">
<img
src={getLogoPreviewUrl()!}
alt={t("edit_custom_game_modal_logo_preview")}
className="edit-custom-game-modal__preview-image"
/>
</div>
)}
</div>
<div className="edit-custom-game-modal__image-section">
<TextField
label={t("edit_custom_game_modal_hero")}
placeholder={t("edit_custom_game_modal_select_hero")}
value={heroPath}
readOnly
theme="dark"
rightContent={
<Button
type="button"
theme="outline"
onClick={handleSelectHero}
disabled={isUpdating}
>
<ImageIcon />
{t("edit_custom_game_modal_browse")}
</Button>
}
/>
{heroPath && (
<div className="edit-custom-game-modal__image-preview">
<img
src={getHeroPreviewUrl()!}
alt={t("edit_custom_game_modal_hero_preview")}
className="edit-custom-game-modal__preview-image"
/>
</div>
)}
</div>
</div>
<div className="edit-custom-game-modal__actions">
<Button
type="button"
theme="outline"
onClick={handleClose}
disabled={isUpdating}
>
{t("edit_custom_game_modal_cancel")}
</Button>
<Button
type="button"
theme="primary"
onClick={handleUpdateGame}
disabled={!isFormValid || isUpdating}
>
{isUpdating
? t("edit_custom_game_modal_updating")
: t("edit_custom_game_modal_update")}
</Button>
</div>
</div>
</Modal>
);
}

View File

@@ -4,14 +4,14 @@ import { ImageIcon } from "@primer/octicons-react";
import { Modal, TextField, Button } from "@renderer/components";
import { useToast } from "@renderer/hooks";
import type { LibraryGame } from "@types";
import type { LibraryGame, Game } from "@types";
import "./edit-game-modal.scss";
export interface EditGameModalProps {
visible: boolean;
onClose: () => void;
game: LibraryGame | null;
game: LibraryGame | Game | null;
onGameUpdated: (updatedGame: any) => void;
}
@@ -20,7 +20,7 @@ export function EditGameModal({
onClose,
game,
onGameUpdated,
}: EditGameModalProps) {
}: Readonly<EditGameModalProps>) {
const { t } = useTranslation("sidebar");
const { showSuccessToast, showErrorToast } = useToast();
@@ -30,13 +30,18 @@ export function EditGameModal({
const [heroPath, setHeroPath] = useState("");
const [isUpdating, setIsUpdating] = useState(false);
// Helper function to check if game is a custom game
const isCustomGame = (game: LibraryGame | Game): boolean => {
return game.shop === "custom";
};
// Helper function to extract local path from URL
const extractLocalPath = (url: string | null | undefined): string => {
return url?.startsWith("local:") ? url.replace("local:", "") : "";
};
// Helper function to set asset paths for custom games
const setCustomGameAssets = (game: LibraryGame) => {
const setCustomGameAssets = (game: LibraryGame | Game) => {
setIconPath(extractLocalPath(game.iconUrl));
setLogoPath(extractLocalPath(game.logoImageUrl));
setHeroPath(extractLocalPath(game.libraryHeroImageUrl));
@@ -53,10 +58,10 @@ export function EditGameModal({
if (game && visible) {
setGameName(game.title || "");
if (game.shop === "custom") {
if (isCustomGame(game)) {
setCustomGameAssets(game);
} else {
setNonCustomGameAssets(game);
setNonCustomGameAssets(game as LibraryGame);
}
}
}, [game, visible]);
@@ -114,7 +119,7 @@ export function EditGameModal({
};
// Helper function to prepare custom game assets
const prepareCustomGameAssets = (game: LibraryGame) => {
const prepareCustomGameAssets = (game: LibraryGame | Game) => {
const iconUrl = iconPath ? `local:${iconPath}` : game.iconUrl;
const logoImageUrl = logoPath ? `local:${logoPath}` : game.logoImageUrl;
const libraryHeroImageUrl = heroPath
@@ -134,7 +139,7 @@ export function EditGameModal({
};
// Helper function to update custom game
const updateCustomGame = async (game: LibraryGame) => {
const updateCustomGame = async (game: LibraryGame | Game) => {
const { iconUrl, logoImageUrl, libraryHeroImageUrl } =
prepareCustomGameAssets(game);
@@ -173,9 +178,9 @@ export function EditGameModal({
try {
const updatedGame =
game.shop === "custom"
isCustomGame(game)
? await updateCustomGame(game)
: await updateNonCustomGame(game);
: await updateNonCustomGame(game as LibraryGame);
showSuccessToast(t("edit_custom_game_modal_success"));
onGameUpdated(updatedGame);
@@ -193,13 +198,13 @@ export function EditGameModal({
};
// Helper function to reset form to initial state
const resetFormToInitialState = (game: LibraryGame) => {
const resetFormToInitialState = (game: LibraryGame | Game) => {
setGameName(game.title || "");
if (game.shop === "custom") {
if (isCustomGame(game)) {
setCustomGameAssets(game);
} else {
setNonCustomGameAssets(game);
setNonCustomGameAssets(game as LibraryGame);
}
};
@@ -212,16 +217,16 @@ export function EditGameModal({
const isFormValid = gameName.trim();
const getIconPreviewUrl = () => {
return iconPath ? `local:${iconPath}` : null;
const getIconPreviewUrl = (): string | undefined => {
return iconPath ? `local:${iconPath}` : undefined;
};
const getLogoPreviewUrl = () => {
return logoPath ? `local:${logoPath}` : null;
const getLogoPreviewUrl = (): string | undefined => {
return logoPath ? `local:${logoPath}` : undefined;
};
const getHeroPreviewUrl = () => {
return heroPath ? `local:${heroPath}` : null;
const getHeroPreviewUrl = (): string | undefined => {
return heroPath ? `local:${heroPath}` : undefined;
};
return (
@@ -265,7 +270,7 @@ export function EditGameModal({
{iconPath && (
<div className="edit-game-modal__image-preview">
<img
src={getIconPreviewUrl()!}
src={getIconPreviewUrl()}
alt={t("edit_custom_game_modal_icon_preview")}
className="edit-game-modal__preview-image"
/>
@@ -296,7 +301,7 @@ export function EditGameModal({
{logoPath && (
<div className="edit-game-modal__image-preview">
<img
src={getLogoPreviewUrl()!}
src={getLogoPreviewUrl()}
alt={t("edit_custom_game_modal_logo_preview")}
className="edit-game-modal__preview-image"
/>
@@ -327,7 +332,7 @@ export function EditGameModal({
{heroPath && (
<div className="edit-game-modal__image-preview">
<img
src={getHeroPreviewUrl()!}
src={getHeroPreviewUrl()}
alt={t("edit_custom_game_modal_hero_preview")}
className="edit-game-modal__preview-image"
/>

View File

@@ -1,5 +1,4 @@
export * from "./repacks-modal";
export * from "./download-settings-modal";
export * from "./game-options-modal";
export * from "./edit-custom-game-modal";
export * from "./edit-game-modal";