86 lines
2.1 KiB
Dart
86 lines
2.1 KiB
Dart
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,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|