import { useState, useEffect } from 'react'; import { Text, ImageStyle } from 'react-native'; import { Image } from 'expo-image'; import { LinearGradient } from 'expo-linear-gradient'; import { Radius } from '../constants/theme'; // 12 distinct dark gradients — one is assigned per title hash const GRADIENTS: [string, string][] = [ ['#12234a', '#1e4080'], ['#1a0e3a', '#3d1a7a'], ['#0e2a3a', '#1a5a7a'], ['#2a0e1e', '#6a1a3e'], ['#0e2a1e', '#1a6a3e'], ['#2a1e0e', '#7a4a1e'], ['#1e0e2a', '#4a1e6a'], ['#0e1e2a', '#1e4a6a'], ['#2a0e2a', '#6a1a6a'], ['#1e2a0e', '#4a6a1e'], ['#2a1e1e', '#6a3a3a'], ['#0e2a2a', '#1a6a6a'], ]; function textHash(s: string): number { let h = 0; for (const c of s) h = (Math.imul(31, h) + c.charCodeAt(0)) | 0; return Math.abs(h); } interface Props { uri: string | null; title: string; size: number; radius?: number; style?: ImageStyle; blurRadius?: number; } export default function CoverImage({ uri, title, size, radius = Radius.sm, style, blurRadius }: Props) { const [failed, setFailed] = useState(false); // Reset error state when URI changes (new track loaded) useEffect(() => { setFailed(false); }, [uri]); if (uri && !failed) { return ( setFailed(true)} /> ); } const [c1, c2] = GRADIENTS[textHash(title || '') % GRADIENTS.length]; const letter = (title || '?').trim().toUpperCase()[0]; const fontSize = size * 0.36; return ( {letter} ); }