import React from 'react'; import Box from "@mui/material/Box"; import Typography from "@mui/material/Typography"; import { withTranslation } from 'react-i18next'; import { withLanguage } from '../i18n/withTranslation.js'; const ITEM_WIDTH = 140 + 16; // 140px width + 16px gap const AUTO_SCROLL_SPEED = 1.0; class ManufacturerCarousel extends React.Component { _isMounted = false; originalItems = []; animationFrame = null; translateX = 0; constructor(props) { super(props); this.state = { items: [], // [{ id, name, src }] }; this.carouselTrackRef = React.createRef(); } componentDidMount() { this._isMounted = true; this.loadImages(); } componentWillUnmount() { this._isMounted = false; if (this.animationFrame) { cancelAnimationFrame(this.animationFrame); this.animationFrame = null; } // Revoke object URLs to avoid memory leaks for (const item of this.originalItems) { if (item.src) URL.revokeObjectURL(item.src); } } loadImages = () => { window.socketManager.emit('getHerstellerImages', {}, (res) => { if (!this._isMounted || !res?.success || !res.manufacturers?.length) return; const items = res.manufacturers .filter(m => m.imageBuffer) .map(m => { const blob = new Blob([m.imageBuffer], { type: 'image/avif' }); return { id: m.id, name: m.name || '', src: URL.createObjectURL(blob) }; }) .sort(() => Math.random() - 0.5); if (items.length === 0) return; this.originalItems = items; this.setState({ items: [...items, ...items] }, () => { this.startAutoScroll(); }); }); }; startAutoScroll = () => { if (!this.animationFrame) { this.animationFrame = requestAnimationFrame(this.tick); } }; tick = () => { if (!this._isMounted || this.originalItems.length === 0) return; this.translateX -= AUTO_SCROLL_SPEED; const maxScroll = ITEM_WIDTH * this.originalItems.length; if (Math.abs(this.translateX) >= maxScroll) { this.translateX = 0; } if (this.carouselTrackRef.current) { this.carouselTrackRef.current.style.transform = `translateX(${this.translateX}px)`; } this.animationFrame = requestAnimationFrame(this.tick); }; render() { const { t } = this.props; const { items } = this.state; if (!items || items.length === 0) return null; return ( {t('product.manufacturer')}
{/* Fade edges */}
{items.map((item, index) => (
{item.name}
))}
); } } export default withTranslation()(withLanguage(ManufacturerCarousel));