From c1aef89b84d6ff14c2be9020e45b97e97a27f344 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 9 Mar 2025 12:57:37 +0800 Subject: [PATCH] :recycle: Refactor account badge showing --- lib/screens/account/profile_page.dart | 30 +------------- lib/widgets/account/account_popover.dart | 50 ++++++++++-------------- lib/widgets/account/badge.dart | 50 ++++++++++++++++++++++++ lib/widgets/chat/chat_message.dart | 18 +++------ lib/widgets/post/post_item.dart | 22 +++-------- lib/widgets/post/publisher_popover.dart | 36 +++++------------ 6 files changed, 92 insertions(+), 114 deletions(-) create mode 100644 lib/widgets/account/badge.dart diff --git a/lib/screens/account/profile_page.dart b/lib/screens/account/profile_page.dart index e7946ce..5b3cd56 100644 --- a/lib/screens/account/profile_page.dart +++ b/lib/screens/account/profile_page.dart @@ -18,6 +18,7 @@ import 'package:surface/types/account.dart'; import 'package:surface/types/check_in.dart'; import 'package:surface/types/post.dart'; import 'package:surface/widgets/account/account_image.dart'; +import 'package:surface/widgets/account/badge.dart'; import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/universal_image.dart'; import 'package:surface/theme.dart'; @@ -484,34 +485,7 @@ class _UserScreenState extends State Wrap( children: _account!.badges .map( - (ele) => Tooltip( - richMessage: TextSpan( - children: [ - TextSpan( - text: kBadgesMeta[ele.type]?.$1.tr() ?? - 'unknown'.tr(), - ), - if (ele.metadata['title'] != null) - TextSpan( - text: '\n${ele.metadata['title']}', - style: const TextStyle( - fontWeight: FontWeight.bold), - ), - TextSpan(text: '\n'), - TextSpan( - text: DateFormat.yMEd().format(ele.createdAt), - ), - ], - ), - child: Icon( - kBadgesMeta[ele.type]?.$2 ?? - Symbols.question_mark, - color: ele.metadata['color'] != null - ? HexColor.fromHex(ele.metadata['color']!) - : kBadgesMeta[ele.type]?.$3, - fill: 1, - ), - ), + (ele) => AccountBadge(badge: ele), ) .toList(), ).padding(horizontal: 8), diff --git a/lib/widgets/account/account_popover.dart b/lib/widgets/account/account_popover.dart index 5eec0de..4ddf674 100644 --- a/lib/widgets/account/account_popover.dart +++ b/lib/widgets/account/account_popover.dart @@ -8,9 +8,9 @@ import 'package:relative_time/relative_time.dart'; import 'package:styled_widget/styled_widget.dart'; import 'package:surface/providers/experience.dart'; import 'package:surface/providers/sn_network.dart'; -import 'package:surface/screens/account/profile_page.dart'; import 'package:surface/types/account.dart'; import 'package:surface/widgets/account/account_image.dart'; +import 'package:surface/widgets/account/badge.dart'; import 'package:surface/widgets/universal_image.dart'; class AccountPopoverCard extends StatelessWidget { @@ -72,37 +72,21 @@ class AccountPopoverCard extends StatelessWidget { const Gap(8) ], ).padding(horizontal: 16), - if (data.badges.isNotEmpty) const Gap(12), if (data.badges.isNotEmpty) Wrap( spacing: 4, children: data.badges .map( - (ele) => Tooltip( - richMessage: TextSpan( - children: [ - TextSpan(text: kBadgesMeta[ele.type]?.$1.tr() ?? 'unknown'.tr()), - if (ele.metadata['title'] != null) - TextSpan( - text: '\n${ele.metadata['title']}', - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan(text: '\n'), - TextSpan( - text: DateFormat.yMEd().format(ele.createdAt), - ), - ], - ), - child: Icon( - kBadgesMeta[ele.type]?.$2 ?? Symbols.question_mark, - color: kBadgesMeta[ele.type]?.$3, - fill: 1, - ), - ), + (ele) => AccountBadge(badge: ele), ) .toList(), - ).padding(horizontal: 24), - const Gap(8), + ).padding(horizontal: 24, bottom: 12, top: 12), + if (data.profile?.description.isNotEmpty ?? false) + Text( + data.profile?.description ?? '', + maxLines: 2, + overflow: TextOverflow.ellipsis, + ).padding(horizontal: 26, bottom: 8), Row( crossAxisAlignment: CrossAxisAlignment.center, children: [ @@ -110,7 +94,9 @@ class AccountPopoverCard extends StatelessWidget { const Gap(8), Text('Lv${getLevelFromExp(data.profile?.experience ?? 0)}'), const Gap(8), - Text(calcLevelUpProgressLevel(data.profile?.experience ?? 0)).fontSize(11).opacity(0.5), + Text(calcLevelUpProgressLevel(data.profile?.experience ?? 0)) + .fontSize(11) + .opacity(0.5), const Gap(8), Container( width: double.infinity, @@ -126,15 +112,17 @@ class AccountPopoverCard extends StatelessWidget { FutureBuilder( future: sn.client.get('/cgi/id/users/${data.name}/status'), builder: (context, snapshot) { - final SnAccountStatusInfo? status = - snapshot.hasData ? SnAccountStatusInfo.fromJson(snapshot.data!.data) : null; + final SnAccountStatusInfo? status = snapshot.hasData + ? SnAccountStatusInfo.fromJson(snapshot.data!.data) + : null; return Row( children: [ Icon( Symbols.circle, fill: 1, size: 16, - color: (status?.isOnline ?? false) ? Colors.green : Colors.grey, + color: + (status?.isOnline ?? false) ? Colors.green : Colors.grey, ).padding(all: 4), const Gap(8), Text( @@ -144,7 +132,9 @@ class AccountPopoverCard extends StatelessWidget { : 'accountStatusOffline'.tr() : 'loading'.tr(), ), - if (status != null && !status.isOnline && status.lastSeenAt != null) + if (status != null && + !status.isOnline && + status.lastSeenAt != null) Text( 'accountStatusLastSeen'.tr(args: [ status.lastSeenAt != null diff --git a/lib/widgets/account/badge.dart b/lib/widgets/account/badge.dart new file mode 100644 index 0000000..b0f9aac --- /dev/null +++ b/lib/widgets/account/badge.dart @@ -0,0 +1,50 @@ +import 'package:easy_localization/easy_localization.dart'; +import 'package:flutter/material.dart'; +import 'package:material_symbols_icons/symbols.dart'; +import 'package:surface/screens/account/profile_page.dart' show kBadgesMeta; +import 'package:surface/types/account.dart'; + +class AccountBadge extends StatelessWidget { + final SnAccountBadge badge; + final double radius; + final EdgeInsets? padding; + const AccountBadge({ + super.key, + required this.badge, + this.radius = 20, + this.padding, + }); + + @override + Widget build(BuildContext context) { + return Tooltip( + richMessage: TextSpan( + children: [ + TextSpan(text: kBadgesMeta[badge.type]?.$1.tr() ?? 'unknown'.tr()), + if (badge.metadata['title'] != null) + TextSpan( + text: '\n${badge.metadata['title']}', + style: const TextStyle(fontWeight: FontWeight.bold), + ), + TextSpan(text: '\n'), + TextSpan( + text: DateFormat.yMEd().format(badge.createdAt), + ), + ], + ), + child: Container( + padding: padding ?? EdgeInsets.all(3), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(radius), + color: kBadgesMeta[badge.type]?.$3, + ), + child: Icon( + kBadgesMeta[badge.type]?.$2 ?? Symbols.question_mark, + color: Colors.white, + fill: 1, + size: radius - 4, + ), + ), + ); + } +} diff --git a/lib/widgets/chat/chat_message.dart b/lib/widgets/chat/chat_message.dart index 8739d98..805ac3a 100644 --- a/lib/widgets/chat/chat_message.dart +++ b/lib/widgets/chat/chat_message.dart @@ -12,10 +12,10 @@ import 'package:surface/providers/config.dart'; import 'package:surface/providers/keypair.dart'; import 'package:surface/providers/user_directory.dart'; import 'package:surface/providers/userinfo.dart'; -import 'package:surface/screens/account/profile_page.dart'; import 'package:surface/types/chat.dart'; import 'package:surface/widgets/account/account_image.dart'; import 'package:surface/widgets/account/account_popover.dart'; +import 'package:surface/widgets/account/badge.dart'; import 'package:surface/widgets/attachment/attachment_list.dart'; import 'package:surface/widgets/context_menu.dart'; import 'package:surface/widgets/link_preview.dart'; @@ -109,18 +109,10 @@ class ChatMessage extends StatelessWidget { child: AccountImage( content: user?.avatar, badge: (user?.badges.isNotEmpty ?? false) - ? Icon( - kBadgesMeta[user!.badges.first.type]?.$2 ?? - Symbols.question_mark, - color: kBadgesMeta[user.badges.first.type]?.$3, - fill: 1, - size: 18, - shadows: [ - Shadow( - offset: Offset(1, 1), - blurRadius: 5.0, - color: Color.fromARGB(200, 0, 0, 0)), - ], + ? AccountBadge( + badge: user!.badges.first, + radius: 16, + padding: EdgeInsets.all(2), ) : null, ), diff --git a/lib/widgets/post/post_item.dart b/lib/widgets/post/post_item.dart index bc9b6ed..b027603 100644 --- a/lib/widgets/post/post_item.dart +++ b/lib/widgets/post/post_item.dart @@ -29,6 +29,7 @@ import 'package:surface/types/attachment.dart'; import 'package:surface/types/post.dart'; import 'package:surface/types/reaction.dart'; import 'package:surface/widgets/account/account_image.dart'; +import 'package:surface/widgets/account/badge.dart'; import 'package:surface/widgets/attachment/attachment_item.dart'; import 'package:surface/widgets/attachment/attachment_list.dart'; import 'package:surface/widgets/dialog.dart'; @@ -43,8 +44,6 @@ import 'package:surface/widgets/post/publisher_popover.dart'; import 'package:surface/widgets/universal_image.dart'; import 'package:xml/xml.dart'; -import '../../screens/account/profile_page.dart' show kBadgesMeta; - class OpenablePostItem extends StatelessWidget { final SnPost data; final bool showReactions; @@ -887,7 +886,7 @@ class _PostContentHeader extends StatelessWidget { 'publisherId': data.publisherId, }); if (!context.mounted) return; - context.showSnackbar('postDeleted'.tr(args: ['#${data.id}'])); + onDeleted.call(); } catch (err) { if (!context.mounted) return; context.showErrorDialog(err); @@ -930,19 +929,10 @@ class _PostContentHeader extends StatelessWidget { borderRadius: data.publisher.type == 1 ? (isCompact ? 4 : 8) : 20, badge: (user?.badges.isNotEmpty ?? false) - ? Icon( - kBadgesMeta[user!.badges.first.type]?.$2 ?? - Symbols.question_mark, - color: kBadgesMeta[user.badges.first.type]?.$3, - fill: 1, - size: 18, - shadows: [ - Shadow( - offset: Offset(1, 1), - blurRadius: 5.0, - color: Color.fromARGB(200, 0, 0, 0), - ), - ], + ? AccountBadge( + badge: user!.badges.first, + radius: 16, + padding: EdgeInsets.all(2), ) : null, ) diff --git a/lib/widgets/post/publisher_popover.dart b/lib/widgets/post/publisher_popover.dart index 28e16c0..69c04b5 100644 --- a/lib/widgets/post/publisher_popover.dart +++ b/lib/widgets/post/publisher_popover.dart @@ -9,10 +9,9 @@ import 'package:surface/providers/sn_network.dart'; import 'package:surface/providers/user_directory.dart'; import 'package:surface/types/post.dart'; import 'package:surface/widgets/account/account_image.dart'; +import 'package:surface/widgets/account/badge.dart'; import 'package:surface/widgets/universal_image.dart'; -import '../../screens/account/profile_page.dart' show kBadgesMeta; - class PublisherPopoverCard extends StatelessWidget { final SnPublisher data; @@ -76,39 +75,22 @@ class PublisherPopoverCard extends StatelessWidget { const Gap(8) ], ).padding(horizontal: 16), - if (user != null && user.badges.isNotEmpty) const Gap(16), if (user != null && user.badges.isNotEmpty) Wrap( spacing: 4, children: user.badges .map( - (ele) => Tooltip( - richMessage: TextSpan( - children: [ - TextSpan( - text: kBadgesMeta[ele.type]?.$1.tr() ?? - 'unknown'.tr()), - if (ele.metadata['title'] != null) - TextSpan( - text: '\n${ele.metadata['title']}', - style: const TextStyle(fontWeight: FontWeight.bold), - ), - TextSpan(text: '\n'), - TextSpan( - text: DateFormat.yMEd().format(ele.createdAt), - ), - ], - ), - child: Icon( - kBadgesMeta[ele.type]?.$2 ?? Symbols.question_mark, - color: kBadgesMeta[ele.type]?.$3, - fill: 1, - ), - ), + (ele) => AccountBadge(badge: ele), ) .toList(), - ).padding(horizontal: 24), + ).padding(horizontal: 24, top: 16), const Gap(16), + if (data.description.isNotEmpty) + Text( + data.description, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ).padding(horizontal: 26, bottom: 20), Row( children: [ Expanded(