import { useState, useEffect } from "react"; import { BifrostImageGenerationOutput, ImageEditInput, ImageVariationInput } from "@/lib/types/logs"; import { Image, ChevronLeft, ChevronRight } from "lucide-react"; import { ImageMessage } from "@/components/chat/ImageMessage"; import { Button } from "@/components/ui/button"; import { RequestTypeLabels } from "@/lib/constants/logs"; interface ImageGenerationInput { prompt: string; } interface ImageViewProps { imageInput?: ImageGenerationInput; imageEditInput?: ImageEditInput; imageVariationInput?: ImageVariationInput; imageOutput?: BifrostImageGenerationOutput; requestType?: string; } // Detect MIME type from base64 magic bytes and return a data URL function getImageSrc(b64: string): string { if (b64.startsWith("/9j/")) return `data:image/jpeg;base64,${b64}`; if (b64.startsWith("iVBOR")) return `data:image/png;base64,${b64}`; if (b64.startsWith("UklGR")) return `data:image/webp;base64,${b64}`; if (b64.startsWith("R0lGO")) return `data:image/gif;base64,${b64}`; return `data:image/png;base64,${b64}`; } // Helper function to get method type label from request type function getMethodTypeLabel(requestType?: string): string { if (!requestType) return "Image Generation"; const normalizedType = requestType.toLowerCase(); if (normalizedType.includes("image_edit")) { return RequestTypeLabels[normalizedType as keyof typeof RequestTypeLabels] || "Image Edit"; } if (normalizedType.includes("image_variation")) { return RequestTypeLabels[normalizedType as keyof typeof RequestTypeLabels] || "Image Variation"; } return RequestTypeLabels[normalizedType as keyof typeof RequestTypeLabels] || "Image Generation"; } export default function ImageView({ imageInput, imageEditInput, imageVariationInput, imageOutput, requestType }: ImageViewProps) { const [currentIndex, setCurrentIndex] = useState(0); // Get all valid images const images = imageOutput?.data?.filter((img) => img.url || img.b64_json) ?? []; const totalImages = images.length; const currentImage = images[currentIndex] ?? null; // Get method type label const methodTypeLabel = getMethodTypeLabel(requestType); // Clamp currentIndex when images array changes to ensure it's always valid useEffect(() => { if (totalImages === 0) { setCurrentIndex(0); } else { setCurrentIndex((prev) => Math.min(prev, totalImages - 1)); } }, [totalImages]); // Looping navigation const goToPrevious = () => setCurrentIndex((prev) => (prev === 0 ? totalImages - 1 : prev - 1)); const goToNext = () => setCurrentIndex((prev) => (prev === totalImages - 1 ? 0 : prev + 1)); return (