feat: display and crop the user avatar correctly
This commit is contained in:
parent
1c8e357722
commit
2a05a9f8df
@ -1,24 +1,20 @@
|
||||
class PostCreator {
|
||||
final String id;
|
||||
final String displayName;
|
||||
final String? avatar;
|
||||
|
||||
PostCreator({
|
||||
required this.id,
|
||||
required this.displayName,
|
||||
});
|
||||
PostCreator({required this.id, required this.displayName, this.avatar});
|
||||
|
||||
factory PostCreator.fromJson(Map<String, dynamic> json) {
|
||||
return PostCreator(
|
||||
id: json['id']?.toString() ?? '',
|
||||
displayName: json['displayName'] ?? '',
|
||||
avatar: json['avatar']?.toString(),
|
||||
);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'id': id,
|
||||
'displayName': displayName,
|
||||
};
|
||||
return {'id': id, 'displayName': displayName, 'avatar': avatar};
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +49,9 @@ class Post {
|
||||
body: json['body'] ?? '',
|
||||
likes: int.tryParse(json['likes']?.toString() ?? '0') ?? 0,
|
||||
comments: int.tryParse(json['comments']?.toString() ?? '0') ?? 0,
|
||||
creationDate: DateTime.parse(json['creationDate'] ?? DateTime.now().toIso8601String()),
|
||||
creationDate: DateTime.parse(
|
||||
json['creationDate'] ?? DateTime.now().toIso8601String(),
|
||||
),
|
||||
liked: json['liked'] == true,
|
||||
images: json['images'] != null ? List<String>.from(json['images']) : null,
|
||||
);
|
||||
@ -113,7 +111,9 @@ class LikedUser {
|
||||
return LikedUser(
|
||||
id: json['id']?.toString() ?? '',
|
||||
displayName: json['displayName'] ?? '',
|
||||
likeTime: DateTime.parse(json['likeTime'] ?? DateTime.now().toIso8601String()),
|
||||
likeTime: DateTime.parse(
|
||||
json['likeTime'] ?? DateTime.now().toIso8601String(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -157,10 +157,14 @@ class DetailedPost {
|
||||
likes: int.tryParse(json['likes']?.toString() ?? '0') ?? 0,
|
||||
comments: int.tryParse(json['comments']?.toString() ?? '0') ?? 0,
|
||||
liked: json['liked'] == true,
|
||||
creationDate: DateTime.parse(json['creationDate'] ?? DateTime.now().toIso8601String()),
|
||||
likedUsers: (json['likedUsers'] as List?)
|
||||
?.map((user) => LikedUser.fromJson(user))
|
||||
.toList() ?? [],
|
||||
creationDate: DateTime.parse(
|
||||
json['creationDate'] ?? DateTime.now().toIso8601String(),
|
||||
),
|
||||
likedUsers:
|
||||
(json['likedUsers'] as List?)
|
||||
?.map((user) => LikedUser.fromJson(user))
|
||||
.toList() ??
|
||||
[],
|
||||
images: json['images'] != null ? List<String>.from(json['images']) : null,
|
||||
);
|
||||
}
|
||||
@ -186,8 +190,6 @@ class CreatePostRequest {
|
||||
CreatePostRequest({required this.body});
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'body': body,
|
||||
};
|
||||
return {'body': body};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -380,6 +380,98 @@ class PostImagesCarousel extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class UserAvatar extends StatelessWidget {
|
||||
final String displayName;
|
||||
final String? avatarUrl;
|
||||
final double radius;
|
||||
final Color? backgroundColor;
|
||||
|
||||
const UserAvatar({
|
||||
Key? key,
|
||||
required this.displayName,
|
||||
this.avatarUrl,
|
||||
this.radius = 20,
|
||||
this.backgroundColor,
|
||||
}) : super(key: key);
|
||||
|
||||
Color _getAvatarColor(String displayName) {
|
||||
final colors = [
|
||||
Color(0xFF32B0A5),
|
||||
Color(0xFF4600B9),
|
||||
Color(0xFF6A4C93),
|
||||
Color(0xFFFF6347),
|
||||
Color(0xFF32CD32),
|
||||
Color(0xFF9932CC),
|
||||
];
|
||||
|
||||
int hash = displayName.hashCode;
|
||||
return colors[hash.abs() % colors.length];
|
||||
}
|
||||
|
||||
String _getAvatarLetter(String displayName) {
|
||||
return displayName.isNotEmpty ? displayName[0].toUpperCase() : '?';
|
||||
}
|
||||
|
||||
bool _isValidImageUrl(String? url) {
|
||||
return url != null && url.isNotEmpty && url.trim().isNotEmpty;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final color = backgroundColor ?? _getAvatarColor(displayName);
|
||||
final letter = _getAvatarLetter(displayName);
|
||||
|
||||
return CircleAvatar(
|
||||
radius: radius,
|
||||
backgroundColor: color,
|
||||
child: _isValidImageUrl(avatarUrl)
|
||||
? ClipOval(
|
||||
child: Image.network(
|
||||
avatarUrl!,
|
||||
width: radius * 2,
|
||||
height: radius * 2,
|
||||
fit: BoxFit.cover,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
return SizedBox(
|
||||
width: radius * 2,
|
||||
height: radius * 2,
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: radius * 0.6,
|
||||
height: radius * 0.6,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Text(
|
||||
letter,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: radius * 0.8,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
: Text(
|
||||
letter,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: radius * 0.8,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class PostCard extends StatefulWidget {
|
||||
final Post post;
|
||||
|
||||
@ -413,24 +505,6 @@ class _PostCardState extends State<PostCard> {
|
||||
}
|
||||
}
|
||||
|
||||
Color _getAvatarColor(String displayName) {
|
||||
final colors = [
|
||||
Color(0xFF32B0A5),
|
||||
Color(0xFF4600B9),
|
||||
Color(0xFF6A4C93),
|
||||
Color(0xFFFF6347),
|
||||
Color(0xFF32CD32),
|
||||
Color(0xFF9932CC),
|
||||
];
|
||||
|
||||
int hash = displayName.hashCode;
|
||||
return colors[hash.abs() % colors.length];
|
||||
}
|
||||
|
||||
String _getAvatarLetter(String displayName) {
|
||||
return displayName.isNotEmpty ? displayName[0].toUpperCase() : '?';
|
||||
}
|
||||
|
||||
void _sharePost(Post post) {
|
||||
final shareText =
|
||||
'${post.creator.displayName} posted on Wesal.online:\n\n${post.body}';
|
||||
@ -503,8 +577,6 @@ class _PostCardState extends State<PostCard> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final creator = _currentPost.creator;
|
||||
final avatarColor = _getAvatarColor(creator.displayName);
|
||||
final avatarLetter = _getAvatarLetter(creator.displayName);
|
||||
final relativeTime = InvitationUtils.getRelativeTime(
|
||||
_currentPost.creationDate,
|
||||
);
|
||||
@ -538,17 +610,10 @@ class _PostCardState extends State<PostCard> {
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
CircleAvatar(
|
||||
UserAvatar(
|
||||
displayName: creator.displayName,
|
||||
avatarUrl: creator.avatar,
|
||||
radius: 20,
|
||||
backgroundColor: avatarColor,
|
||||
child: Text(
|
||||
avatarLetter,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(width: 12),
|
||||
Expanded(
|
||||
|
||||
Loading…
Reference in New Issue
Block a user