paginetedListView
This commit is contained in:
parent
f193baebe7
commit
05b3a612ba
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
class DeadCode {
|
|
||||||
final String? desc;
|
|
||||||
|
|
||||||
const DeadCode([this.desc = '']);
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
export 'anotations.dart';
|
|
|
@ -785,3 +785,5 @@ double computeGradientAlignmentY(double evaluatedAngle) {
|
||||||
}
|
}
|
||||||
return double.parse(roundTo(y, 2));
|
return double.parse(roundTo(y, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,8 @@ Future<void> _initializeSystemSettings() async {
|
||||||
if (kDebugMode) {
|
if (kDebugMode) {
|
||||||
//kDebugMode
|
//kDebugMode
|
||||||
print('Debug mode');
|
print('Debug mode');
|
||||||
|
} else {
|
||||||
|
print('Release mode');
|
||||||
bool unsentReports =
|
bool unsentReports =
|
||||||
await FirebaseCrashlytics.instance.checkForUnsentReports();
|
await FirebaseCrashlytics.instance.checkForUnsentReports();
|
||||||
if (unsentReports) {
|
if (unsentReports) {
|
||||||
|
@ -66,9 +68,6 @@ Future<void> _initializeSystemSettings() async {
|
||||||
// Não existem relatórios não enviados
|
// Não existem relatórios não enviados
|
||||||
print('Todos os relatórios de falhas foram enviados.');
|
print('Todos os relatórios de falhas foram enviados.');
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
print('Release mode');
|
|
||||||
|
|
||||||
await crashlyticsInstance.setCrashlyticsCollectionEnabled(true);
|
await crashlyticsInstance.setCrashlyticsCollectionEnabled(true);
|
||||||
// if (crashlyticsInstance.isCrashlyticsCollectionEnabled) {
|
// if (crashlyticsInstance.isCrashlyticsCollectionEnabled) {
|
||||||
FlutterError.onError = await crashlyticsInstance.recordFlutterError;
|
FlutterError.onError = await crashlyticsInstance.recordFlutterError;
|
||||||
|
|
|
@ -4,7 +4,6 @@ part of 'vehicles_on_the_property.dart';
|
||||||
|
|
||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class VehicleHistoryScreen extends StatefulWidget {
|
class VehicleHistoryScreen extends StatefulWidget {
|
||||||
|
|
||||||
VehicleHistoryScreen(this.model, {super.key});
|
VehicleHistoryScreen(this.model, {super.key});
|
||||||
late VehicleModel model;
|
late VehicleModel model;
|
||||||
final scaffoldKey = GlobalKey<ScaffoldState>();
|
final scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
@ -12,23 +11,21 @@ class VehicleHistoryScreen extends StatefulWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<VehicleHistoryScreen> createState() => _VehicleHistoryScreenState();
|
State<VehicleHistoryScreen> createState() => _VehicleHistoryScreenState();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
||||||
with Remotable {
|
with Remotable {
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
_scrollController.dispose();
|
_pagingController.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_initializeScrollController();
|
_initializeScrollController();
|
||||||
|
_pagingController.addPageRequestListener(_fetch);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -38,22 +35,19 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
||||||
late final double limitedBodyTextSize =
|
late final double limitedBodyTextSize =
|
||||||
LimitedFontSizeUtil.getBodyFontSize(context);
|
LimitedFontSizeUtil.getBodyFontSize(context);
|
||||||
|
|
||||||
return Scaffold(
|
return Column(
|
||||||
key: widget.scaffoldKey,
|
mainAxisSize: MainAxisSize.max,
|
||||||
body: Column(
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
mainAxisSize: MainAxisSize.max,
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
// if (_hasData == false &&
|
||||||
children: [
|
// _pageNumber <= 1 &&
|
||||||
if (_hasData == false &&
|
// _loading == false)
|
||||||
_pageNumber <= 1 &&
|
// _buildNoDataFound(context, limitedHeaderTextSize)
|
||||||
_loading == false)
|
// else if (_hasData == true || _pageNumber >= 1)
|
||||||
_buildNoDataFound(context, limitedHeaderTextSize)
|
_buildHistoryList(context, limitedBodyTextSize),
|
||||||
else if (_hasData == true || _pageNumber >= 1)
|
// if (_hasData == true && _loading == true)
|
||||||
_buildHistoryList(context, limitedBodyTextSize),
|
// _buildLoadingIndicator(context),
|
||||||
if (_hasData == true && _loading == true)
|
].addToStart(const SizedBox(height: 0)),
|
||||||
_buildLoadingIndicator(context),
|
|
||||||
].addToStart(const SizedBox(height: 0)),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,30 +76,34 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
||||||
|
|
||||||
Widget _buildHistoryList(BuildContext context, double limitedBodyTextSize) {
|
Widget _buildHistoryList(BuildContext context, double limitedBodyTextSize) {
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: FutureBuilder<void>(
|
child: RefreshIndicator(
|
||||||
future: _fetch(),
|
onRefresh: () async => _pagingController.refresh(),
|
||||||
builder: (context, snapshot) {
|
child: PagedListView<int, dynamic>(
|
||||||
if (snapshot.connectionState == ConnectionState.waiting) {
|
// separatorBuilder: (context, index) => const Divider(),
|
||||||
return Center(child: CircularProgressIndicator());
|
pagingController: _pagingController,
|
||||||
} else if (snapshot.hasError) {
|
builderDelegate: PagedChildBuilderDelegate(
|
||||||
return Center(child: Text('Error: ${snapshot.error}'));
|
animateTransitions: true,
|
||||||
} else {
|
itemBuilder: (context, item, index) =>
|
||||||
return ListView.builder(
|
_generateItems(context, index, item),
|
||||||
shrinkWrap: true,
|
firstPageErrorIndicatorBuilder: (context) => Placeholder(),
|
||||||
addAutomaticKeepAlives: true,
|
newPageErrorIndicatorBuilder: (context) => Placeholder(),
|
||||||
restorationId: '',
|
),
|
||||||
physics: const BouncingScrollPhysics(),
|
),
|
||||||
controller: _scrollController,
|
|
||||||
itemCount: _wrap.length,
|
|
||||||
itemBuilder: (context, index) => _generateItems(context, _wrap[index], index),
|
|
||||||
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ListView.builder(
|
||||||
|
// shrinkWrap: true,
|
||||||
|
// addAutomaticKeepAlives: true,
|
||||||
|
// restorationId: '',
|
||||||
|
// physics: const BouncingScrollPhysics(),
|
||||||
|
// controller: _scrollController,
|
||||||
|
// itemCount: _wrap.length,
|
||||||
|
// itemBuilder: (context, index) => _generateItems(context, _wrap[index], index),
|
||||||
|
|
||||||
|
// ),
|
||||||
|
|
||||||
Widget _buildLoadingIndicator(BuildContext context) {
|
Widget _buildLoadingIndicator(BuildContext context) {
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.only(top: 15, bottom: 15),
|
padding: const EdgeInsets.only(top: 15, bottom: 15),
|
||||||
|
@ -118,15 +116,13 @@ class _VehicleHistoryScreenState extends State<VehicleHistoryScreen>
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
mixin Remotable on State<VehicleHistoryScreen> {
|
mixin Remotable on State<VehicleHistoryScreen> {
|
||||||
|
final PagingController<int, dynamic> _pagingController =
|
||||||
|
PagingController<int, dynamic>(firstPageKey: 1);
|
||||||
|
|
||||||
late ScrollController _scrollController;
|
// late ScrollController _scrollController;
|
||||||
double offset = 0.0;
|
double offset = 0.0;
|
||||||
List<dynamic> _wrap = [];
|
List<dynamic> _wrap = [];
|
||||||
int _pageNumber = 1;
|
int _pageNumber = 1;
|
||||||
|
@ -134,37 +130,46 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
Future<void> _fetch() async {
|
Future<void> _fetch(dynamic pageKey) async {
|
||||||
if (!_hasData || !_loading) return;
|
if (!_hasData || !_loading) return;
|
||||||
print('hasHasData');
|
print('hasHasData');
|
||||||
setState(() => _loading = true);
|
// setState(() => _loading = true);
|
||||||
try {
|
try {
|
||||||
|
var newItems =
|
||||||
|
await PhpGroup.getVehiclesByProperty.call(pageKey.toString());
|
||||||
|
final bool isLastPage = newItems.jsonBody == null ||
|
||||||
|
newItems.jsonBody == [] ||
|
||||||
|
newItems.jsonBody == '';
|
||||||
|
|
||||||
var response = await PhpGroup.getVehiclesByProperty.call(_pageNumber.toString());
|
if (newItems.jsonBody == null) {
|
||||||
final List<dynamic> vehicles = response.jsonBody['vehicles'] as List<dynamic>? ?? [];
|
} else {
|
||||||
safeSetState(() => count = response.jsonBody['total_rows'] ?? 0);
|
final List<dynamic> vehicles =
|
||||||
if (vehicles.isNotEmpty) {
|
newItems.jsonBody['vehicles'] as List<dynamic>? ?? [];
|
||||||
|
_pagingController.nextPageKey = pageKey + 1;
|
||||||
|
|
||||||
|
safeSetState(() => count = newItems.jsonBody['total_rows'] ?? 0);
|
||||||
|
if (vehicles.isNotEmpty) {
|
||||||
|
// setState(() {
|
||||||
|
// _hasData = true;
|
||||||
|
// _loading = false;
|
||||||
|
// _wrap.addAll(vehicles);
|
||||||
|
// });
|
||||||
|
_pagingController.appendLastPage(vehicles);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_showNoMoreDataSnackBar(context);
|
||||||
setState(() {
|
setState(() {
|
||||||
_hasData = true;
|
_hasData = false;
|
||||||
_loading = false;
|
_loading = false;
|
||||||
_wrap.addAll(vehicles);
|
|
||||||
});
|
});
|
||||||
|
print('hasEmpty: ${_wrap.length}');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_showNoMoreDataSnackBar(context);
|
|
||||||
|
|
||||||
setState(() {
|
|
||||||
_hasData = false;
|
|
||||||
_loading = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
print('hasEmpty: ${_wrap.length}');
|
|
||||||
return;
|
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
DialogUtil.errorDefault(context);
|
DialogUtil.errorDefault(context);
|
||||||
LogUtil.requestAPIFailed("proccessRequest.php", "", "Consulta de Veículo", e, s);
|
LogUtil.requestAPIFailed(
|
||||||
|
"proccessRequest.php", "", "Consulta de Veículo", e, s);
|
||||||
setState(() {
|
setState(() {
|
||||||
_hasData = false;
|
_hasData = false;
|
||||||
_loading = false;
|
_loading = false;
|
||||||
|
@ -202,37 +207,48 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget? _generateItems(BuildContext context, dynamic snapshot, int index) {
|
Widget _generateItems(BuildContext context, int index, dynamic item) {
|
||||||
if (index == 0) return _buildHeader(context);
|
log('item: $item');
|
||||||
|
|
||||||
final bool? isOwner = snapshot['isOwnerVehicle'];
|
// return Placeholder();
|
||||||
final IconData? iconData = isOwner == true ? Symbols.garage : Symbols.directions_car;
|
|
||||||
final FreCardIcon? cardIcon = isOwner != null
|
|
||||||
? FreCardIcon(height: 50, width: 100, icon: Icon(iconData, size: 80, opticalSize: 10))
|
|
||||||
: null;
|
|
||||||
|
|
||||||
final String? tag = snapshot['tag'];
|
// if (index == 0) return _buildHeader(context);
|
||||||
final bool containTag = tag.isNotNullAndEmpty;
|
|
||||||
final Map<String, String> labelsHashMap = _generateLabelsHashMap(context, snapshot, tag, containTag);
|
|
||||||
|
|
||||||
final List<Map<String, Color>> statusHashMapList = _generateStatusHashMapList(snapshot);
|
final bool? isOwner = item['isOwnerVehicle'];
|
||||||
|
final IconData? iconData =
|
||||||
|
isOwner == true ? Symbols.garage : Symbols.directions_car;
|
||||||
|
final FreCardIcon? cardIcon = isOwner != null
|
||||||
|
? FreCardIcon(
|
||||||
|
height: 50,
|
||||||
|
width: 100,
|
||||||
|
icon: Icon(iconData, size: 80, opticalSize: 10))
|
||||||
|
: null;
|
||||||
|
|
||||||
Future<void> onTapCardItemAction() async {
|
final String? tag = item['tag'];
|
||||||
_handleCardItemTap(context, cardIcon, snapshot);
|
final bool containTag = tag.isNotNullAndEmpty;
|
||||||
}
|
final Map<String, String> labelsHashMap =
|
||||||
|
_generateLabelsHashMap(context, item, tag, containTag);
|
||||||
|
|
||||||
final statusLinkedHashMap = statusHashMapList.map((map) => LinkedHashMap<String, Color>.from(map)).toList();
|
final List<Map<String, Color>> statusHashMapList =
|
||||||
final length = statusLinkedHashMap.expand((e) => [e.length]);
|
_generateStatusHashMapList(item);
|
||||||
|
|
||||||
return CardItemTemplateComponentWidget(
|
Future<void> onTapCardItemAction() async {
|
||||||
icon: cardIcon,
|
_handleCardItemTap(context, cardIcon, item);
|
||||||
labelsHashMap: labelsHashMap,
|
|
||||||
statusHashMap: statusHashMapList,
|
|
||||||
onTapCardItemAction: onTapCardItemAction,
|
|
||||||
itemWidthFactor: length == 1 ? 0.25 : 0.50,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final statusLinkedHashMap = statusHashMapList
|
||||||
|
.map((map) => LinkedHashMap<String, Color>.from(map))
|
||||||
|
.toList();
|
||||||
|
final length = statusLinkedHashMap.expand((e) => [e.length]);
|
||||||
|
|
||||||
|
return CardItemTemplateComponentWidget(
|
||||||
|
icon: cardIcon,
|
||||||
|
labelsHashMap: labelsHashMap,
|
||||||
|
statusHashMap: statusHashMapList,
|
||||||
|
onTapCardItemAction: onTapCardItemAction,
|
||||||
|
itemWidthFactor: length == 1 ? 0.25 : 0.50,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Map<String, String> _generateLabelsHashMap(BuildContext context,
|
Map<String, String> _generateLabelsHashMap(BuildContext context,
|
||||||
Map<String, dynamic> uItem, String? tag, bool containTag) {
|
Map<String, dynamic> uItem, String? tag, bool containTag) {
|
||||||
|
@ -249,17 +265,16 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Map<String, Color>> _generateStatusHashMapList(
|
List<Map<String, Color>> _generateStatusHashMapList(
|
||||||
Map<String, dynamic> uItem) {
|
Map<String, dynamic> uItem) {
|
||||||
final statusHashMap =
|
final statusHashMap = widget.model.generateStatusColorMap(uItem, false);
|
||||||
widget.model.generateStatusColorMap(uItem, false);
|
|
||||||
return statusHashMap != null ? [statusHashMap] : [];
|
return statusHashMap != null ? [statusHashMap] : [];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handleCardItemTap(BuildContext context, FreCardIcon? cardIcon,
|
Future<void> _handleCardItemTap(BuildContext context, FreCardIcon? cardIcon,
|
||||||
Map<String, dynamic> uItem) async {
|
Map<String, dynamic> uItem) async {
|
||||||
try {
|
try {
|
||||||
final dialogContent = widget.model.buildVehicleDetails(
|
final dialogContent = widget.model.buildVehicleDetails(
|
||||||
icon: cardIcon,
|
icon: cardIcon,
|
||||||
item: uItem,
|
item: uItem,
|
||||||
context: context,
|
context: context,
|
||||||
|
@ -274,7 +289,7 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
||||||
).whenComplete(() {
|
).whenComplete(() {
|
||||||
safeSetState(() {
|
safeSetState(() {
|
||||||
_pageNumber = 1;
|
_pageNumber = 1;
|
||||||
_fetch();
|
_fetch(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
|
@ -289,27 +304,26 @@ mixin Remotable on State<VehicleHistoryScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void _initializeScrollController() {
|
void _initializeScrollController() {
|
||||||
_scrollController = ScrollController(keepScrollOffset: true, initialScrollOffset: offset)
|
// _scrollController = ScrollController(keepScrollOffset: true, initialScrollOffset: offset)
|
||||||
..addListener(() {
|
// ..addListener(() {
|
||||||
print('ScrollController');
|
// print('ScrollController');
|
||||||
if(!_hasData) return;
|
// if(!_hasData) return;
|
||||||
if
|
// if
|
||||||
// (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent)
|
// // (_scrollController.position.pixels >= _scrollController.position.maxScrollExtent)
|
||||||
(_scrollController.position.atEdge && _scrollController.position.pixels != 0)
|
// (_scrollController.position.atEdge && _scrollController.position.pixels != 0)
|
||||||
{
|
// {
|
||||||
print('ScrollController -> loadMore');
|
// print('ScrollController -> loadMore');
|
||||||
offset = _scrollController.offset;
|
// offset = _scrollController.offset;
|
||||||
_loadMore();
|
// _loadMore();
|
||||||
}
|
// }
|
||||||
},);
|
// },);
|
||||||
}
|
|
||||||
|
|
||||||
void _loadMore() {
|
|
||||||
if (_hasData) {
|
|
||||||
_pageNumber+=1;
|
|
||||||
_loading = true;
|
|
||||||
_fetch();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void _loadMore() {
|
||||||
|
// if (_hasData) {
|
||||||
|
// _pageNumber+=1;
|
||||||
|
// _loading = true;
|
||||||
|
// _fetch(_pageNumber);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ import 'package:hub/shared/utils/dialog_util.dart';
|
||||||
import 'package:hub/shared/utils/license_util.dart';
|
import 'package:hub/shared/utils/license_util.dart';
|
||||||
import 'package:hub/shared/utils/limited_text_size.dart';
|
import 'package:hub/shared/utils/limited_text_size.dart';
|
||||||
import 'package:hub/shared/utils/log_util.dart';
|
import 'package:hub/shared/utils/log_util.dart';
|
||||||
|
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
|
||||||
part 'vehicle_history_screen.dart';
|
part 'vehicle_history_screen.dart';
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
19
pubspec.yaml
19
pubspec.yaml
|
@ -15,6 +15,7 @@ dependencies:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
auto_size_text: 3.0.0
|
auto_size_text: 3.0.0
|
||||||
barcode_widget: ^2.0.4
|
barcode_widget: ^2.0.4
|
||||||
|
infinite_scroll_pagination: ^4.1.0
|
||||||
cached_network_image: ^3.4.0
|
cached_network_image: ^3.4.0
|
||||||
firebase_core: ^3.4.0
|
firebase_core: ^3.4.0
|
||||||
flutter_inappwebview: ^6.0.0
|
flutter_inappwebview: ^6.0.0
|
||||||
|
@ -103,7 +104,25 @@ dependencies:
|
||||||
# crypto: ^3.0.5
|
# crypto: ^3.0.5
|
||||||
freezed_annotation: ^2.4.4
|
freezed_annotation: ^2.4.4
|
||||||
package_info_plus: ^8.1.1
|
package_info_plus: ^8.1.1
|
||||||
|
sliver_tools: ^0.2.12
|
||||||
# json_annotation: ^4.9.0
|
# json_annotation: ^4.9.0
|
||||||
|
base:
|
||||||
|
git:
|
||||||
|
url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git'
|
||||||
|
path: 'packages/base'
|
||||||
|
components:
|
||||||
|
git:
|
||||||
|
url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git'
|
||||||
|
path: 'packages/components'
|
||||||
|
templates:
|
||||||
|
git:
|
||||||
|
url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git'
|
||||||
|
path: 'packages/templates'
|
||||||
|
theme:
|
||||||
|
git:
|
||||||
|
url: 'git@github.com:FRE-Informatica/flutter-freaccess-base.git'
|
||||||
|
path: 'packages/theme'
|
||||||
|
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
http: 1.2.1
|
http: 1.2.1
|
||||||
|
|
Loading…
Reference in New Issue