M3 Overhaul
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
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,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user