import 'package:flutter/material.dart'; import 'package:hub/flutter_flow/index.dart'; import 'package:hub/shared/utils/limited_text_size.dart'; import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; extension PagedListViewExtension on PagedSliverList {} mixin Pageable on State { Expanded buildPaginatedListView( String noDataFound, PagingController pg, Widget Function(BuildContext) headerBuilder, Widget Function(BuildContext, ItemType, int) bodyBuilder) { final theme = FlutterFlowTheme.of(context); return Expanded( child: RefreshIndicator( backgroundColor: theme.primaryBackground, color: theme.primary, onRefresh: () async => pg.refresh(), child: PagedListView( pagingController: pg, builderDelegate: PagedChildBuilderDelegate( animateTransitions: true, itemBuilder: (context, item, int index) { return Column(children: [ if (index == 0) headerBuilder(context), bodyBuilder(context, item, index), ]); }, newPageProgressIndicatorBuilder: (context) => buildLoadingIndicator(context), firstPageProgressIndicatorBuilder: (context) => buildLoadingIndicator(context), noItemsFoundIndicatorBuilder: (context) => buildNoDataFound(context, noDataFound, headerBuilder), firstPageErrorIndicatorBuilder: (context) => const Placeholder(), newPageErrorIndicatorBuilder: (context) => const Placeholder(), ), ), ), ); } Future showError(PagingStatus status, PagingController pg) async { if (status == PagingStatus.subsequentPageError) { final message = FFLocalizations.of(context).getVariableText( enText: 'Something went wrong while fetching a new page.', ptText: 'Algo deu errado ao buscar uma nova página.', ); final retry = FFLocalizations.of(context).getVariableText( enText: 'Retry', ptText: 'Recarregar', ); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(message), action: SnackBarAction( label: retry, onPressed: () => pg.retryLastFailedRequest(), ), ), ); } } Future fetchPage({ required Future<(bool, dynamic)> Function() dataProvider, required void Function(dynamic data) onDataAvailable, required void Function() onDataUnavailable, required void Function(Object error, StackTrace stackTrace) onFetchError, }) async { try { final (bool isDataAvailable, dynamic data) = await dataProvider(); if (isDataAvailable) { onDataAvailable(data); } else { onDataUnavailable(); } } catch (error, stackTrace) { onFetchError(error, stackTrace); } } void showNoMoreDataSnackBar(BuildContext context) { final message = FFLocalizations.of(context).getVariableText( ptText: "Não há mais dados.", enText: "No more data.", ); showSnackbar(context, message, true); } Widget buildNoDataFound( BuildContext context, String title, Widget Function(BuildContext) headerBuilder, ) { final headerFontSize = LimitedFontSizeUtil.getHeaderFontSize(context); // final bodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context); return Column( children: [ headerBuilder(context), Expanded( child: Center( child: Text( title, style: TextStyle( fontFamily: 'Nunito', fontSize: headerFontSize, ), ), ), ), ], ); } Widget buildLoadingIndicator(BuildContext context) { print('Loading'); return Container( padding: const EdgeInsets.symmetric(vertical: 15), child: Center( child: CircularProgressIndicator( valueColor: AlwaysStoppedAnimation( FlutterFlowTheme.of(context).primary, ), ), ), ); } }