"use client"; import React from "react"; import Image from "next/image"; import { Sparkles } from "lucide-react"; import { cn } from "../lib/utils"; interface SafeImageProps extends Omit, 'src'> { src?: string; alt?: string; className?: string; imgClassName?: string; fallbackText?: string; } export default function SafeImage({ src, alt = "تصویر مکمل کنینا", className, imgClassName, fallbackText = "در حال بروزرسانی تصویر..." }: SafeImageProps) { const [error, setError] = React.useState(false); const [loading, setLoading] = React.useState(true); // Check if external domain is in allowed remote patterns or relative path const isExternal = typeof src === 'string' && (src.startsWith('http://') || src.startsWith('https://')); const isBlobOrData = typeof src === 'string' && (src.startsWith('blob:') || src.startsWith('data:')); const isAllowedHost = React.useMemo(() => { if (!isExternal || !src) return true; try { const url = new URL(src); const allowedHosts = [ 'canina.ir', 'api.canina.ir', 'stage.canina.ir', 'stageapi.canina.ir', 'apicanina.parsaaghayi.ir', 'canina.de', 'www.canina.de', 'images.unsplash.com', 'plus.unsplash.com', 'localhost', '127.0.0.1' ]; return allowedHosts.some(h => url.hostname === h || url.hostname.endsWith(`.${h}`)); } catch { return false; } }, [src, isExternal]); if (!src || error) { return (
{alt} {fallbackText}
); } return (
{loading && (
)} {alt} setLoading(false)} onError={() => setError(true)} />
); }