flutter-freaccess-hub/lib/shared/mixins/pegeable_mixin.dart

141 lines
4.6 KiB
Dart

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<PageKeyType, ItemType>
on PagedSliverList<PageKeyType, ItemType> {}
typedef PaginatedListViewHeaderBuilder<T> = Widget Function<T>(
Future<List<T?>> Function() gen);
typedef PaginatedListViewBodyBuilder<T> = Widget Function(BuildContext, T, int);
mixin Pageable<T extends StatefulWidget> on State<T> {
Expanded buildPaginatedListView<PageKeyType, BodyType, HeaderType>(
String noDataFound,
PagingController<PageKeyType, BodyType> pg,
Future<List<HeaderType?>> Function() headerItems,
PaginatedListViewHeaderBuilder<BodyType> headerBuilder,
PaginatedListViewBodyBuilder<BodyType> bodyBuilder) {
final theme = FlutterFlowTheme.of(context);
return Expanded(
child: RefreshIndicator(
backgroundColor: theme.primaryBackground,
color: theme.primary,
onRefresh: () async => pg.refresh(),
child: PagedListView<PageKeyType, BodyType>(
pagingController: pg,
builderDelegate: PagedChildBuilderDelegate<BodyType>(
animateTransitions: true,
itemBuilder: (context, item, int index) {
return Column(children: [
if (index == 0) headerBuilder(headerItems),
bodyBuilder(context, item, index),
]);
},
newPageProgressIndicatorBuilder: (context) =>
buildLoadingIndicator(context),
firstPageProgressIndicatorBuilder: (context) =>
buildLoadingIndicator(context),
noItemsFoundIndicatorBuilder: (context) =>
buildNoDataFound<HeaderType>(
context, noDataFound, headerItems, headerBuilder),
firstPageErrorIndicatorBuilder: (context) => const Placeholder(),
newPageErrorIndicatorBuilder: (context) => const Placeholder(),
),
),
),
);
}
Future<void> 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<void> 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<T>(
BuildContext context,
String title,
Future<List<T?>> Function() items,
Widget Function<T>(Future<List<T?>> Function() items) headerBuilder,
) {
final headerFontSize = LimitedFontSizeUtil.getHeaderFontSize(context);
// final bodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);
return Column(
children: [
headerBuilder(items),
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<Color>(
FlutterFlowTheme.of(context).primary,
),
),
),
);
}
}