import 'package:flutter/material.dart'; /// Native Flutter profile avatar that displays either: /// 1. User's avatar image URL (if provided) /// 2. Initials derived from full name (fallback) class ProfileAvatar extends StatelessWidget { const ProfileAvatar({ super.key, required this.fullName, this.avatarUrl, this.radius = 18, }); final String fullName; final String? avatarUrl; final double radius; String _getInitials() { final trimmed = fullName.trim(); if (trimmed.isEmpty) return 'U'; final parts = trimmed.split(RegExp(r'\s+')); if (parts.length == 1) { return parts[0].substring(0, 1).toUpperCase(); } // Get first letter of first and last name return '${parts.first[0]}${parts.last[0]}'.toUpperCase(); } Color _getInitialsColor(String initials) { // Generate a deterministic color based on initials final hash = initials.codeUnitAt(0) + (initials.length > 1 ? initials.codeUnitAt(1) * 256 : 0); final colors = [ Colors.red, Colors.pink, Colors.purple, Colors.deepPurple, Colors.indigo, Colors.blue, Colors.lightBlue, Colors.cyan, Colors.teal, Colors.green, Colors.lightGreen, Colors.orange, Colors.deepOrange, Colors.brown, ]; return colors[hash % colors.length]; } @override Widget build(BuildContext context) { final initials = _getInitials(); // If avatar URL is provided, attempt to load the image if (avatarUrl != null && avatarUrl!.isNotEmpty) { return CircleAvatar( radius: radius, backgroundImage: NetworkImage(avatarUrl!), onBackgroundImageError: (_, __) { // Silently fall back to initials if image fails }, child: null, // Image will display if loaded successfully ); } // Fallback to initials return CircleAvatar( radius: radius, backgroundColor: _getInitialsColor(initials), child: Text( initials, style: TextStyle( color: Colors.white, fontSize: radius * 0.8, fontWeight: FontWeight.w600, ), ), ); } }