Fetch image_ids lazily with first image, remove from initial cards load
ci/woodpecker/push/woodpecker Pipeline was successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
@@ -5,7 +5,8 @@ export const CardContext = createContext();
|
||||
export function CardProvider({ children }) {
|
||||
const [ownedAmounts, setOwnedAmounts] = useState({});
|
||||
const [expandedCardId, setExpandedCardId] = useState(null);
|
||||
// cardImages[cardId] is an array of base64 strings, one per artwork index
|
||||
// cardImages[cardId].blobs: string[] (base64 per artwork index)
|
||||
// cardImages[cardId].ids: number[] (image_ids from API)
|
||||
const [cardImages, setCardImages] = useState({});
|
||||
|
||||
const updateAmount = (card_id, key, amount) => {
|
||||
@@ -15,11 +16,15 @@ export function CardProvider({ children }) {
|
||||
}));
|
||||
};
|
||||
|
||||
const setCardImage = (card_id, index, blob) => {
|
||||
const setCardImage = (card_id, index, blob, image_ids) => {
|
||||
setCardImages(prev => {
|
||||
const existing = prev[card_id] ? [...prev[card_id]] : [];
|
||||
existing[index] = blob;
|
||||
return { ...prev, [card_id]: existing };
|
||||
const existing = prev[card_id] ?? { blobs: [], ids: [] };
|
||||
const blobs = [...existing.blobs];
|
||||
blobs[index] = blob;
|
||||
return {
|
||||
...prev,
|
||||
[card_id]: { blobs, ids: image_ids ?? existing.ids }
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
+19
-22
@@ -45,14 +45,14 @@ function HomePage() {
|
||||
|
||||
useEffect(() => {
|
||||
if (!expandedCardId) return;
|
||||
const card = cards.find(c => c.id === expandedCardId);
|
||||
if (!card) return;
|
||||
const imageId = card.image_ids?.[artworkIndex];
|
||||
if (!imageId || cardImages[expandedCardId]?.[artworkIndex]) return;
|
||||
const imageIds = cardImages[expandedCardId]?.ids;
|
||||
const imageId = imageIds?.[artworkIndex];
|
||||
if (cardImages[expandedCardId]?.blobs[artworkIndex]) return;
|
||||
// imageId may be undefined on first load (ids not yet fetched)
|
||||
fetchCardImage(expandedCardId, imageId)
|
||||
.then(image => setCardImage(expandedCardId, artworkIndex, image))
|
||||
.then(({ image, image_ids }) => setCardImage(expandedCardId, artworkIndex, image, image_ids))
|
||||
.catch(err => console.error('Failed to load card image', err));
|
||||
}, [expandedCardId, artworkIndex, cards, cardImages, setCardImage]);
|
||||
}, [expandedCardId, artworkIndex, cardImages, setCardImage]);
|
||||
|
||||
const getTotal = useCallback((card) =>
|
||||
card.printings?.reduce((sum, p) => {
|
||||
@@ -134,30 +134,27 @@ function HomePage() {
|
||||
<div style={{ flex: 1, padding: '16px', overflowY: 'auto', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: '10px' }}>
|
||||
{expandedCard ? (
|
||||
<>
|
||||
{(() => {
|
||||
const imgs = cardImages[expandedCardId];
|
||||
const blob = imgs?.blobs[artworkIndex];
|
||||
const ids = imgs?.ids ?? [];
|
||||
return (
|
||||
<div style={{ position: 'relative', width: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
|
||||
{cardImages[expandedCardId]?.[artworkIndex] ? (
|
||||
<img src={cardImages[expandedCardId][artworkIndex]} alt={expandedCard.name} style={{ maxWidth: '100%' }} />
|
||||
{blob ? (
|
||||
<img src={blob} alt={expandedCard.name} style={{ maxWidth: '100%' }} />
|
||||
) : (
|
||||
<div style={{ color: '#444', fontSize: '12px', padding: '2rem' }}>Loading image…</div>
|
||||
)}
|
||||
{(expandedCard.image_ids?.length ?? 0) > 1 && (
|
||||
{ids.length > 1 && (
|
||||
<div style={{ position: 'absolute', bottom: '6px', display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||
<button
|
||||
className="icon-btn"
|
||||
onClick={() => setArtworkIndex(i => Math.max(0, i - 1))}
|
||||
disabled={artworkIndex === 0}
|
||||
>‹</button>
|
||||
<span style={{ fontSize: '11px', color: '#555' }}>
|
||||
{artworkIndex + 1} / {expandedCard.image_ids.length}
|
||||
</span>
|
||||
<button
|
||||
className="icon-btn"
|
||||
onClick={() => setArtworkIndex(i => Math.min(expandedCard.image_ids.length - 1, i + 1))}
|
||||
disabled={artworkIndex === expandedCard.image_ids.length - 1}
|
||||
>›</button>
|
||||
<button className="icon-btn" onClick={() => setArtworkIndex(i => Math.max(0, i - 1))} disabled={artworkIndex === 0}>‹</button>
|
||||
<span style={{ fontSize: '11px', color: '#555' }}>{artworkIndex + 1} / {ids.length}</span>
|
||||
<button className="icon-btn" onClick={() => setArtworkIndex(i => Math.min(ids.length - 1, i + 1))} disabled={artworkIndex === ids.length - 1}>›</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
<div style={{ width: '100%', borderTop: '1px solid #222', paddingTop: '10px', display: 'flex', flexDirection: 'column', gap: '5px' }}>
|
||||
<span style={{ fontSize: '15px', fontWeight: 600, color: '#e0e0e0' }}>{expandedCard.name}</span>
|
||||
<div style={{ display: 'flex', gap: '6px', flexWrap: 'wrap' }}>
|
||||
|
||||
+1
-2
@@ -13,8 +13,7 @@ export async function fetchCardImage(cardId, imageId) {
|
||||
: `${API_BASE}/cardImage/${cardId}`;
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) throw new Error('Failed to fetch card image');
|
||||
const data = await response.json();
|
||||
return data.image;
|
||||
return await response.json(); // { image, image_ids }
|
||||
}
|
||||
|
||||
export async function updateCardAmount(cardId, setId, rarityId, amount) {
|
||||
|
||||
Reference in New Issue
Block a user