import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:veloe_kemono_party_flutter/main.dart'; import 'package:veloe_kemono_party_flutter/pages/widgets/post_container.dart'; class PostsScreen extends ConsumerStatefulWidget { final String creatorId; final String service; const PostsScreen({ super.key, required this.creatorId, required this.service, }); @override ConsumerState createState() => _PostsScreenState(); } class _PostsScreenState extends ConsumerState with PaginationMixin { @override void initState() { super.initState(); Future.microtask(() => ref.read(postsProvider(( widget.creatorId, // Direct access now valid widget.service )).notifier).loadInitial()); } @override Widget build(BuildContext context) { final postsAsync = ref.watch(postsProvider((widget.creatorId, widget.service))); return Scaffold( appBar: AppBar( title: const Text('Posts'), leading: IconButton( icon: const Icon(Icons.arrow_back), onPressed: () => Navigator.pop(context), ), ), body: postsAsync.when( loading: () => const Center(child: CircularProgressIndicator()), error: (error, _) => Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text('Error: ${error.toString()}'), ElevatedButton( onPressed: () => ref.invalidate(postsProvider((widget.creatorId, widget.service))), child: const Text('Retry'), ) ], ), ), data: (allPosts) => NotificationListener( onNotification: (notification) { if (notification is ScrollUpdateNotification) { _scrollListener(); } return false; }, child: CustomScrollView( controller: _scrollController, slivers: [ SliverList( delegate: SliverChildBuilderDelegate( (context, index) => PostContainer( key: ValueKey(allPosts[index].id), post: allPosts[index], ), childCount: allPosts.length, ), ), SliverToBoxAdapter( child: _buildLoadMoreIndicator(), ), ], ), ), ), ); } Widget _buildLoadMoreIndicator() { return ref.watch(postsProvider((widget.creatorId, widget.service))).maybeWhen( loading: () => const Padding( padding: EdgeInsets.all(16), child: Center(child: CircularProgressIndicator()), ), error: (error, _) => Column( children: [ Text('Load more failed: ${error.toString()}'), ElevatedButton( onPressed: () => ref.read(postsProvider((widget.creatorId, widget.service)).notifier).loadNext(), child: const Text('Retry'), ) ], ), orElse: () => const SizedBox.shrink(), ); } } mixin PaginationMixin on ConsumerState { final ScrollController _scrollController = ScrollController(); bool _isLoading = false; @override void initState() { super.initState(); _scrollController.addListener(_scrollListener); } void _scrollListener() { if (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent * 0.8) { _loadNextPage(); } } PostsScreen get postsWidget => widget as PostsScreen; Future _loadNextPage() async { if (_isLoading) return; _isLoading = true; final notifier = ref.read(postsProvider(( postsWidget.creatorId, // Use converted widget reference postsWidget.service )).notifier); await notifier.loadNext(); _isLoading = false; } @override void dispose() { _scrollController.dispose(); super.dispose(); } }