feat: Introduce image_uris property to Card interface and update components to prioritize it for card image display.

This commit is contained in:
2025-12-19 02:39:54 +01:00
parent 312530d0f0
commit 7b47d566c2
4 changed files with 37 additions and 5 deletions

View File

@@ -429,13 +429,25 @@ export const DeckBuilderView: React.FC<DeckBuilderViewProps> = ({ initialPool, a
const targetId = c.scryfallId; // DraftCard uses scryfallId for the real ID const targetId = c.scryfallId; // DraftCard uses scryfallId for the real ID
const setCode = c.setCode || c.set; const setCode = c.setCode || c.set;
const cardWithDefinition = {
...c,
definition: {
set: setCode,
id: targetId,
...(c.definition || {})
}
};
if (targetId && setCode) { if (targetId && setCode) {
return { return {
...c, ...cardWithDefinition,
image: `/cards/images/${setCode}/full/${targetId}.jpg` 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 }); socketService.socket.emit('player_ready', { deck: preparedDeck });

View File

@@ -29,11 +29,18 @@ export const CardComponent: React.FC<CardComponentProps> = ({ card, onDragStart,
return () => unregisterCard(card.instanceId); return () => unregisterCard(card.instanceId);
}, [card.instanceId]); }, [card.instanceId]);
// Robustly resolve Art Crop
// Robustly resolve Art Crop // Robustly resolve Art Crop
// Robustly resolve Art Crop // Robustly resolve Art Crop
let imageSrc = card.imageUrl; 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') { if (viewMode === 'cutout') {
imageSrc = `/cards/images/${card.definition.set}/crop/${card.definition.id}.jpg`; imageSrc = `/cards/images/${card.definition.set}/crop/${card.definition.id}.jpg`;
} else { } else {

View File

@@ -502,6 +502,9 @@ export const GameView: React.FC<GameViewProps> = ({ gameState, currentPlayerId }
{hoveredCard && ( {hoveredCard && (
<img <img
src={(() => { src={(() => {
if (hoveredCard.image_uris?.normal) {
return hoveredCard.image_uris.normal;
}
if (hoveredCard.definition?.set && hoveredCard.definition?.id) { if (hoveredCard.definition?.set && hoveredCard.definition?.id) {
return `/cards/images/${hoveredCard.definition.set}/full/${hoveredCard.definition.id}.jpg`; return `/cards/images/${hoveredCard.definition.set}/full/${hoveredCard.definition.id}.jpg`;
} }
@@ -859,9 +862,10 @@ export const GameView: React.FC<GameViewProps> = ({ gameState, currentPlayerId }
<DraggableCardWrapper card={card}> <DraggableCardWrapper card={card}>
<CardComponent <CardComponent
card={card} card={card}
viewMode="normal"
onDragStart={() => { }} onDragStart={() => { }}
onDragEnd={() => { }} onDragEnd={() => { }}
onClick={toggleTap} onClick={() => setInspectedCard(card)}
onContextMenu={(id, e) => handleContextMenu(e, 'card', id)} onContextMenu={(id, e) => handleContextMenu(e, 'card', id)}
style={{ transformOrigin: 'bottom center' }} style={{ transformOrigin: 'bottom center' }}
onMouseEnter={() => setHoveredCard(card)} onMouseEnter={() => setHoveredCard(card)}

View File

@@ -45,6 +45,15 @@ export interface CardInstance {
oracleText?: string; oracleText?: string;
manaCost?: string; manaCost?: string;
definition?: any; definition?: any;
image_uris?: {
normal?: string;
crop?: string;
art_crop?: string;
small?: string;
large?: string;
png?: string;
border_crop?: string;
};
} }
export interface PlayerState { export interface PlayerState {