123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- 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<PostsScreen> createState() => _PostsScreenState();
- }
- class _PostsScreenState extends ConsumerState<PostsScreen> 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<ScrollNotification>(
- 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<T extends ConsumerStatefulWidget> on ConsumerState<T> {
- 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<void> _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();
- }
- }
|