From 7b47d566c23f1bbf7cd40bd6654a8b0d61c42d99 Mon Sep 17 00:00:00 2001 From: dnviti Date: Fri, 19 Dec 2025 02:39:54 +0100 Subject: [PATCH] feat: Introduce `image_uris` property to `Card` interface and update components to prioritize it for card image display. --- .../src/modules/draft/DeckBuilderView.tsx | 18 +++++++++++++++--- src/client/src/modules/game/CardComponent.tsx | 9 ++++++++- src/client/src/modules/game/GameView.tsx | 6 +++++- src/client/src/types/game.ts | 9 +++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/src/client/src/modules/draft/DeckBuilderView.tsx b/src/client/src/modules/draft/DeckBuilderView.tsx index f814a09..ef7dc22 100644 --- a/src/client/src/modules/draft/DeckBuilderView.tsx +++ b/src/client/src/modules/draft/DeckBuilderView.tsx @@ -429,13 +429,25 @@ export const DeckBuilderView: React.FC = ({ initialPool, a const targetId = c.scryfallId; // DraftCard uses scryfallId for the real ID const setCode = c.setCode || c.set; + const cardWithDefinition = { + ...c, + definition: { + set: setCode, + id: targetId, + ...(c.definition || {}) + } + }; + if (targetId && setCode) { return { - ...c, - image: `/cards/images/${setCode}/full/${targetId}.jpg` + ...cardWithDefinition, + image_uris: { + normal: `/cards/images/${setCode}/full/${targetId}.jpg`, + crop: `/cards/images/${setCode}/crop/${targetId}.jpg` + } }; } - return c; + return cardWithDefinition; }); socketService.socket.emit('player_ready', { deck: preparedDeck }); diff --git a/src/client/src/modules/game/CardComponent.tsx b/src/client/src/modules/game/CardComponent.tsx index 0dcfc59..3b87305 100644 --- a/src/client/src/modules/game/CardComponent.tsx +++ b/src/client/src/modules/game/CardComponent.tsx @@ -29,11 +29,18 @@ export const CardComponent: React.FC = ({ card, onDragStart, return () => unregisterCard(card.instanceId); }, [card.instanceId]); + // Robustly resolve Art Crop // Robustly resolve Art Crop // Robustly resolve Art Crop let imageSrc = card.imageUrl; - if (card.definition && card.definition.set && card.definition.id) { + if (card.image_uris) { + if (viewMode === 'cutout' && card.image_uris.crop) { + imageSrc = card.image_uris.crop; + } else if (card.image_uris.normal) { + imageSrc = card.image_uris.normal; + } + } else if (card.definition && card.definition.set && card.definition.id) { if (viewMode === 'cutout') { imageSrc = `/cards/images/${card.definition.set}/crop/${card.definition.id}.jpg`; } else { diff --git a/src/client/src/modules/game/GameView.tsx b/src/client/src/modules/game/GameView.tsx index 855589c..aea5bd1 100644 --- a/src/client/src/modules/game/GameView.tsx +++ b/src/client/src/modules/game/GameView.tsx @@ -502,6 +502,9 @@ export const GameView: React.FC = ({ gameState, currentPlayerId } {hoveredCard && ( { + if (hoveredCard.image_uris?.normal) { + return hoveredCard.image_uris.normal; + } if (hoveredCard.definition?.set && hoveredCard.definition?.id) { return `/cards/images/${hoveredCard.definition.set}/full/${hoveredCard.definition.id}.jpg`; } @@ -859,9 +862,10 @@ export const GameView: React.FC = ({ gameState, currentPlayerId } { }} onDragEnd={() => { }} - onClick={toggleTap} + onClick={() => setInspectedCard(card)} onContextMenu={(id, e) => handleContextMenu(e, 'card', id)} style={{ transformOrigin: 'bottom center' }} onMouseEnter={() => setHoveredCard(card)} diff --git a/src/client/src/types/game.ts b/src/client/src/types/game.ts index ca8b605..26f62c9 100644 --- a/src/client/src/types/game.ts +++ b/src/client/src/types/game.ts @@ -45,6 +45,15 @@ export interface CardInstance { oracleText?: string; manaCost?: string; definition?: any; + image_uris?: { + normal?: string; + crop?: string; + art_crop?: string; + small?: string; + large?: string; + png?: string; + border_crop?: string; + }; } export interface PlayerState {