import React, { Component } from 'react'; import Box from '@mui/material/Box'; import CardMedia from '@mui/material/CardMedia'; import Stack from '@mui/material/Stack'; import Dialog from '@mui/material/Dialog'; import DialogContent from '@mui/material/DialogContent'; import IconButton from '@mui/material/IconButton'; import Badge from '@mui/material/Badge'; import CloseIcon from '@mui/icons-material/Close'; import LoupeIcon from '@mui/icons-material/Loupe'; class Images extends Component { constructor(props) { super(props); this.state = { mainPic:0,pics:[], needsSocketRetry: false }; } componentDidMount () { this.updatePics(0); } componentDidUpdate(prevProps) { if (prevProps.fullscreenOpen !== this.props.fullscreenOpen) { this.updatePics(); } // Retry loading images if socket just became available const wasConnected = prevProps.socketB && prevProps.socketB.connected; const isNowConnected = this.props.socketB && this.props.socketB.connected; if (!wasConnected && isNowConnected && this.state.needsSocketRetry) { this.setState({ needsSocketRetry: false }); this.updatePics(); } } updatePics = (newMainPic = this.state.mainPic) => { if (!window.tinyPicCache) window.tinyPicCache = {}; if (!window.smallPicCache) window.smallPicCache = {}; if (!window.mediumPicCache) window.mediumPicCache = {}; if (!window.largePicCache) window.largePicCache = {}; if(this.props.pictureList && this.props.pictureList.length > 0){ const bildIds = this.props.pictureList.split(','); const pics = []; const mainPicId = bildIds[newMainPic]; for(const bildId of bildIds){ if(bildId == mainPicId){ if(window.largePicCache[bildId]){ pics.push(window.largePicCache[bildId]); }else if(window.mediumPicCache[bildId]){ pics.push(window.mediumPicCache[bildId]); if(this.props.fullscreenOpen) this.loadPic('large',bildId,newMainPic); }else if(window.smallPicCache[bildId]){ pics.push(window.smallPicCache[bildId]); this.loadPic(this.props.fullscreenOpen ? 'large' : 'medium',bildId,newMainPic); }else if(window.tinyPicCache[bildId]){ pics.push(window.tinyPicCache[bildId]); this.loadPic(this.props.fullscreenOpen ? 'large' : 'medium',bildId,newMainPic); }else{ pics.push(`/assets/images/prod${bildId}.jpg`); this.loadPic(this.props.fullscreenOpen ? 'large' : 'medium',bildId,newMainPic); } }else{ if(window.tinyPicCache[bildId]){ pics.push(window.tinyPicCache[bildId]); }else if(window.mediumPicCache[bildId]){ pics.push(window.mediumPicCache[bildId]); this.loadPic('tiny',bildId,newMainPic); }else{ pics.push(null); this.loadPic('tiny',bildId,pics.length-1); } } } console.log('DEBUG: pics array contents:', pics); console.log('DEBUG: pics array types:', pics.map(p => typeof p + ': ' + p)); this.setState({ pics, mainPic: newMainPic }); }else{ if(this.state.pics.length > 0) this.setState({ pics:[], mainPic: newMainPic }); } } loadPic = (size,bildId,index) => { // Check if socketB is available and connected before emitting if (!this.props.socketB || !this.props.socketB.connected) { console.log("Images: socketB not available, will retry when connected"); this.setState({ needsSocketRetry: true }); return; } this.props.socketB.emit('getPic', { bildId, size }, (res) => { if(res.success){ const url = URL.createObjectURL(new Blob([res.imageBuffer], { type: 'image/jpeg' })); if(size === 'medium') window.mediumPicCache[bildId] = url; if(size === 'small') window.smallPicCache[bildId] = url; if(size === 'tiny') window.tinyPicCache[bildId] = url; if(size === 'large') window.largePicCache[bildId] = url; const pics = this.state.pics; pics[index] = url this.setState({ pics }); } }) } handleThumbnailClick = (clickedPic) => { // Find the original index of the clicked picture in the full pics array const originalIndex = this.state.pics.findIndex(pic => pic === clickedPic); if (originalIndex !== -1) { this.updatePics(originalIndex); } } render() { // Prerender detection - if no sockets, render simple CardMedia with static path if (!this.props.socketB) { const getImagePath = (pictureList) => { if (!pictureList || !pictureList.trim()) { return '/assets/images/nopicture.jpg'; } return `/assets/images/prod${pictureList.split(',')[0].trim()}.jpg`; }; return ( <> {/* Empty thumbnail gallery for prerender - reserves the mt+mb spacing (16px) */} ); } // SPA version - full functionality with static fallback const getImageSrc = () => { // If dynamic image is loaded, use it if (this.state.pics[this.state.mainPic]) { return this.state.pics[this.state.mainPic]; } // Otherwise, use static fallback (same as prerender) if (!this.props.pictureList || !this.props.pictureList.trim()) { return '/assets/images/nopicture.jpg'; } return `/assets/images/prod${this.props.pictureList.split(',')[0].trim()}.jpg`; }; return ( <> {this.state.pics.filter(pic => pic !== null && pic !== this.state.pics[this.state.mainPic]).map((pic, filterIndex) => { // Find the original index in the full pics array const originalIndex = this.state.pics.findIndex(p => p === pic); return ( this.handleThumbnailClick(pic)} /> ); })} {/* Fullscreen Dialog */} { // Only close if clicking on the background (DialogContent itself) if (e.target === e.currentTarget) { this.props.onCloseFullscreen(); } }} > {/* Close Button */} {/* Main Image in Fullscreen */} {this.state.pics[this.state.mainPic] && ( )} {/* Thumbnail Stack in Fullscreen */} e.stopPropagation()} > {this.state.pics.filter(pic => pic !== null && pic !== this.state.pics[this.state.mainPic]).map((pic, filterIndex) => { // Find the original index in the full pics array const originalIndex = this.state.pics.findIndex(p => p === pic); return ( this.handleThumbnailClick(pic)} /> ); })} ); } } export default Images;