mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-28 21:46:46 +00:00
PartList display now utilizes infinite scrolling
This commit is contained in:
parent
11b9668b7f
commit
64e544c043
@ -19,6 +19,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart';
|
||||||
|
|
||||||
class CategoryDisplayWidget extends StatefulWidget {
|
class CategoryDisplayWidget extends StatefulWidget {
|
||||||
|
|
||||||
@ -124,8 +125,6 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
|
|||||||
|
|
||||||
List<InvenTreePartCategory> _subcategories = List<InvenTreePartCategory>();
|
List<InvenTreePartCategory> _subcategories = List<InvenTreePartCategory>();
|
||||||
|
|
||||||
List<InvenTreePart> _parts = List<InvenTreePart>();
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> onBuild(BuildContext context) async {
|
Future<void> onBuild(BuildContext context) async {
|
||||||
refresh();
|
refresh();
|
||||||
@ -154,20 +153,6 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
|
|||||||
// Update state
|
// Update state
|
||||||
setState(() {});
|
setState(() {});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Request a list of parts under this category
|
|
||||||
await InvenTreePart().list(context, filters: {"category": "$pk"}).then((var parts) {
|
|
||||||
_parts.clear();
|
|
||||||
|
|
||||||
for (var part in parts) {
|
|
||||||
if (part is InvenTreePart) {
|
|
||||||
_parts.add(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update state
|
|
||||||
setState(() {});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget getCategoryDescriptionCard() {
|
Widget getCategoryDescriptionCard() {
|
||||||
@ -262,32 +247,6 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
|
|||||||
return tiles;
|
return tiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> partTiles() {
|
|
||||||
List<Widget> tiles = <Widget>[
|
|
||||||
getCategoryDescriptionCard(),
|
|
||||||
ListTile(
|
|
||||||
title: Text(
|
|
||||||
I18N.of(context).parts,
|
|
||||||
style: TextStyle(fontWeight: FontWeight.bold)
|
|
||||||
),
|
|
||||||
trailing: _parts.isNotEmpty ? Text("${_parts.length}") : null,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
tiles.add(progressIndicator());
|
|
||||||
} else if (_parts.length == 0) {
|
|
||||||
tiles.add(ListTile(
|
|
||||||
title: Text("No Parts"),
|
|
||||||
subtitle: Text("No parts available in this category")
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
tiles.add(PartList(_parts));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tiles;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Widget> actionTiles() {
|
List<Widget> actionTiles() {
|
||||||
|
|
||||||
List<Widget> tiles = [
|
List<Widget> tiles = [
|
||||||
@ -313,9 +272,7 @@ class _CategoryDisplayState extends RefreshableState<CategoryDisplayWidget> {
|
|||||||
children: detailTiles()
|
children: detailTiles()
|
||||||
);
|
);
|
||||||
case 1:
|
case 1:
|
||||||
return ListView(
|
return PaginatedPartList(category?.pk ?? null);
|
||||||
children: partTiles()
|
|
||||||
);
|
|
||||||
case 2:
|
case 2:
|
||||||
return ListView(
|
return ListView(
|
||||||
children: actionTiles()
|
children: actionTiles()
|
||||||
@ -368,13 +325,67 @@ class SubcategoryList extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Builder for displaying a list of Part objects
|
* Widget for displaying a list of Part objects within a PartCategory display.
|
||||||
|
*
|
||||||
|
* Uses server-side pagination for snappy results
|
||||||
*/
|
*/
|
||||||
class PartList extends StatelessWidget {
|
|
||||||
final List<InvenTreePart> _parts;
|
|
||||||
|
|
||||||
PartList(this._parts);
|
class PaginatedPartList extends StatefulWidget {
|
||||||
|
|
||||||
|
final int categoryId;
|
||||||
|
|
||||||
|
PaginatedPartList(this.categoryId);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_PaginatedPartListState createState() => _PaginatedPartListState(categoryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class _PaginatedPartListState extends State<PaginatedPartList> {
|
||||||
|
|
||||||
|
static const _pageSize = 25;
|
||||||
|
|
||||||
|
final int categoryId;
|
||||||
|
|
||||||
|
_PaginatedPartListState(this.categoryId);
|
||||||
|
|
||||||
|
final PagingController<int, InvenTreePart> _pagingController = PagingController(firstPageKey: 0);
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_pagingController.addPageRequestListener((pageKey) {
|
||||||
|
_fetchPage(pageKey);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _fetchPage(int pageKey) async {
|
||||||
|
try {
|
||||||
|
|
||||||
|
final page = await InvenTreePart().listPaginated(_pageSize, pageKey, filters: {"category": "${categoryId}"});
|
||||||
|
final isLastPage = page.length < _pageSize;
|
||||||
|
|
||||||
|
// Construct a list of part objects
|
||||||
|
List<InvenTreePart> parts = [];
|
||||||
|
|
||||||
|
for (var result in page.results) {
|
||||||
|
if (result is InvenTreePart) {
|
||||||
|
parts.add(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLastPage) {
|
||||||
|
_pagingController.appendLastPage(parts);
|
||||||
|
} else {
|
||||||
|
final int nextPageKey = pageKey + page.length;
|
||||||
|
_pagingController.appendPage(parts, nextPageKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
print("Error! - ${error.toString()}");
|
||||||
|
_pagingController.error = error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void _openPart(BuildContext context, int pk) {
|
void _openPart(BuildContext context, int pk) {
|
||||||
// Attempt to load the part information
|
// Attempt to load the part information
|
||||||
@ -386,13 +397,7 @@ class PartList extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _build(BuildContext context, int index) {
|
Widget _buildPart(BuildContext context, InvenTreePart part) {
|
||||||
InvenTreePart part;
|
|
||||||
|
|
||||||
if (index < _parts.length) {
|
|
||||||
part = _parts[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text(part.fullname),
|
title: Text(part.fullname),
|
||||||
subtitle: Text("${part.description}"),
|
subtitle: Text("${part.description}"),
|
||||||
@ -406,15 +411,18 @@ class PartList extends StatelessWidget {
|
|||||||
_openPart(context, part.pk);
|
_openPart(context, part.pk);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ListView.separated(
|
return PagedListView<int, InvenTreePart>.separated(
|
||||||
shrinkWrap: true,
|
pagingController: _pagingController,
|
||||||
physics: ClampingScrollPhysics(),
|
builderDelegate: PagedChildBuilderDelegate<InvenTreePart>(
|
||||||
separatorBuilder: (_, __) => const Divider(height: 3),
|
itemBuilder: (context, item, index) {
|
||||||
itemBuilder: _build, itemCount: _parts.length);
|
return _buildPart(context, item);
|
||||||
|
}
|
||||||
|
),
|
||||||
|
separatorBuilder: (context, index) => const Divider(height: 1),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user