diff --git a/lib/set_list.dart b/lib/set_list.dart index 0f84cce..5c4d32f 100644 --- a/lib/set_list.dart +++ b/lib/set_list.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:fmassive/database.dart'; import 'package:fmassive/edit_set.dart'; import 'package:fmassive/main.dart'; +import 'package:infinite_scroll_pagination/infinite_scroll_pagination.dart'; import 'package:intl/intl.dart'; import 'package:moor_flutter/moor_flutter.dart'; @@ -16,25 +17,41 @@ class SetList extends StatefulWidget { class _SetList extends State { bool showSearch = false; - late Stream> stream; + final PagingController pagingController = + PagingController(firstPageKey: 0); @override initState() { super.initState(); - setStream(); - } - - void setStream() { - stream = (db.select(db.gymSets) - ..where((gymSet) => gymSet.name.contains(widget.search)) - ..limit(10, offset: 0)) - .watch(); + pagingController.addPageRequestListener((pageKey) { + fetch(pageKey); + }); } @override didUpdateWidget(covariant SetList oldWidget) { super.didUpdateWidget(oldWidget); - setStream(); + pagingController.refresh(); + } + + Future fetch(int pageKey) async { + try { + final gymSets = await (db.select(db.gymSets) + ..where((gymSet) => gymSet.name.contains(widget.search)) + ..limit(10, offset: pageKey * 10)) + .get(); + + final isLastPage = gymSets.length < 10; + + if (isLastPage) { + pagingController.appendLastPage(gymSets); + } else { + final nextPageKey = pageKey + 1; + pagingController.appendPage(gymSets, nextPageKey); + } + } catch (error) { + pagingController.error = error; + } } void toggleSearch() { @@ -46,50 +63,53 @@ class _SetList extends State { @override Widget build(BuildContext context) { return Scaffold( - body: StreamBuilder>( - stream: stream, - builder: (context, snapshot) { - final gymSets = snapshot.data; - - if (gymSets == null) - return const Center(child: CircularProgressIndicator()); - - return ListView.builder( - itemCount: gymSets.length, - itemBuilder: (context, index) { - return ListTile( - title: Text(gymSets[index].name), - subtitle: Text( - "${gymSets[index].reps} x ${gymSets[index].weight}kg"), - trailing: Text(DateFormat("yyyy-MM-dd") - .format(DateTime.parse(gymSets[index].created))), - onTap: () async { - await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => EditGymSetPage( - gymSet: gymSets[index].toCompanion(false)), - ), - ); - }); - }, - ); - }), - floatingActionButton: FloatingActionButton( - onPressed: () async { + body: PagedListView( + pagingController: pagingController, + builderDelegate: PagedChildBuilderDelegate( + itemBuilder: (context, gymSet, index) => ListTile( + title: Text(gymSet.name), + subtitle: Text("${gymSet.reps} x ${gymSet.weight}kg"), + trailing: Text( + DateFormat("yyyy-MM-dd").format(DateTime.parse(gymSet.created)), + ), + onTap: () async { await Navigator.push( context, MaterialPageRoute( builder: (context) => EditGymSetPage( - gymSet: GymSetsCompanion( - name: const Value(''), - reps: const Value(0), - weight: const Value(0), - image: const Value(''), - created: Value(DateTime.now().toString()))), + gymSet: gymSet.toCompanion(false), + ), ), ); + pagingController.refresh(); }, - child: const Icon(Icons.add))); + ), + firstPageProgressIndicatorBuilder: (_) => + const Center(child: CircularProgressIndicator()), + newPageProgressIndicatorBuilder: (_) => + const Center(child: CircularProgressIndicator()), + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: () async { + await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => EditGymSetPage( + gymSet: GymSetsCompanion( + name: const Value(''), + reps: const Value(0), + weight: const Value(0), + image: const Value(''), + created: Value(DateTime.now().toString()), + ), + ), + ), + ); + pagingController.refresh(); + }, + child: const Icon(Icons.add), + ), + ); } } diff --git a/pubspec.lock b/pubspec.lock index a91cecc..cca7507 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -392,6 +392,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" + infinite_scroll_pagination: + dependency: "direct main" + description: + name: infinite_scroll_pagination + sha256: "9517328f4e373f08f57dbb11c5aac5b05554142024d6b60c903f3b73476d52db" + url: "https://pub.dev" + source: hosted + version: "3.2.0" intl: dependency: "direct main" description: @@ -677,6 +685,14 @@ packages: description: flutter source: sdk version: "0.0.99" + sliver_tools: + dependency: transitive + description: + name: sliver_tools + sha256: ccdc502098a8bfa07b3ec582c282620031481300035584e1bb3aca296a505e8c + url: "https://pub.dev" + source: hosted + version: "0.2.10" source_gen: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 489b501..1757942 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,6 +46,7 @@ dependencies: audioplayers: ^4.0.1 intl: ^0.18.0 permission_handler: ^10.2.0 + infinite_scroll_pagination: ^3.2.0 dev_dependencies: flutter_test: