mirror of
https://github.com/inventree/inventree-app.git
synced 2025-04-27 21:16:48 +00:00
Refresh fix (#436)
* Add notificationPredicate to improve scroll-to-reload Ref: https://api.flutter.dev/flutter/material/RefreshIndicator-class.html * Add scroll-to-refresh for paginated list
This commit is contained in:
parent
8f1cd1cae1
commit
b6ab9d5da5
@ -4,6 +4,7 @@
|
|||||||
- Add ability to scan in received items using supplier barcodes
|
- Add ability to scan in received items using supplier barcodes
|
||||||
- Store API token, rather than username:password
|
- Store API token, rather than username:password
|
||||||
- Ensure that user will lose access if token is revoked by server
|
- Ensure that user will lose access if token is revoked by server
|
||||||
|
- Improve scroll-to-refresh behaviour across multiple widgets
|
||||||
|
|
||||||
|
|
||||||
### 0.12.8 - September 2023
|
### 0.12.8 - September 2023
|
||||||
|
@ -394,31 +394,36 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta
|
|||||||
|
|
||||||
children.add(
|
children.add(
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
physics: ClampingScrollPhysics(),
|
physics: AlwaysScrollableScrollPhysics(),
|
||||||
scrollDirection: Axis.vertical,
|
scrollDirection: Axis.vertical,
|
||||||
slivers: <Widget>[
|
slivers: <Widget>[
|
||||||
PagedSliverList.separated(
|
PagedSliverList.separated(
|
||||||
pagingController: _pagingController,
|
pagingController: _pagingController,
|
||||||
builderDelegate: PagedChildBuilderDelegate<InvenTreeModel>(
|
builderDelegate: PagedChildBuilderDelegate<InvenTreeModel>(
|
||||||
itemBuilder: (ctx, item, index) {
|
itemBuilder: (ctx, item, index) {
|
||||||
return buildItem(ctx, item);
|
return buildItem(ctx, item);
|
||||||
},
|
},
|
||||||
noItemsFoundIndicatorBuilder: (context) {
|
noItemsFoundIndicatorBuilder: (context) {
|
||||||
return NoResultsWidget(noResultsText);
|
return NoResultsWidget(noResultsText);
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
separatorBuilder: (context, item) => const Divider(height: .1),
|
separatorBuilder: (context, item) => const Divider(height: 1),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return Column(
|
return RefreshIndicator(
|
||||||
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
children: children,
|
children: children,
|
||||||
|
),
|
||||||
|
onRefresh: () async {
|
||||||
|
_pagingController.refresh();
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ mixin BaseWidgetProperties {
|
|||||||
*/
|
*/
|
||||||
List<Widget> appBarActions(BuildContext context) => [];
|
List<Widget> appBarActions(BuildContext context) => [];
|
||||||
|
|
||||||
// Return a title for the appBar
|
// Return a title for the appBar (placeholder)
|
||||||
String getAppBarTitle() { return "--- app bar ---"; }
|
String getAppBarTitle() { return "--- app bar ---"; }
|
||||||
|
|
||||||
// Function to construct a drawer (override if needed)
|
// Function to construct a drawer (override if needed)
|
||||||
@ -40,6 +40,7 @@ mixin BaseWidgetProperties {
|
|||||||
|
|
||||||
// Default body calls getTiles()
|
// Default body calls getTiles()
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
|
physics: AlwaysScrollableScrollPhysics(),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: getTiles(context)
|
children: getTiles(context)
|
||||||
)
|
)
|
||||||
@ -202,7 +203,8 @@ mixin BaseWidgetProperties {
|
|||||||
*/
|
*/
|
||||||
abstract class RefreshableState<T extends StatefulWidget> extends State<T> with BaseWidgetProperties {
|
abstract class RefreshableState<T extends StatefulWidget> extends State<T> with BaseWidgetProperties {
|
||||||
|
|
||||||
final refreshableKey = GlobalKey<ScaffoldState>();
|
final scaffoldKey = GlobalKey<ScaffoldState>();
|
||||||
|
final refreshKey = GlobalKey<RefreshIndicatorState>();
|
||||||
|
|
||||||
// Storage for context once "Build" is called
|
// Storage for context once "Build" is called
|
||||||
late BuildContext? _context;
|
late BuildContext? _context;
|
||||||
@ -265,19 +267,31 @@ abstract class RefreshableState<T extends StatefulWidget> extends State<T> with
|
|||||||
|
|
||||||
Widget body = tabs.isEmpty ? getBody(context) : TabBarView(children: getTabs(context));
|
Widget body = tabs.isEmpty ? getBody(context) : TabBarView(children: getTabs(context));
|
||||||
|
|
||||||
|
// predicateDepth needs to be different based on the child type
|
||||||
|
// hack, determined experimentally
|
||||||
|
int predicateDepth = 0;
|
||||||
|
|
||||||
|
if (tabs.isNotEmpty) {
|
||||||
|
predicateDepth = 1;
|
||||||
|
}
|
||||||
|
|
||||||
Scaffold view = Scaffold(
|
Scaffold view = Scaffold(
|
||||||
key: refreshableKey,
|
key: scaffoldKey,
|
||||||
appBar: buildAppBar(context, refreshableKey),
|
appBar: buildAppBar(context, scaffoldKey),
|
||||||
drawer: getDrawer(context),
|
drawer: getDrawer(context),
|
||||||
floatingActionButton: buildSpeedDial(context),
|
floatingActionButton: buildSpeedDial(context),
|
||||||
floatingActionButtonLocation: FloatingActionButtonLocation.miniEndDocked,
|
floatingActionButtonLocation: FloatingActionButtonLocation.miniEndDocked,
|
||||||
body: RefreshIndicator(
|
body: RefreshIndicator(
|
||||||
|
key: refreshKey,
|
||||||
|
notificationPredicate: (ScrollNotification notification) {
|
||||||
|
return notification.depth == predicateDepth;
|
||||||
|
},
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
refresh(context);
|
refresh(context);
|
||||||
},
|
},
|
||||||
child: body
|
child: body
|
||||||
),
|
),
|
||||||
bottomNavigationBar: buildBottomAppBar(context, refreshableKey),
|
bottomNavigationBar: buildBottomAppBar(context, scaffoldKey),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Default implementation is *not* tabbed
|
// Default implementation is *not* tabbed
|
||||||
|
Loading…
x
Reference in New Issue
Block a user