wip pageable mixin
This commit is contained in:
parent
a4b7ee3cd0
commit
7b0297a491
|
@ -11,15 +11,18 @@ class VehicleHistoryScreen extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
||||
with Remotable {
|
||||
with Pageable {
|
||||
final apiCall = PhpGroup.getVehiclesByProperty;
|
||||
int count = 0;
|
||||
final PagingController<int, dynamic> _pagingController =
|
||||
PagingController<int, dynamic>(firstPageKey: 1);
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_pagingController.addPageRequestListener(
|
||||
(dynamic pageKey) => _fetch(
|
||||
hasData: () async {
|
||||
(dynamic pageKey) => fetchPage(
|
||||
dataProvider: () async {
|
||||
final newItems = await apiCall.call(pageKey.toString());
|
||||
if (newItems.jsonBody == null) return (false, null);
|
||||
final List<dynamic> vehicles =
|
||||
|
@ -31,27 +34,19 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
|||
});
|
||||
return (vehicles.isNotEmpty, vehicles);
|
||||
},
|
||||
onNotHas: () {
|
||||
_showNoMoreDataSnackBar(context);
|
||||
setState(() {
|
||||
// _hasData = false;
|
||||
// _loading = false;
|
||||
});
|
||||
onDataUnavailable: () {
|
||||
setState(() {});
|
||||
showNoMoreDataSnackBar(context);
|
||||
},
|
||||
onHas: (vehicles) {
|
||||
setState(() {
|
||||
// _loading = false;
|
||||
});
|
||||
onDataAvailable: (vehicles) {
|
||||
setState(() {});
|
||||
_pagingController.appendLastPage(vehicles);
|
||||
},
|
||||
onError: (e, s) {
|
||||
onFetchError: (e, s) {
|
||||
DialogUtil.errorDefault(context);
|
||||
LogUtil.requestAPIFailed(
|
||||
"proccessRequest.php", "", "Consulta de Veículo", e, s);
|
||||
setState(() {
|
||||
// _hasData = false;
|
||||
// _loading = false;
|
||||
});
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
);
|
||||
|
@ -92,7 +87,7 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
|||
return Column(
|
||||
children: [
|
||||
_buildHeader(context),
|
||||
_buildBody(),
|
||||
_buildBody(context),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -117,36 +112,23 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
|||
);
|
||||
}
|
||||
|
||||
Expanded _buildBody() {
|
||||
Expanded _buildBody(BuildContext context) {
|
||||
final noDataFound = FFLocalizations.of(context).getVariableText(
|
||||
ptText: "Nenhum veículo encontrado!",
|
||||
enText: "No vehicle found",
|
||||
);
|
||||
return Expanded(
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async => _pagingController.refresh(),
|
||||
child: PagedListView<int, dynamic>(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<dynamic>(
|
||||
animateTransitions: true,
|
||||
itemBuilder: (context, item, index) =>
|
||||
_generateItems(context, index, item),
|
||||
// noMoreItemsIndicatorBuilder: ,
|
||||
newPageProgressIndicatorBuilder: (context) =>
|
||||
_buildLoadingIndicator(context),
|
||||
firstPageProgressIndicatorBuilder: (context) =>
|
||||
_buildLoadingIndicator(context),
|
||||
noItemsFoundIndicatorBuilder: (context) =>
|
||||
_buildNoDataFound(context, noDataFound),
|
||||
firstPageErrorIndicatorBuilder: (context) => const Placeholder(),
|
||||
newPageErrorIndicatorBuilder: (context) => const Placeholder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
return buildPaginatedListView<int, dynamic>(
|
||||
noDataFound,
|
||||
_pagingController,
|
||||
_generateItems,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _generateItems(BuildContext context, int index, dynamic item) {
|
||||
Widget _generateItems(
|
||||
BuildContext context,
|
||||
dynamic item,
|
||||
int index,
|
||||
) {
|
||||
log('item: $item');
|
||||
final bool? isOwner = item['isOwnerVehicle'];
|
||||
final IconData iconData =
|
||||
|
@ -249,69 +231,3 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
mixin Remotable on State<VehicleHistoryScreen> {
|
||||
final PagingController<int, dynamic> _pagingController =
|
||||
PagingController<int, dynamic>(firstPageKey: 1);
|
||||
|
||||
double offset = 0.0;
|
||||
// bool _hasData = true;
|
||||
// bool _loading = true;
|
||||
int count = 0;
|
||||
|
||||
Future<void> _fetch({
|
||||
required Future<(bool, dynamic)> Function() hasData,
|
||||
required void Function(dynamic) onHas,
|
||||
required void Function() onNotHas,
|
||||
required void Function(Object, StackTrace) onError,
|
||||
}) async {
|
||||
// if (!_hasData || !_loading) return;
|
||||
try {
|
||||
final (bool, dynamic) data = await hasData();
|
||||
if (data.$1)
|
||||
onHas(data.$2);
|
||||
else
|
||||
onNotHas();
|
||||
} catch (e, s) {
|
||||
onError(e, s);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
final headerFontSize = LimitedFontSizeUtil.getHeaderFontSize(context);
|
||||
// final bodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);
|
||||
return Expanded(
|
||||
child: Center(
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Nunito',
|
||||
fontSize: headerFontSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildLoadingIndicator(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 15),
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
FlutterFlowTheme.of(context).primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'package:hub/features/module/index.dart';
|
|||
import 'package:hub/flutter_flow/index.dart';
|
||||
import 'package:hub/pages/vehicles_on_the_property/vehicle_model.dart';
|
||||
import 'package:hub/shared/extensions/index.dart';
|
||||
import 'package:hub/shared/mixins/pageable_mixin.dart';
|
||||
import 'package:hub/shared/utils/dialog_util.dart';
|
||||
import 'package:hub/shared/utils/license_util.dart';
|
||||
import 'package:hub/shared/utils/limited_text_size.dart';
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
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> {}
|
||||
|
||||
mixin Pageable<T extends StatefulWidget> on State<T> {
|
||||
Expanded buildPaginatedListView<X, Y>(
|
||||
String noDataFound,
|
||||
PagingController<X, Y> pg,
|
||||
Widget Function(BuildContext, Y, int) itemBuilder) {
|
||||
final theme = FlutterFlowTheme.of(context);
|
||||
|
||||
return Expanded(
|
||||
child: RefreshIndicator(
|
||||
backgroundColor: theme.primaryBackground,
|
||||
color: theme.primary,
|
||||
onRefresh: () async => pg.refresh(),
|
||||
child: PagedListView<X, Y>(
|
||||
pagingController: pg,
|
||||
builderDelegate: PagedChildBuilderDelegate<Y>(
|
||||
animateTransitions: true,
|
||||
|
||||
itemBuilder: (context, item, index) =>
|
||||
itemBuilder(context, item, index),
|
||||
// noMoreItemsIndicatorBuilder: ,
|
||||
newPageProgressIndicatorBuilder: (context) =>
|
||||
buildLoadingIndicator(context),
|
||||
firstPageProgressIndicatorBuilder: (context) =>
|
||||
buildLoadingIndicator(context),
|
||||
noItemsFoundIndicatorBuilder: (context) =>
|
||||
buildNoDataFound(context, noDataFound),
|
||||
firstPageErrorIndicatorBuilder: (context) => const Placeholder(),
|
||||
newPageErrorIndicatorBuilder: (context) => const Placeholder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
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(BuildContext context, String title) {
|
||||
final headerFontSize = LimitedFontSizeUtil.getHeaderFontSize(context);
|
||||
// final bodyFontSize = LimitedFontSizeUtil.getBodyFontSize(context);
|
||||
return Expanded(
|
||||
child: Center(
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontFamily: 'Nunito',
|
||||
fontSize: headerFontSize,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildLoadingIndicator(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(vertical: 15),
|
||||
child: Center(
|
||||
child: CircularProgressIndicator(
|
||||
valueColor: AlwaysStoppedAnimation<Color>(
|
||||
FlutterFlowTheme.of(context).primary,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue