mirror of
				https://github.com/inventree/inventree-app.git
				synced 2025-10-31 13:25:40 +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:
		| @@ -394,31 +394,36 @@ abstract class PaginatedSearchState<T extends PaginatedSearchWidget> extends Sta | ||||
|  | ||||
|     children.add( | ||||
|       Expanded( | ||||
|         child: CustomScrollView( | ||||
|             shrinkWrap: true, | ||||
|             physics: ClampingScrollPhysics(), | ||||
|             scrollDirection: Axis.vertical, | ||||
|             slivers: <Widget>[ | ||||
|               PagedSliverList.separated( | ||||
|                 pagingController: _pagingController, | ||||
|                 builderDelegate: PagedChildBuilderDelegate<InvenTreeModel>( | ||||
|                     itemBuilder: (ctx, item, index) { | ||||
|                       return buildItem(ctx, item); | ||||
|                     }, | ||||
|                     noItemsFoundIndicatorBuilder: (context) { | ||||
|                       return NoResultsWidget(noResultsText); | ||||
|                     } | ||||
|                 ), | ||||
|                 separatorBuilder: (context, item) => const Divider(height: .1), | ||||
|               ) | ||||
|             ] | ||||
|           child: CustomScrollView( | ||||
|               shrinkWrap: true, | ||||
|               physics: AlwaysScrollableScrollPhysics(), | ||||
|               scrollDirection: Axis.vertical, | ||||
|               slivers: <Widget>[ | ||||
|                 PagedSliverList.separated( | ||||
|                   pagingController: _pagingController, | ||||
|                   builderDelegate: PagedChildBuilderDelegate<InvenTreeModel>( | ||||
|                       itemBuilder: (ctx, item, index) { | ||||
|                         return buildItem(ctx, item); | ||||
|                       }, | ||||
|                       noItemsFoundIndicatorBuilder: (context) { | ||||
|                         return NoResultsWidget(noResultsText); | ||||
|                       } | ||||
|                   ), | ||||
|                   separatorBuilder: (context, item) => const Divider(height: 1), | ||||
|                 ) | ||||
|               ] | ||||
|           ) | ||||
|         ) | ||||
|       ) | ||||
|     ); | ||||
|  | ||||
|     return Column( | ||||
|     return RefreshIndicator( | ||||
|       child: Column( | ||||
|         mainAxisAlignment: MainAxisAlignment.start, | ||||
|         children: children, | ||||
|       ), | ||||
|       onRefresh: () async { | ||||
|         _pagingController.refresh(); | ||||
|       }, | ||||
|     ); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,7 @@ mixin BaseWidgetProperties { | ||||
|    */ | ||||
|   List<Widget> appBarActions(BuildContext context) => []; | ||||
|  | ||||
|   // Return a title for the appBar | ||||
|   // Return a title for the appBar (placeholder) | ||||
|   String getAppBarTitle() { return "--- app bar ---"; } | ||||
|  | ||||
|   // Function to construct a drawer (override if needed) | ||||
| @@ -40,6 +40,7 @@ mixin BaseWidgetProperties { | ||||
|  | ||||
|     // Default body calls getTiles() | ||||
|     return SingleChildScrollView( | ||||
|       physics: AlwaysScrollableScrollPhysics(), | ||||
|       child: Column( | ||||
|         children: getTiles(context) | ||||
|       ) | ||||
| @@ -202,7 +203,8 @@ mixin 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 | ||||
|   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)); | ||||
|  | ||||
|     // predicateDepth needs to be different based on the child type | ||||
|     // hack, determined experimentally | ||||
|     int predicateDepth = 0; | ||||
|  | ||||
|     if (tabs.isNotEmpty) { | ||||
|       predicateDepth = 1; | ||||
|     } | ||||
|  | ||||
|     Scaffold view = Scaffold( | ||||
|       key: refreshableKey, | ||||
|       appBar: buildAppBar(context, refreshableKey), | ||||
|       key: scaffoldKey, | ||||
|       appBar: buildAppBar(context, scaffoldKey), | ||||
|       drawer: getDrawer(context), | ||||
|       floatingActionButton: buildSpeedDial(context), | ||||
|       floatingActionButtonLocation: FloatingActionButtonLocation.miniEndDocked, | ||||
|       body: RefreshIndicator( | ||||
|         key: refreshKey, | ||||
|         notificationPredicate: (ScrollNotification notification) { | ||||
|           return notification.depth == predicateDepth; | ||||
|         }, | ||||
|         onRefresh: () async { | ||||
|           refresh(context); | ||||
|         }, | ||||
|         child: body | ||||
|       ), | ||||
|       bottomNavigationBar: buildBottomAppBar(context, refreshableKey), | ||||
|       bottomNavigationBar: buildBottomAppBar(context, scaffoldKey), | ||||
|     ); | ||||
|  | ||||
|     // Default implementation is *not* tabbed | ||||
|   | ||||
		Reference in New Issue
	
	Block a user