Improve video loading and display with error handling and updated headers

Improves thumbnail loading in VideoCard component with error handling and updates response headers in /thumbnail route.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 50814a1e-92e4-4968-856f-7bc7eedf5e8f
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/8cc42625-c1f5-4e43-99bd-77f2c4dedee2/50814a1e-92e4-4968-856f-7bc7eedf5e8f/WNLqOHv
This commit is contained in:
sebastjanartic 2025-08-04 19:48:38 +00:00
parent b57b48818d
commit 1321038609
3 changed files with 39 additions and 13 deletions

View File

@ -61,20 +61,20 @@ export default function VideoCard({ video, onClick, onShare }: VideoCardProps) {
alt={video.title}
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
data-testid={`img-thumbnail-${video.id}`}
onLoad={() => {
console.log('Thumbnail loaded successfully:', video.thumbnailUrl);
}}
onError={(e) => {
// Create video preview iframe as fallback if thumbnail fails
console.error('Thumbnail failed to load:', video.thumbnailUrl);
// Use a data URL SVG as fallback
const target = e.target as HTMLImageElement;
const container = target.parentElement;
if (container) {
container.innerHTML = `
<iframe
src="https://iframe.mediadelivery.net/embed/476412/${video.id}?preload=metadata&muted=true&controls=false&poster=true"
class="w-full h-full object-cover"
frameborder="0"
style="pointer-events: none;"
></iframe>
`;
}
const fallbackSvg = `
<svg width="400" height="225" xmlns="http://www.w3.org/2000/svg">
<rect width="400" height="225" fill="#dc2626"/>
<text x="200" y="112" text-anchor="middle" fill="white" font-family="Arial" font-size="16">Thumbnail Error</text>
</svg>
`;
target.src = 'data:image/svg+xml;base64,' + btoa(fallbackSvg);
}}
/>

View File

@ -167,8 +167,9 @@ export async function registerRoutes(app: Express): Promise<Server> {
</svg>
`;
res.setHeader('Content-Type', 'image/svg+xml');
res.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
res.setHeader('Cache-Control', 'public, max-age=86400');
res.setHeader('Access-Control-Allow-Origin', '*');
res.send(svg);
} catch (error) {

25
test.svg Normal file
View File

@ -0,0 +1,25 @@
<svg width="400" height="225" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" style="stop-color:#1e40af;stop-opacity:1" />
<stop offset="100%" style="stop-color:#1e3a8a;stop-opacity:1" />
</linearGradient>
</defs>
<rect width="400" height="225" fill="url(#grad)" />
<!-- Play button circle -->
<circle cx="200" cy="112" r="35" fill="rgba(255,255,255,0.9)" />
<!-- Play button triangle -->
<polygon points="188,97 188,127 218,112" fill="#1e40af" />
<!-- Title background -->
<rect x="0" y="175" width="400" height="50" fill="rgba(0,0,0,0.7)" />
<!-- Title text -->
<text x="20" y="200" fill="white" font-family="Arial, sans-serif" font-size="14" font-weight="bold">Alex Reichinger - Ciao mia bella</text>
<!-- Duration -->
<text x="370" y="200" fill="white" font-family="Arial, sans-serif" font-size="12" text-anchor="end">3:02</text>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB