From 38fc4e969f1dfb55f035029968bed06b7ef1c930 Mon Sep 17 00:00:00 2001 From: LittleSheep Date: Wed, 7 Jan 2026 22:52:46 +0800 Subject: [PATCH] :lipstick: Improved pinned post --- lib/screens/posts/publisher_profile.dart | 3 + lib/screens/realm/realm_detail.dart | 116 ++++++++++++++++++++++- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/lib/screens/posts/publisher_profile.dart b/lib/screens/posts/publisher_profile.dart index 487d96f8..7d06ec67 100644 --- a/lib/screens/posts/publisher_profile.dart +++ b/lib/screens/posts/publisher_profile.dart @@ -76,6 +76,9 @@ class _PinnedPostsPageView extends HookConsumerWidget { shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(8)), ), + collapsedShape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(8)), + ), children: [ SizedBox( height: 400, diff --git a/lib/screens/realm/realm_detail.dart b/lib/screens/realm/realm_detail.dart index 0f59da7b..5367c33a 100644 --- a/lib/screens/realm/realm_detail.dart +++ b/lib/screens/realm/realm_detail.dart @@ -9,6 +9,7 @@ import 'package:island/services/responsive.dart'; import 'package:island/widgets/account/account_pfc.dart'; import 'package:island/widgets/account/status.dart'; import 'package:island/widgets/post/post_list.dart'; +import 'package:island/widgets/post/post_item.dart'; import 'package:island/services/color_extraction.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:gap/gap.dart'; @@ -27,6 +28,113 @@ import 'package:island/pods/paging.dart'; import 'package:island/widgets/paging/pagination_list.dart'; import 'package:styled_widget/styled_widget.dart'; +class _RealmPinnedPostsPageView extends HookConsumerWidget { + final String realmSlug; + + const _RealmPinnedPostsPageView({required this.realmSlug}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final provider = postListProvider( + PostListQueryConfig( + id: 'realm-$realmSlug-pinned', + initialFilter: PostListQuery(realm: realmSlug, pinned: true), + ), + ); + final pinnedPosts = ref.watch(provider); + final pageController = usePageController(); + final currentPage = useState(0); + + useEffect(() { + void listener() { + currentPage.value = pageController.page?.round() ?? 0; + } + + pageController.addListener(listener); + return () => pageController.removeListener(listener); + }, [pageController]); + + return pinnedPosts.when( + data: (data) { + if (data.items.isEmpty) { + return const SizedBox.shrink(); + } + + return Card( + margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4), + child: Theme( + data: Theme.of(context).copyWith(dividerColor: Colors.transparent), + child: ExpansionTile( + initiallyExpanded: true, + leading: const Icon(Symbols.push_pin), + title: Text('pinnedPosts'.tr()), + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + collapsedShape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(8)), + ), + children: [ + SizedBox( + height: 400, + child: Stack( + children: [ + PageView.builder( + controller: pageController, + itemCount: data.items.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.all(8), + child: SingleChildScrollView( + child: Card( + child: PostActionableItem( + item: data.items[index], + borderRadius: 8, + ), + ), + ), + ); + }, + ), + Positioned( + bottom: 16, + left: 0, + right: 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: List.generate( + data.items.length, + (index) => AnimatedContainer( + duration: const Duration(milliseconds: 200), + margin: EdgeInsets.symmetric(horizontal: 4), + width: 8, + height: 8, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: index == currentPage.value + ? Theme.of(context).colorScheme.primary + : Theme.of( + context, + ).colorScheme.primary.withOpacity(0.5), + ), + ), + ), + ), + ), + ], + ), + ), + ], + ), + ), + ); + }, + loading: () => const SizedBox.shrink(), + error: (_, _) => const SizedBox.shrink(), + ); + } +} + final realmAppbarForegroundColorProvider = FutureProvider.autoDispose .family((ref, realmSlug) async { final realm = await ref.watch(realmProvider(realmSlug).future); @@ -235,8 +343,8 @@ class RealmDetailScreen extends HookConsumerWidget { flex: 3, child: CustomScrollView( slivers: [ - SliverPostList( - query: PostListQuery(realm: slug, pinned: true), + SliverToBoxAdapter( + child: _RealmPinnedPostsPageView(realmSlug: slug), ), SliverPostList( query: PostListQuery(realm: slug, pinned: false), @@ -338,8 +446,8 @@ class RealmDetailScreen extends HookConsumerWidget { ), ), SliverToBoxAdapter(child: realmChatRoomListWidget(realm)), - SliverPostList( - query: PostListQuery(realm: slug, pinned: true), + SliverToBoxAdapter( + child: _RealmPinnedPostsPageView(realmSlug: slug), ), SliverPostList( query: PostListQuery(realm: slug, pinned: false),