import React, { memo, useEffect, useState } from 'react'; import { Website } from '../types'; import { cacheWebsiteIcon, getCachedWebsiteIcon, removeCachedWebsiteIcon } from './utils/iconService'; interface WebsiteTileProps { website: Website; isEditing: boolean; onEdit: (website: Website) => void; onMove: (website: Website, direction: 'left' | 'right') => void; tileSize?: string; } const getTileSizeClass = (size: string | undefined) => { switch (size) { case 'small': return 'w-28 h-28'; case 'medium': return 'w-32 h-32'; case 'large': return 'w-36 h-36'; default: return 'w-32 h-32'; } }; const getIconPixelSize = (size: string | undefined): number => { switch (size) { case 'small': return 34; case 'medium': return 42; case 'large': return 48; default: return 40; } }; const getIconLoadingPixelSize = (size: string | undefined): number => { switch (size) { case 'small': return 24; case 'medium': return 32; case 'large': return 40; default: return 32; } }; const WebsiteTile: React.FC = ({ website, isEditing, onEdit, onMove, tileSize }) => { const [isLoading, setIsLoading] = useState(false); const [iconSource, setIconSource] = useState(null); const [usingCachedIcon, setUsingCachedIcon] = useState(false); useEffect(() => { let cancelled = false; setIconSource(null); setUsingCachedIcon(false); const loadIcon = async () => { const cachedIcon = await getCachedWebsiteIcon(website.icon); if (cancelled) return; if (cachedIcon) { setIconSource(cachedIcon); setUsingCachedIcon(cachedIcon !== website.icon); return; } setIconSource(website.icon); const newlyCachedIcon = await cacheWebsiteIcon(website.icon); if (!cancelled && newlyCachedIcon) { setIconSource(newlyCachedIcon); setUsingCachedIcon(newlyCachedIcon !== website.icon); } }; void loadIcon(); return () => { cancelled = true; }; }, [website.icon]); const handleIconError = () => { if (!usingCachedIcon) return; setIconSource(website.icon); setUsingCachedIcon(false); void removeCachedWebsiteIcon(website.icon); }; const handleClick = (e: React.MouseEvent) => { if (isEditing) { e.preventDefault(); return; } setIsLoading(true); }; const iconSizeClass = `w-[${getIconPixelSize(tileSize)}px] h-[${getIconPixelSize(tileSize)}px]`; const iconSizeLoadingClass = `w-[${getIconLoadingPixelSize(tileSize)}px] h-[${getIconLoadingPixelSize(tileSize)}px]`; return (
{isLoading && (
)}
{iconSource && ( {`${website.name} )}
{website.name}
{isEditing && (
)}
); }; export default memo(WebsiteTile);