From f3208553488b93392342df24304f1cd0a18a3bcd Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Thu, 31 Jul 2025 01:17:20 +0800 Subject: [PATCH] :lipstick: Optimize explore page styles --- assets/i18n/en-US.json | 4 +- lib/screens/explore.dart | 107 +++++++++++++------------ lib/screens/posts/post_detail.dart | 25 +++--- lib/screens/posts/post_search.dart | 13 ++- lib/screens/posts/pub_profile.dart | 48 ++++++----- lib/widgets/account/account_name.dart | 47 +++++------ lib/widgets/account/fortune_graph.dart | 5 +- lib/widgets/check_in.dart | 6 +- lib/widgets/post/post_list.dart | 9 ++- lib/widgets/post/post_replies.dart | 18 ++--- 10 files changed, 145 insertions(+), 137 deletions(-) diff --git a/assets/i18n/en-US.json b/assets/i18n/en-US.json index 6db88ba..1eb2011 100644 --- a/assets/i18n/en-US.json +++ b/assets/i18n/en-US.json @@ -626,8 +626,8 @@ "chatJoin": "Join the Chat", "realmJoin": "Join the Realm", "realmJoinSuccess": "Successfully joined the realm.", - "discoverRealms": "Discover Realms", - "discoverPublishers": "Discover Publishers", + "discoverRealms": "Discover realms", + "discoverPublishers": "Discover publishers", "search": "Search", "publisherMembers": "Collaborators", "developerHub": "Developer Hub", diff --git a/lib/screens/explore.dart b/lib/screens/explore.dart index 47e71f9..f515114 100644 --- a/lib/screens/explore.dart +++ b/lib/screens/explore.dart @@ -198,21 +198,23 @@ class ExploreScreen extends HookConsumerWidget { if (isWider) { return Row( children: [ - Flexible(flex: 3, child: bodyView), - const VerticalDivider(width: 1), + Flexible(flex: 3, child: bodyView.padding(left: 8)), if (user.value != null) Flexible( flex: 2, child: SingleChildScrollView( child: Column( children: [ - CheckInWidget(), - Card( + CheckInWidget( margin: EdgeInsets.only( - left: 16, + left: 8, right: 16, - top: 8, + top: 16, + bottom: 8, ), + ), + Card( + margin: EdgeInsets.only(left: 8, right: 16, top: 8), child: Column( children: [ // Use the reusable EventCalendarWidget @@ -227,6 +229,11 @@ class ExploreScreen extends HookConsumerWidget { ), ), FortuneGraphWidget( + margin: EdgeInsets.only( + left: 8, + right: 16, + top: 16, + ), events: events, constrainWidth: true, onPointSelected: onDaySelected, @@ -306,56 +313,55 @@ class _DiscoveryActivityItem extends StatelessWidget { final items = data['items'] as List; final type = items.firstOrNull?['type'] ?? 'unknown'; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - const Icon(Symbols.explore, size: 19), - const Gap(8), - Text( - (switch (type) { - 'realm' => 'discoverRealms', - 'publisher' => 'discoverPublishers', - 'article' => 'discoverWebArticles', - _ => 'unknown', - }).tr(), - style: Theme.of(context).textTheme.titleMedium, - ).padding(top: 1), - ], - ).padding(horizontal: 20, top: 8, bottom: 4), - SizedBox( - height: 180, - child: ListView.builder( - scrollDirection: Axis.horizontal, - itemCount: items.length, - padding: const EdgeInsets.symmetric(horizontal: 8), - itemBuilder: (context, index) { - final item = items[index]; - switch (type) { - case 'realm': - return RealmCard( + return Card( + margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + const Icon(Symbols.explore, size: 19), + const Gap(8), + Text( + (switch (type) { + 'realm' => 'discoverRealms', + 'publisher' => 'discoverPublishers', + 'article' => 'discoverWebArticles', + _ => 'unknown', + }).tr(), + style: Theme.of(context).textTheme.titleMedium, + ).padding(top: 1), + ], + ).padding(horizontal: 20, top: 8, bottom: 4), + SizedBox( + height: 180, + child: ListView.builder( + scrollDirection: Axis.horizontal, + itemCount: items.length, + padding: const EdgeInsets.symmetric(horizontal: 8), + itemBuilder: (context, index) { + final item = items[index]; + return switch (type) { + 'realm' => RealmCard( realm: SnRealm.fromJson(item['data']), maxWidth: 280, - ); - case 'publisher': - return PublisherCard( + ), + 'publisher' => PublisherCard( publisher: SnPublisher.fromJson(item['data']), maxWidth: 280, - ); - case 'article': - return WebArticleCard( + ), + 'article' => WebArticleCard( article: SnWebArticle.fromJson(item['data']), maxWidth: 280, - ); - default: - return Placeholder(); - } - }, - ), - ).padding(bottom: 4), - ], + ), + _ => Placeholder(), + }; + }, + ), + ).padding(bottom: 8), + ], + ), ); } } @@ -381,6 +387,7 @@ class _ActivityListView extends HookConsumerWidget { return CustomScrollView( slivers: [ + SliverGap(12), if (user.value != null && !contentOnly) SliverToBoxAdapter(child: CheckInWidget()), SliverList.builder( diff --git a/lib/screens/posts/post_detail.dart b/lib/screens/posts/post_detail.dart index da9dd50..1f14583 100644 --- a/lib/screens/posts/post_detail.dart +++ b/lib/screens/posts/post_detail.dart @@ -67,21 +67,16 @@ class PostDetailScreen extends HookConsumerWidget { CustomScrollView( slivers: [ SliverToBoxAdapter( - child: Column( - children: [ - PostItem( - item: post!, - isFullPost: true, - backgroundColor: isWide ? Colors.transparent : null, - onUpdate: (newItem) { - // Update the local state with the new post data - ref - .read(postStateProvider(id).notifier) - .updatePost(newItem); - }, - ), - const Divider(height: 1), - ], + child: PostItem( + item: post!, + isFullPost: true, + backgroundColor: isWide ? Colors.transparent : null, + onUpdate: (newItem) { + // Update the local state with the new post data + ref + .read(postStateProvider(id).notifier) + .updatePost(newItem); + }, ), ), PostRepliesList(postId: id), diff --git a/lib/screens/posts/post_search.dart b/lib/screens/posts/post_search.dart index d443026..b414749 100644 --- a/lib/screens/posts/post_search.dart +++ b/lib/screens/posts/post_search.dart @@ -5,6 +5,7 @@ import 'package:island/models/post.dart'; import 'package:island/pods/network.dart'; import 'package:island/widgets/app_scaffold.dart'; import 'package:island/widgets/post/post_item.dart'; +import 'package:island/widgets/response.dart'; import 'package:riverpod_paging_utils/riverpod_paging_utils.dart'; final postSearchNotifierProvider = StateNotifierProvider.autoDispose< @@ -141,6 +142,7 @@ class _PostSearchScreenState extends ConsumerState { } return ListView.builder( + padding: EdgeInsets.zero, itemCount: data.items.length + (data.hasMore ? 1 : 0), itemBuilder: (context, index) { if (index >= data.items.length) { @@ -151,14 +153,19 @@ class _PostSearchScreenState extends ConsumerState { } final post = data.items[index]; - return Column( - children: [PostItem(item: post), const Divider(height: 1)], + return Card( + margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: PostActionableItem(item: post, borderRadius: 8), ); }, ); }, loading: () => const Center(child: CircularProgressIndicator()), - error: (error, stack) => Center(child: Text('Error: $error')), + error: + (error, stack) => ResponseErrorWidget( + error: error, + onRetry: () => ref.invalidate(postSearchNotifierProvider), + ), ); }, ), diff --git a/lib/screens/posts/pub_profile.dart b/lib/screens/posts/pub_profile.dart index e8d77ff..970a1dd 100644 --- a/lib/screens/posts/pub_profile.dart +++ b/lib/screens/posts/pub_profile.dart @@ -285,33 +285,31 @@ class PublisherProfileScreen extends HookConsumerWidget { ).padding(horizontal: 24, top: 24), ), SliverToBoxAdapter( - child: Column( - children: [ - if (badges.value?.isNotEmpty ?? false) - BadgeList(badges: badges.value!).padding(top: 16), - if (data.verification != null) - VerificationStatusCard( - mark: data.verification!, - ).padding(top: 16), - ], - ).padding(horizontal: 24), + child: Card( + margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: Column( + children: [ + if (badges.value?.isNotEmpty ?? false) + BadgeList(badges: badges.value!).padding(top: 16), + if (data.verification != null) + VerificationStatusCard(mark: data.verification!), + ], + ), + ).padding(top: 16), ), SliverToBoxAdapter( - child: const Divider(height: 1).padding(vertical: 24), - ), - SliverToBoxAdapter( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Text('bio').tr().bold(), - Text( - data.bio.isEmpty ? 'descriptionNone'.tr() : data.bio, - ), - ], - ).padding(horizontal: 24), - ), - SliverToBoxAdapter( - child: const Divider(height: 1).padding(top: 24), + child: Card( + margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text('bio').tr().bold().padding(bottom: 2), + Text( + data.bio.isEmpty ? 'descriptionNone'.tr() : data.bio, + ), + ], + ).padding(horizontal: 20, vertical: 16), + ), ), SliverPostList(pubName: name), SliverGap(MediaQuery.of(context).padding.bottom + 16), diff --git a/lib/widgets/account/account_name.dart b/lib/widgets/account/account_name.dart index b31f0af..4d84de4 100644 --- a/lib/widgets/account/account_name.dart +++ b/lib/widgets/account/account_name.dart @@ -140,30 +140,27 @@ class VerificationStatusCard extends StatelessWidget { @override Widget build(BuildContext context) { - return Card( - margin: EdgeInsets.zero, - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Icon( - mark.type == 4 - ? Symbols.play_circle - : mark.type == 0 - ? Symbols.build_circle - : Symbols.verified, - size: 32, - color: kVerificationMarkColors[mark.type], - fill: 1, - ), - const Gap(8), - Text(mark.title ?? 'No title').bold(), - Text(mark.description ?? 'descriptionNone'.tr()), - const Gap(6), - Text( - 'Verified by\n${mark.verifiedBy ?? 'No one verified it'}', - ).fontSize(11).opacity(0.8), - ], - ).padding(horizontal: 24, vertical: 16), - ); + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon( + mark.type == 4 + ? Symbols.play_circle + : mark.type == 0 + ? Symbols.build_circle + : Symbols.verified, + size: 32, + color: kVerificationMarkColors[mark.type], + fill: 1, + ), + const Gap(8), + Text(mark.title ?? 'No title').bold(), + Text(mark.description ?? 'descriptionNone'.tr()), + const Gap(6), + Text( + 'Verified by\n${mark.verifiedBy ?? 'No one verified it'}', + ).fontSize(11).opacity(0.8), + ], + ).padding(horizontal: 24, vertical: 16); } } diff --git a/lib/widgets/account/fortune_graph.dart b/lib/widgets/account/fortune_graph.dart index 1e51e90..b967566 100644 --- a/lib/widgets/account/fortune_graph.dart +++ b/lib/widgets/account/fortune_graph.dart @@ -26,6 +26,8 @@ class FortuneGraphWidget extends HookConsumerWidget { final String? eventCalanderUser; + final EdgeInsets? margin; + const FortuneGraphWidget({ super.key, required this.events, @@ -34,6 +36,7 @@ class FortuneGraphWidget extends HookConsumerWidget { this.height = 180, this.onPointSelected, this.eventCalanderUser, + this.margin, }); @override @@ -249,7 +252,7 @@ class FortuneGraphWidget extends HookConsumerWidget { if (constrainWidth) { return ConstrainedBox( constraints: BoxConstraints(maxWidth: maxWidth), - child: Card(margin: EdgeInsets.all(16), child: content), + child: Card(margin: margin ?? EdgeInsets.all(16), child: content), ).center(); } diff --git a/lib/widgets/check_in.dart b/lib/widgets/check_in.dart index 4dd7446..a8f4f9f 100644 --- a/lib/widgets/check_in.dart +++ b/lib/widgets/check_in.dart @@ -35,7 +35,8 @@ Future checkInResultToday(Ref ref) async { } class CheckInWidget extends HookConsumerWidget { - const CheckInWidget({super.key}); + final EdgeInsets? margin; + const CheckInWidget({super.key, this.margin}); @override Widget build(BuildContext context, WidgetRef ref) { @@ -66,7 +67,8 @@ class CheckInWidget extends HookConsumerWidget { } return Card( - margin: EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8), + margin: + margin ?? EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8), child: Row( crossAxisAlignment: CrossAxisAlignment.center, spacing: 16, diff --git a/lib/widgets/post/post_list.dart b/lib/widgets/post/post_list.dart index 533bf0e..80e90d4 100644 --- a/lib/widgets/post/post_list.dart +++ b/lib/widgets/post/post_list.dart @@ -94,9 +94,7 @@ class SliverPostList extends HookConsumerWidget { final post = data.items[index]; - return Column( - children: [_buildPostItem(post), const Divider(height: 1)], - ); + return _buildPostItem(post); }, ), ); @@ -114,7 +112,10 @@ class SliverPostList extends HookConsumerWidget { onUpdate: onUpdate, ); case PostItemType.regular: - return PostItem(item: post); + return Card( + margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: PostActionableItem(item: post, borderRadius: 8), + ); } } } diff --git a/lib/widgets/post/post_replies.dart b/lib/widgets/post/post_replies.dart index 4b83972..ce490e9 100644 --- a/lib/widgets/post/post_replies.dart +++ b/lib/widgets/post/post_replies.dart @@ -93,16 +93,14 @@ class PostRepliesList extends HookConsumerWidget { return endItemView; } - return Column( - children: [ - PostItem( - item: data.items[index], - backgroundColor: - backgroundColor ?? (isWide ? Colors.transparent : null), - isShowReference: false, - ), - const Divider(height: 1), - ], + return Card( + margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: PostActionableItem( + item: data.items[index], + backgroundColor: + backgroundColor ?? (isWide ? Colors.transparent : null), + isShowReference: false, + ), ); }, );