fluffychat/lib/widgets/avatar.dart

152 lines
4.6 KiB
Dart
Raw Normal View History

2020-01-01 18:10:13 +00:00
import 'package:flutter/material.dart';
2021-10-26 16:50:34 +00:00
import 'package:matrix/matrix.dart';
2020-01-01 18:10:13 +00:00
2021-10-26 16:50:34 +00:00
import 'package:fluffychat/utils/string_color.dart';
import 'package:fluffychat/widgets/mxc_image.dart';
2023-11-11 16:56:23 +00:00
import 'package:fluffychat/widgets/presence_builder.dart';
2020-01-01 18:10:13 +00:00
class Avatar extends StatelessWidget {
2021-11-19 19:38:16 +00:00
final Uri? mxContent;
final String? name;
2020-01-01 18:10:13 +00:00
final double size;
2021-11-19 19:38:16 +00:00
final void Function()? onTap;
2020-03-13 20:42:05 +00:00
static const double defaultSize = 44;
2021-11-19 19:38:16 +00:00
final Client? client;
2023-11-11 16:56:23 +00:00
final String? presenceUserId;
final Color? presenceBackgroundColor;
2024-07-14 14:49:46 +00:00
final BorderRadius? borderRadius;
final IconData? icon;
2024-07-15 11:18:15 +00:00
final BorderSide? border;
2020-01-01 18:10:13 +00:00
2021-11-20 09:42:23 +00:00
const Avatar({
2020-03-13 20:42:05 +00:00
this.mxContent,
2021-11-20 09:42:23 +00:00
this.name,
2020-03-13 20:42:05 +00:00
this.size = defaultSize,
this.onTap,
2021-01-20 19:27:09 +00:00
this.client,
2023-11-11 16:56:23 +00:00
this.presenceUserId,
this.presenceBackgroundColor,
2024-07-14 14:49:46 +00:00
this.borderRadius,
2024-07-15 11:18:15 +00:00
this.border,
2024-07-14 14:49:46 +00:00
this.icon,
super.key,
});
2020-01-01 18:10:13 +00:00
@override
Widget build(BuildContext context) {
2020-05-13 13:58:59 +00:00
var fallbackLetters = '@';
2021-11-19 19:38:16 +00:00
final name = this.name;
if (name != null) {
if (name.runes.length >= 2) {
fallbackLetters = String.fromCharCodes(name.runes, 0, 2);
} else if (name.runes.length == 1) {
fallbackLetters = name;
}
2020-01-18 12:22:22 +00:00
}
final noPic = mxContent == null ||
mxContent.toString().isEmpty ||
mxContent.toString() == 'null';
2024-07-19 12:50:17 +00:00
final textColor = name?.lightColorAvatar;
final textWidget = Container(
2024-07-19 12:50:17 +00:00
color: textColor,
alignment: Alignment.center,
child: Text(
fallbackLetters,
style: TextStyle(
color: Colors.white,
2024-07-19 13:30:04 +00:00
fontWeight: FontWeight.bold,
fontSize: (size / 3).roundToDouble(),
),
),
);
2024-07-14 14:49:46 +00:00
final borderRadius = this.borderRadius ?? BorderRadius.circular(size / 2);
2023-11-11 16:56:23 +00:00
final presenceUserId = this.presenceUserId;
final container = Stack(
children: [
2024-07-14 14:49:46 +00:00
SizedBox(
width: size,
height: size,
child: Material(
2024-07-20 06:01:06 +00:00
color: Theme.of(context).brightness == Brightness.light
? Colors.white
: Colors.black,
2024-07-14 14:49:46 +00:00
shape: RoundedRectangleBorder(
borderRadius: borderRadius,
2024-07-18 14:45:10 +00:00
side: border ?? BorderSide.none,
2024-07-14 14:49:46 +00:00
),
clipBehavior: Clip.hardEdge,
2023-11-11 16:56:23 +00:00
child: noPic
? textWidget
: MxcImage(
2024-07-26 17:36:07 +00:00
client: client,
2024-07-18 15:41:45 +00:00
key: ValueKey(mxContent.toString()),
cacheKey: '${mxContent}_$size',
2023-11-11 16:56:23 +00:00
uri: mxContent,
fit: BoxFit.cover,
width: size,
height: size,
2024-07-19 12:50:17 +00:00
placeholder: (_) => Center(
child: Icon(
Icons.person_2,
2024-07-19 13:30:04 +00:00
color: Theme.of(context).colorScheme.tertiary,
2024-07-19 12:50:17 +00:00
size: size / 1.5,
),
),
2023-11-11 16:56:23 +00:00
),
),
),
2024-07-14 14:49:46 +00:00
if (presenceUserId != null)
PresenceBuilder(
client: client,
userId: presenceUserId,
builder: (context, presence) {
if (presence == null ||
(presence.presence == PresenceType.offline &&
presence.lastActiveTimestamp == null)) {
return const SizedBox.shrink();
}
final dotColor = presence.presence.isOnline
? Colors.green
: presence.presence.isUnavailable
? Colors.orange
: Colors.grey;
return Positioned(
bottom: -3,
right: -3,
2023-11-11 16:56:23 +00:00
child: Container(
2024-07-14 14:49:46 +00:00
width: 16,
height: 16,
2023-11-11 16:56:23 +00:00
decoration: BoxDecoration(
2024-07-14 14:49:46 +00:00
color: presenceBackgroundColor ??
Theme.of(context).colorScheme.surface,
borderRadius: BorderRadius.circular(32),
),
alignment: Alignment.center,
child: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color: dotColor,
borderRadius: BorderRadius.circular(16),
border: Border.all(
width: 1,
color: Theme.of(context).colorScheme.surface,
),
),
2023-11-11 16:56:23 +00:00
),
),
2024-07-14 14:49:46 +00:00
);
},
),
2023-11-11 16:56:23 +00:00
],
2020-01-01 18:10:13 +00:00
);
2022-07-08 08:41:36 +00:00
if (onTap == null) return container;
return InkWell(
onTap: onTap,
borderRadius: borderRadius,
child: container,
);
2020-01-01 18:10:13 +00:00
}
}