import 'package:flutter/material.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:island/pods/paging.dart'; import 'package:island/widgets/extended_refresh_indicator.dart'; import 'package:island/widgets/response.dart'; import 'package:super_sliver_list/super_sliver_list.dart'; class PaginationList extends HookConsumerWidget { final ProviderListenable>> provider; final Refreshable> notifier; final Widget? Function(BuildContext, int, T) itemBuilder; final bool isRefreshable; const PaginationList({ super.key, required this.provider, required this.notifier, required this.itemBuilder, this.isRefreshable = true, }); @override Widget build(BuildContext context, WidgetRef ref) { final data = ref.watch(provider); final noti = ref.watch(notifier); final listView = SuperListView.builder( itemBuilder: (context, idx) { final entry = data.valueOrNull?[idx]; if (entry != null) return itemBuilder(context, idx, entry); return null; }, ); final child = NotificationListener( onNotification: (ScrollNotification scrollInfo) { if (scrollInfo is ScrollEndNotification && scrollInfo.metrics.axisDirection == AxisDirection.down && scrollInfo.metrics.pixels >= scrollInfo.metrics.maxScrollExtent) { if (!noti.fetchedAll && !data.isLoading && !data.hasError) { noti.fetchFurther(); } } return true; }, child: listView, ); return isRefreshable ? ExtendedRefreshIndicator(onRefresh: noti.refresh, child: child) : child; } } class PaginationWidget extends HookConsumerWidget { final ProviderListenable>> provider; final Refreshable> notifier; final Widget Function(List) contentBuilder; final bool isRefreshable; final bool isSliver; final bool showDefaultWidgets; const PaginationWidget({ super.key, required this.provider, required this.notifier, required this.contentBuilder, this.isRefreshable = true, this.isSliver = false, this.showDefaultWidgets = true, }); @override Widget build(BuildContext context, WidgetRef ref) { final data = ref.watch(provider); final noti = ref.watch(notifier); if (data.isLoading) { final content = ResponseLoadingWidget(); return isSliver ? SliverFillRemaining(child: content) : content; } if (data.hasError) { final content = ResponseErrorWidget( error: data.error, onRetry: noti.refresh, ); return isSliver ? SliverFillRemaining(child: content) : content; } final content = NotificationListener( onNotification: (ScrollNotification scrollInfo) { if (scrollInfo is ScrollEndNotification && scrollInfo.metrics.axisDirection == AxisDirection.down && scrollInfo.metrics.pixels >= scrollInfo.metrics.maxScrollExtent) { if (!noti.fetchedAll && !data.isLoading && !data.hasError) { noti.fetchFurther(); } } return true; }, child: contentBuilder(data.valueOrNull ?? []), ); return isRefreshable ? ExtendedRefreshIndicator(onRefresh: noti.refresh, child: content) : content; } }