From cb7eef943c0a8dc06d4e4a4f56159245ac21afef Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Sun, 21 Dec 2025 13:07:44 +0800 Subject: [PATCH] :lipstick: Optimized featured post --- assets/i18n/en-US.json | 2 +- assets/i18n/zh-CN.json | 2 +- lib/screens/dashboard/dash.dart | 76 ++++--------------- lib/screens/explore.dart | 24 +----- lib/widgets/account/account_name.dart | 102 +++++++++++++------------- lib/widgets/post/post_featured.dart | 67 +++++++++-------- 6 files changed, 102 insertions(+), 171 deletions(-) diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index d517369b..d56953a9 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -1508,7 +1508,7 @@ "createAccountAgreeTerms": "I've read these terms and agree to the terms of service.", "createAccountProfile": "Create your profile", "createAccountToS": "Review Terms & Conditions", - "accountActivationAlert": "Remember to activate your account", + "accountActivationAlert": "Activate your account", "accountActivationAlertHint": "Unactivated account may leads to various of permission issues, activate your account by clicking the link we sent to your email inbox.", "accountActivationResendHint": "Didn't see it? Try click the button below to resend one. If you need to update your email while your account was unactivated, feel free to contact our customer service.", "accountActivationResend": "Resend", diff --git a/assets/i18n/zh-CN.json b/assets/i18n/zh-CN.json index 9c651ef4..9c5e99ae 100644 --- a/assets/i18n/zh-CN.json +++ b/assets/i18n/zh-CN.json @@ -1486,7 +1486,7 @@ "createAccountAgreeTerms": "我已阅读并同意服务条款。", "createAccountProfile": "创建您的个人资料", "createAccountToS": "查看条款与条件", - "accountActivationAlert": "请记住激活您的账户", + "accountActivationAlert": "激活您的账户", "accountActivationAlertHint": "未激活的账户可能会导致各种权限问题,请点击我们发送到您邮箱收件箱的链接来激活您的账户。", "accountActivationResendHint": "没收到?请尝试点击下方按钮重新发送。如果您在账户未激活期间需要更新邮箱,请随时联系我们的客服。", "accountActivationResend": "重新发送", diff --git a/lib/screens/dashboard/dash.dart b/lib/screens/dashboard/dash.dart index 9cd42f65..0c36e676 100644 --- a/lib/screens/dashboard/dash.dart +++ b/lib/screens/dashboard/dash.dart @@ -13,12 +13,12 @@ import 'package:island/pods/userinfo.dart'; import 'package:island/screens/chat/chat.dart'; import 'package:island/services/event_bus.dart'; import 'package:island/services/responsive.dart'; +import 'package:island/widgets/account/account_name.dart'; import 'package:island/widgets/account/fortune_graph.dart'; import 'package:island/widgets/account/friends_overview.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/notification_tile.dart'; import 'package:island/widgets/post/post_featured.dart'; -import 'package:island/widgets/post/post_item.dart'; import 'package:island/widgets/check_in.dart'; import 'package:island/screens/notification.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart'; @@ -124,9 +124,13 @@ class _DashboardGridWide extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final userInfo = ref.watch(userInfoProvider); + return Row( spacing: 16, children: [ + if (userInfo.value != null && userInfo.value?.activatedAt == null) + SizedBox(width: 400, child: AccountUnactivatedCard()), SizedBox( width: 400, child: Column( @@ -151,7 +155,7 @@ class _DashboardGridWide extends HookConsumerWidget { ], ), ), - SizedBox(width: 400, child: FeaturedPostCard()), + SizedBox(width: 400, child: PostFeaturedList(collapsable: false)), SizedBox( width: 400, child: Column( @@ -179,12 +183,19 @@ class _DashboardGridNarrow extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final userInfo = ref.watch(userInfoProvider); + return Column( spacing: 16, children: [ + if (userInfo.value != null && userInfo.value?.activatedAt == null) + AccountUnactivatedCard(), CheckInWidget(margin: EdgeInsets.zero, checkInOnly: true), FortuneCard(), - SizedBox(height: 400, child: FeaturedPostCard()), + ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 400), + child: PostFeaturedList(), + ), FriendsOverviewWidget(), NotificationsCard(), ChatListCard(), @@ -318,65 +329,6 @@ class ClockCard extends HookConsumerWidget { } } -class FeaturedPostCard extends HookConsumerWidget { - const FeaturedPostCard({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final featuredPostsAsync = ref.watch(featuredPostsProvider); - - return ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(8)), - child: Card( - color: Theme.of(context).colorScheme.surfaceContainerHigh, - margin: EdgeInsets.zero, - child: Column( - children: [ - SizedBox( - height: 48, - child: Row( - spacing: 8, - children: [ - const Icon(Symbols.highlight), - Text('highlightPost').tr(), - ], - ).padding(horizontal: 16, vertical: 8), - ), - Expanded( - child: featuredPostsAsync.when( - loading: () => const Center(child: CircularProgressIndicator()), - error: (error, stack) => Center(child: Text('Error: $error')), - data: (posts) { - if (posts.isEmpty) { - return Padding( - padding: EdgeInsets.all(16), - child: Center( - child: Text('noFeaturedPostsAvailable').tr(), - ), - ); - } - return PageView.builder( - scrollDirection: Axis.horizontal, - itemCount: posts.length, - itemBuilder: (context, index) { - return SingleChildScrollView( - child: PostActionableItem( - item: posts[index], - borderRadius: 8, - ), - ); - }, - ); - }, - ), - ), - ], - ), - ), - ); - } -} - class NotificationsCard extends HookConsumerWidget { const NotificationsCard({super.key}); diff --git a/lib/screens/explore.dart b/lib/screens/explore.dart index be119a5e..8d7daade 100644 --- a/lib/screens/explore.dart +++ b/lib/screens/explore.dart @@ -346,29 +346,7 @@ class ExploreScreen extends HookConsumerWidget { child: Align( alignment: Alignment.topCenter, child: SingleChildScrollView( - child: Column( - spacing: 8, - children: [ - const Gap(4), - if (user.value?.activatedAt == null) - AccountUnactivatedCard(), - CheckInWidget( - margin: EdgeInsets.zero, - onChecked: () { - ref.invalidate(eventCalendarProvider(query.value)); - }, - ), - if (notificationCount.value != null && - notificationCount.value! > 0) - notificationIndicatorWidget( - context, - count: notificationCount.value ?? 0, - margin: EdgeInsets.zero, - ), - PostFeaturedList(), - FriendsOverviewWidget(), - ], - ), + child: Column(spacing: 8, children: [const Gap(4)]), ), ), ) diff --git a/lib/widgets/account/account_name.dart b/lib/widgets/account/account_name.dart index 6ac98568..51e061ac 100644 --- a/lib/widgets/account/account_name.dart +++ b/lib/widgets/account/account_name.dart @@ -219,20 +219,20 @@ class AccountName extends StatelessWidget { if (account.automatedId != null) hideOverlay ? Icon( - Symbols.smart_toy, - size: 16, - color: nameStyle.color, - fill: 1, - ) - : Tooltip( - message: 'accountAutomated'.tr(), - child: Icon( Symbols.smart_toy, size: 16, color: nameStyle.color, fill: 1, + ) + : Tooltip( + message: 'accountAutomated'.tr(), + child: Icon( + Symbols.smart_toy, + size: 16, + color: nameStyle.color, + fill: 1, + ), ), - ), ], ); } @@ -275,20 +275,20 @@ class AccountName extends StatelessWidget { if (account.automatedId != null) hideOverlay ? Icon( - Symbols.smart_toy, - size: 16, - color: nameStyle.color, - fill: 1, - ) - : Tooltip( - message: 'accountAutomated'.tr(), - child: Icon( Symbols.smart_toy, size: 16, color: nameStyle.color, fill: 1, + ) + : Tooltip( + message: 'accountAutomated'.tr(), + child: Icon( + Symbols.smart_toy, + size: 16, + color: nameStyle.color, + fill: 1, + ), ), - ), ], ); } @@ -310,29 +310,28 @@ class VerificationMark extends StatelessWidget { ? kVerificationMarkIcons[mark.type] : Symbols.verified, size: 16, - color: - (kVerificationMarkColors.length > mark.type && mark.type >= 0) - ? kVerificationMarkColors[mark.type] - : Colors.blue, + color: (kVerificationMarkColors.length > mark.type && mark.type >= 0) + ? kVerificationMarkColors[mark.type] + : Colors.blue, fill: 1, ); return hideOverlay ? icon : Tooltip( - richMessage: TextSpan( - text: mark.title ?? 'No title', - children: [ - TextSpan(text: '\n'), - TextSpan( - text: mark.description ?? 'descriptionNone'.tr(), - style: TextStyle(fontWeight: FontWeight.normal), - ), - ], - style: TextStyle(fontWeight: FontWeight.bold), - ), - child: icon, - ); + richMessage: TextSpan( + text: mark.title ?? 'No title', + children: [ + TextSpan(text: '\n'), + TextSpan( + text: mark.description ?? 'descriptionNone'.tr(), + style: TextStyle(fontWeight: FontWeight.normal), + ), + ], + style: TextStyle(fontWeight: FontWeight.bold), + ), + child: icon, + ); } } @@ -384,19 +383,19 @@ class StellarMembershipMark extends StatelessWidget { return hideOverlay ? icon : Tooltip( - richMessage: TextSpan( - text: 'stellarMembership'.tr(), - children: [ - TextSpan(text: '\n'), - TextSpan( - text: 'currentMembershipMember'.tr(args: [tierName]), - style: TextStyle(fontWeight: FontWeight.normal), - ), - ], - style: TextStyle(fontWeight: FontWeight.bold), - ), - child: icon, - ); + richMessage: TextSpan( + text: 'stellarMembership'.tr(), + children: [ + TextSpan(text: '\n'), + TextSpan( + text: 'currentMembershipMember'.tr(args: [tierName]), + style: TextStyle(fontWeight: FontWeight.normal), + ), + ], + style: TextStyle(fontWeight: FontWeight.bold), + ), + child: icon, + ); } } @@ -414,10 +413,9 @@ class VerificationStatusCard extends StatelessWidget { ? kVerificationMarkIcons[mark.type] : Symbols.verified, size: 32, - color: - (kVerificationMarkColors.length > mark.type && mark.type >= 0) - ? kVerificationMarkColors[mark.type] - : Colors.blue, + color: (kVerificationMarkColors.length > mark.type && mark.type >= 0) + ? kVerificationMarkColors[mark.type] + : Colors.blue, fill: 1, ).alignment(Alignment.centerLeft), const Gap(8), diff --git a/lib/widgets/post/post_featured.dart b/lib/widgets/post/post_featured.dart index 6fd576e3..bd2a94ee 100644 --- a/lib/widgets/post/post_featured.dart +++ b/lib/widgets/post/post_featured.dart @@ -21,7 +21,8 @@ Future> featuredPosts(Ref ref) async { } class PostFeaturedList extends HookConsumerWidget { - const PostFeaturedList({super.key}); + final bool collapsable; + const PostFeaturedList({super.key, this.collapsable = true}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -86,6 +87,7 @@ class PostFeaturedList extends HookConsumerWidget { color: Theme.of(context).colorScheme.surfaceContainerHigh, margin: EdgeInsets.zero, child: Column( + mainAxisSize: MainAxisSize.min, children: [ SizedBox( height: 48, @@ -121,36 +123,37 @@ class PostFeaturedList extends HookConsumerWidget { }, icon: const Icon(Symbols.arrow_right), ), - IconButton( - padding: EdgeInsets.zero, - visualDensity: VisualDensity.compact, - constraints: const BoxConstraints(), - onPressed: () { - isCollapsed.value = !isCollapsed.value; - talker.info( - 'Manual toggle. isCollapsed set to ${isCollapsed.value}', - ); - if (isCollapsed.value && - featuredPostsAsync.hasValue && - featuredPostsAsync.value!.isNotEmpty) { - prefs.setString( - kFeaturedPostsCollapsedId, - featuredPostsAsync.value!.first.id, - ); + if (collapsable) + IconButton( + padding: EdgeInsets.zero, + visualDensity: VisualDensity.compact, + constraints: const BoxConstraints(), + onPressed: () { + isCollapsed.value = !isCollapsed.value; talker.info( - 'Stored collapsed ID: ${featuredPostsAsync.value!.first.id}', + 'Manual toggle. isCollapsed set to ${isCollapsed.value}', ); - } else { - prefs.remove(kFeaturedPostsCollapsedId); - talker.info('Removed stored collapsed ID.'); - } - }, - icon: Icon( - isCollapsed.value - ? Symbols.expand_more - : Symbols.expand_less, + if (isCollapsed.value && + featuredPostsAsync.hasValue && + featuredPostsAsync.value!.isNotEmpty) { + prefs.setString( + kFeaturedPostsCollapsedId, + featuredPostsAsync.value!.first.id, + ); + talker.info( + 'Stored collapsed ID: ${featuredPostsAsync.value!.first.id}', + ); + } else { + prefs.remove(kFeaturedPostsCollapsedId); + talker.info('Removed stored collapsed ID.'); + } + }, + icon: Icon( + isCollapsed.value + ? Symbols.expand_more + : Symbols.expand_less, + ), ), - ), ], ).padding(horizontal: 16, vertical: 8), ), @@ -158,14 +161,14 @@ class PostFeaturedList extends HookConsumerWidget { duration: const Duration(milliseconds: 300), curve: Curves.easeInOut, child: Visibility( - visible: !isCollapsed.value, + visible: collapsable ? !isCollapsed.value : true, child: featuredPostsAsync.when( - loading: - () => const Center(child: CircularProgressIndicator()), + loading: () => + const Center(child: CircularProgressIndicator()), error: (error, stack) => Center(child: Text('Error: $error')), data: (posts) { return SizedBox( - height: 320, + height: 344, child: PageView.builder( controller: pageViewController, scrollDirection: Axis.horizontal,