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