jld3103
2 years ago
5 changed files with 130 additions and 107 deletions
@ -1,103 +0,0 @@
|
||||
part of '../../neon.dart'; |
||||
|
||||
const kAvatarSize = 40.0; |
||||
|
||||
class NeonAccountAvatar extends StatelessWidget { |
||||
const NeonAccountAvatar({ |
||||
required this.account, |
||||
super.key, |
||||
}); |
||||
|
||||
final Account account; |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) { |
||||
final isDark = Theme.of(context).brightness == Brightness.dark; |
||||
final size = (kAvatarSize * MediaQuery.of(context).devicePixelRatio).toInt(); |
||||
final userStatusBloc = Provider.of<AccountsBloc>(context, listen: false).getUserStatusBloc(account); |
||||
return SizedBox.square( |
||||
dimension: kAvatarSize, |
||||
child: Stack( |
||||
alignment: Alignment.center, |
||||
children: [ |
||||
CircleAvatar( |
||||
child: ClipOval( |
||||
child: NeonCachedApiImage( |
||||
account: account, |
||||
cacheKey: 'avatar-${account.id}-${isDark ? 'dark' : 'light'}$size', |
||||
download: () async { |
||||
if (isDark) { |
||||
return account.client.core.getDarkAvatar( |
||||
userId: account.username, |
||||
size: size, |
||||
); |
||||
} else { |
||||
return account.client.core.getAvatar( |
||||
userId: account.username, |
||||
size: size, |
||||
); |
||||
} |
||||
}, |
||||
), |
||||
), |
||||
), |
||||
ResultBuilder<NextcloudUserStatusStatus?>( |
||||
stream: userStatusBloc.userStatus, |
||||
builder: (final context, final userStatus) { |
||||
final hasEmoji = userStatus.data?.icon != null; |
||||
final factor = hasEmoji ? 2 : 3; |
||||
return Align( |
||||
alignment: Alignment.bottomRight, |
||||
child: Container( |
||||
height: kAvatarSize / factor, |
||||
width: kAvatarSize / factor, |
||||
decoration: userStatus.loading || userStatus.error != null || userStatus.data == null || hasEmoji |
||||
? null |
||||
: BoxDecoration( |
||||
shape: BoxShape.circle, |
||||
color: _userStatusToColor(userStatus.data!), |
||||
), |
||||
child: userStatus.loading |
||||
? CircularProgressIndicator( |
||||
strokeWidth: 1.5, |
||||
color: Theme.of(context).colorScheme.onPrimary, |
||||
) |
||||
: userStatus.error != null && |
||||
(userStatus.error is! NextcloudApiException || |
||||
(userStatus.error! as NextcloudApiException).statusCode != 404) |
||||
? NeonException( |
||||
userStatus.error, |
||||
onRetry: userStatusBloc.refresh, |
||||
onlyIcon: true, |
||||
iconSize: kAvatarSize / factor, |
||||
) |
||||
: hasEmoji |
||||
? Text( |
||||
userStatus.data!.icon!, |
||||
style: const TextStyle( |
||||
fontSize: 16, |
||||
), |
||||
) |
||||
: null, |
||||
), |
||||
); |
||||
}, |
||||
), |
||||
], |
||||
), |
||||
); |
||||
} |
||||
|
||||
Color _userStatusToColor(final NextcloudUserStatusStatus userStatus) { |
||||
switch (userStatus.status) { |
||||
case NextcloudUserStatusType.online: |
||||
return const Color(0xFF49B382); |
||||
case NextcloudUserStatusType.away: |
||||
return const Color(0xFFF4A331); |
||||
case NextcloudUserStatusType.dnd: |
||||
return const Color(0xFFED484C); |
||||
default: |
||||
return Colors.transparent; |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,126 @@
|
||||
// ignore_for_file: use_late_for_private_fields_and_variables |
||||
// ^ This is a really strange false positive, it goes of at a very random place without any meaning. Hopefully fixed soon? |
||||
|
||||
part of '../../neon.dart'; |
||||
|
||||
const kAvatarSize = 40.0; |
||||
|
||||
class NeonUserAvatar extends StatefulWidget { |
||||
NeonUserAvatar({ |
||||
required this.account, |
||||
final String? username, |
||||
this.showStatus = true, |
||||
this.size = kAvatarSize, |
||||
super.key, |
||||
}) : username = username ?? account.client.username!; |
||||
|
||||
final Account account; |
||||
final String username; |
||||
final bool showStatus; |
||||
final double size; |
||||
|
||||
@override |
||||
State<NeonUserAvatar> createState() => _UserAvatarState(); |
||||
} |
||||
|
||||
class _UserAvatarState extends State<NeonUserAvatar> { |
||||
late final _userStatusBloc = Provider.of<AccountsBloc>(context, listen: false).getUserStatusesBloc(widget.account); |
||||
|
||||
@override |
||||
void initState() { |
||||
super.initState(); |
||||
|
||||
unawaited(_userStatusBloc.load(widget.username)); |
||||
} |
||||
|
||||
@override |
||||
Widget build(final BuildContext context) { |
||||
final isDark = Theme.of(context).brightness == Brightness.dark; |
||||
final size = (widget.size * MediaQuery.of(context).devicePixelRatio).toInt(); |
||||
return Stack( |
||||
alignment: Alignment.center, |
||||
children: [ |
||||
CircleAvatar( |
||||
radius: widget.size / 2, |
||||
child: ClipOval( |
||||
child: NeonCachedApiImage( |
||||
account: widget.account, |
||||
cacheKey: 'avatar-${widget.username}-${isDark ? 'dark' : 'light'}$size', |
||||
download: () async { |
||||
if (isDark) { |
||||
return widget.account.client.core.getDarkAvatar( |
||||
userId: widget.username, |
||||
size: size, |
||||
); |
||||
} else { |
||||
return widget.account.client.core.getAvatar( |
||||
userId: widget.username, |
||||
size: size, |
||||
); |
||||
} |
||||
}, |
||||
), |
||||
), |
||||
), |
||||
if (widget.showStatus) ...[ |
||||
ResultBuilder<NextcloudUserStatusPublicStatus?>( |
||||
stream: _userStatusBloc.statuses.map((final statuses) => statuses[widget.username]), |
||||
builder: _userStatusIconBuilder, |
||||
), |
||||
], |
||||
], |
||||
); |
||||
} |
||||
|
||||
Widget _userStatusIconBuilder(final BuildContext context, final Result<NextcloudUserStatusPublicStatus?> result) { |
||||
final hasEmoji = result.data?.icon != null; |
||||
final scaledSize = widget.size / (hasEmoji ? 2 : 3); |
||||
|
||||
Widget? child; |
||||
Decoration? decoration; |
||||
if (result.loading) { |
||||
child = CircularProgressIndicator( |
||||
strokeWidth: 1.5, |
||||
color: Theme.of(context).colorScheme.onPrimary, |
||||
); |
||||
} else if (result.error != null) { |
||||
child = Icon( |
||||
Icons.error_outline, |
||||
size: scaledSize, |
||||
color: Theme.of(context).colorScheme.error, |
||||
); |
||||
} else if (hasEmoji) { |
||||
child = Text( |
||||
result.data!.icon!, |
||||
style: const TextStyle( |
||||
fontSize: 16, |
||||
), |
||||
); |
||||
} else if (result.data != null) { |
||||
decoration = BoxDecoration( |
||||
shape: BoxShape.circle, |
||||
color: _userStatusToColor(result.data!.status), |
||||
); |
||||
} |
||||
|
||||
return SizedBox.square( |
||||
dimension: widget.size, |
||||
child: Align( |
||||
alignment: Alignment.bottomRight, |
||||
child: Container( |
||||
width: scaledSize, |
||||
height: scaledSize, |
||||
decoration: decoration, |
||||
child: child, |
||||
), |
||||
), |
||||
); |
||||
} |
||||
|
||||
Color? _userStatusToColor(final NextcloudUserStatusType userStatusType) => switch (userStatusType) { |
||||
NextcloudUserStatusType.online => const Color(0xFF49B382), |
||||
NextcloudUserStatusType.away => const Color(0xFFF4A331), |
||||
NextcloudUserStatusType.dnd => const Color(0xFFED484C), |
||||
_ => null, |
||||
}; |
||||
} |
Loading…
Reference in new issue