"use client"; import React from "react"; import Image from "next/image"; import { Sparkles } from "lucide-react"; import { cn } from "../lib/utils"; import { useSettingsStore } from "../lib/store/settingsStore"; import { getMediaUrl } from "../lib/media"; interface SafeImageProps extends Omit, 'src'> { src?: string; alt?: string; className?: string; imgClassName?: string; fallbackText?: string; priority?: boolean; sizes?: string; quality?: number; width?: number; height?: number; } export default function SafeImage({ src: rawSrc, alt = "تصویر مکمل کنینا", className, imgClassName, fallbackText = "در حال بروزرسانی تصویر...", priority = false, sizes = "(max-width: 640px) 200px, (max-width: 1024px) 300px, 400px", quality = 75, width = 500, height = 500, }: SafeImageProps) { const [error, setError] = React.useState(false); const [loading, setLoading] = React.useState(!priority); const logoUrl = useSettingsStore(state => state.getText('site_logo', '')); const src = React.useMemo(() => getMediaUrl(rawSrc), [rawSrc]); // 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 (
{logoUrl ? ( {alt ) : (
CANINA
)} Canina Pharma {fallbackText}
); } return (
{loading && !priority && (
)} {alt} setLoading(false)} onError={() => setError(true)} />
); }