Skip to content

Commit

Permalink
* Added error logs
Browse files Browse the repository at this point in the history
* Optimized initializing PaginatedItemsBuilder
* Added showLoaderOnResetBuilder in PaginationItemsStateHandler to update showLoaderOnReset param for builders with internal state management.
* Updated example app
* Updated README.md
* Updated version
  • Loading branch information
rithik-dev committed Apr 1, 2022
1 parent 8a62afd commit 9e91bfb
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 57 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## [1.1.0] - 01/04/2022

* Added error logs
* Optimized initializing PaginatedItemsBuilder
* Added showLoaderOnResetBuilder in PaginationItemsStateHandler to update showLoaderOnReset param for builders with internal state management.
* Updated example app
* Updated README.md

## [1.0.9] - 31/03/2022

* Added ignore pointer to disable onTap for loaders
Expand Down
68 changes: 43 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,18 @@ Future<void> updateProducts({
notifyListeners();
}
final res = await apiFunction(
// startKey is optional and only required when you have pagination support in api
startKey: reset ? null : _productsResponse?.paginationKey,
);
if (reset || _productsResponse == null) {
_productsResponse = res;
} else {
_productsResponse!.update(res);
try {
final res = await apiFunction(
// startKey is optional and only required when you have pagination support in api
startKey: reset ? null : _productsResponse?.paginationKey,
);
if (reset || _productsResponse == null) {
_productsResponse = res;
} else {
_productsResponse!.update(res);
}
} catch(_) {
// handle error
}
notifyListeners();
}
Expand All @@ -72,23 +76,36 @@ Future<PaginatedItemsResponse<Product>?> apiFunction({
// can be string or int (page number) or any other type.
dynamic startKey,
}) async {
// startKey necessary if pagination support
final res = await _api.getProducts(startKey: startKey);
return PaginatedItemsResponse<Product>(
// list of items
listItems: res.data?.products,
// only required to pass if pagination supported, else null. (can be of any type)
paginationKey: res.data?.paginationKey,
// unique id, should only be passed in the repository function.
// required for functions like `updateItem`, `findByUid`
// and avoiding duplication of items in list (compares uid)
idGetter: (product) => product.id,
);
try {
// startKey necessary if pagination support
final res = await _api.getProducts(startKey: startKey);
return PaginatedItemsResponse<Product>(
// list of items
listItems: res.data?.products,
// only required to pass if pagination supported, else null. (can be of any type)
paginationKey: res.data?.paginationKey,
// unique id, should only be passed in the repository function.
// required for functions like `updateItem`, `findByUid`
// and avoiding duplication of items in list (compares uid)
idGetter: (product) => product.id,
);
} catch(_) {
// handling error is important as if null is returned, the `response` becomes null,
// which in turn causes infinite loading...
// hence, returning a response with empty list, so that screen shows the no items found text,
// so that the user can refresh the contents, and you can probably have a snackBar or toast,
// notifying the user of the error...
return PaginatedItemsResponse<Product>(
listItems: [],
idGetter: (product) => product.id,
);
}
}
```

Expand Down Expand Up @@ -145,6 +162,7 @@ Future<PaginatedItemsResponse<Post>?> updatePosts(dynamic paginationKey) async {
PaginationItemsStateHandler<Post>(
fetchPageData: updatePosts,
showLoaderOnResetBuilder: (itemsFetchScope) => itemsFetchScope == ItemsFetchScope.noItemsRefresh,
builder: (response, fetchPageData) {
return PaginatedItemsBuilder<Post>(
response: response,
Expand Down
18 changes: 11 additions & 7 deletions example/lib/controllers/posts_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ class PostsController extends ChangeNotifier {
notifyListeners();
}

final res = await PostsRepository.getPosts(
startKey: _postsResponse?.paginationKey,
);
if (reset || _postsResponse == null) {
_postsResponse = res;
} else {
_postsResponse!.update(res);
try {
final res = await PostsRepository.getPosts(
startKey: reset ? null : _postsResponse?.paginationKey,
);
if (reset || _postsResponse == null) {
_postsResponse = res;
} else {
_postsResponse!.update(res);
}
} catch (_) {
// handle error
}
notifyListeners();
}
Expand Down
2 changes: 2 additions & 0 deletions example/lib/screens/home_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ class PostsListWithStateHandledInternally extends StatelessWidget {
child: Scaffold(
body: PaginationItemsStateHandler<Post>(
fetchPageData: updatePosts,
showLoaderOnResetBuilder: (itemsFetchScope) =>
itemsFetchScope == ItemsFetchScope.noItemsRefresh,
builder: (response, fetchPageData) {
return PaginatedItemsBuilder<Post>(
response: response,
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ packages:
path: ".."
relative: true
source: path
version: "1.0.9"
version: "1.1.0"
path:
dependency: transitive
description:
Expand Down
18 changes: 12 additions & 6 deletions lib/src/paginated_items_builder.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'dart:developer' as dev;
import 'dart:math';

import 'package:flutter/material.dart';
Expand Down Expand Up @@ -182,6 +183,7 @@ class _PaginatedItemsBuilderState<T> extends State<PaginatedItemsBuilder<T>> {
(widget.response != null &&
!widget.response!.hasMoreData &&
!_loadingMoreData)) return;

setState(() {
// if (_initialLoading) {
// _initialLoading = false;
Expand All @@ -195,10 +197,18 @@ class _PaginatedItemsBuilderState<T> extends State<PaginatedItemsBuilder<T>> {

try {
await widget.fetchPageData(reset, itemsFetchScope);
} catch (_) {}
} catch (error, stackTrace) {
dev.log(
'\nSomething went wrong.. Most probably the fetchPageData failed due to some error! Please handle any possible errors in the fetchPageData call.',
name: 'PaginationItemsBuilder<$T>',
error: error,
stackTrace: stackTrace,
);
}

if (_initialLoading) _initialLoading = false;
if (_loadingMoreData) _loadingMoreData = false;

try {
setState(() {});
} catch (_) {}
Expand Down Expand Up @@ -289,11 +299,7 @@ class _PaginatedItemsBuilderState<T> extends State<PaginatedItemsBuilder<T>> {
? _config?.mockItemGetter<T>()
: _config?.mockItemGetter(widget.mockItemKey);

final itemsStateHandlerAsParent =
context.findAncestorWidgetOfExactType<PaginationItemsStateHandler<T>>();
if (itemsStateHandlerAsParent == null) {
_fetchData(itemsFetchScope: ItemsFetchScope.initialLoad);
}
_fetchData(itemsFetchScope: ItemsFetchScope.initialLoad);

PaginatedItemsBuilder.config ??=
PaginatedItemsBuilderConfig.defaultConfig();
Expand Down
61 changes: 44 additions & 17 deletions lib/src/pagination_items_state_handler.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import 'dart:developer' as dev;

import 'package:flutter/material.dart';
import 'package:paginated_items_builder/paginated_items_builder.dart';

Expand All @@ -22,10 +24,28 @@ class PaginationItemsStateHandler<T> extends StatefulWidget {
fetchPageData,
) builder;

/// Whether to switch all the cards to their respective loaders when [reset] is true,
/// i.e. if the user pulls down to refresh, or no items were found...
///
/// The callback value is the [ItemsFetchScope], which defines the action calling the
/// fetch data function.
///
/// The [reset] flag will be true only when the [itemsFetchScope] is either
/// [ItemsFetchScope.noItemsRefresh] i.e. no items were found, and user
/// clicked the refresh icon OR [ItemsFetchScope.pullDownToRefresh] i.e.
/// the user wants to refresh the list contents with pull-down action.
///
/// This callback will only be called if [reset] is true.
///
/// By default, [showLoaderOnResetBuilder] is true only if [scope] is [ItemsFetchScope.noItemsRefresh].
final bool Function(ItemsFetchScope itemsFetchScope)?
showLoaderOnResetBuilder;

const PaginationItemsStateHandler({
Key? key,
required this.fetchPageData,
required this.builder,
this.showLoaderOnResetBuilder,
}) : super(key: key);

@override
Expand All @@ -35,36 +55,43 @@ class PaginationItemsStateHandler<T> extends StatefulWidget {

class _PaginationItemsStateHandlerState<T>
extends State<PaginationItemsStateHandler<T>> {
PaginatedItemsResponse<T>? itemsResponse;
PaginatedItemsResponse<T>? _itemsResponse;

Future<void> _update(bool reset, ItemsFetchScope scope) async {
if (reset) {
itemsResponse = null;
bool showLoaderOnReset = scope == ItemsFetchScope.noItemsRefresh;
if (reset && widget.showLoaderOnResetBuilder != null) {
showLoaderOnReset = widget.showLoaderOnResetBuilder!(scope);
}

// showLoaderOnReset only used if reset is true...
if (reset && showLoaderOnReset) {
_itemsResponse = null;
setState(() {});
}

try {
final res = await widget.fetchPageData(itemsResponse?.paginationKey);
if (itemsResponse == null) {
itemsResponse = res;
final res = await widget.fetchPageData(
reset ? null : _itemsResponse?.paginationKey,
);
if (reset || _itemsResponse == null) {
_itemsResponse = res;
} else {
itemsResponse!.update(res);
_itemsResponse!.update(res);
}
} catch (_) {}
} catch (error, stackTrace) {
dev.log(
'\nSomething went wrong.. Most probably the fetchPageData failed due to some error! Please handle any possible errors in the fetchPageData call.',
name: 'PaginationItemsStateHandler<$T>',
error: error,
stackTrace: stackTrace,
);
}

try {
setState(() {});
} catch (_) {}
}

@override
void initState() {
_update(false, ItemsFetchScope.initialLoad);
super.initState();
}

@override
Widget build(BuildContext context) {
return widget.builder(itemsResponse, _update);
}
Widget build(BuildContext context) => widget.builder(_itemsResponse, _update);
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: paginated_items_builder
description: Easier to display items in a list/grid view from your controllers directly or handling state internally with support for pagination.
version: 1.0.9
version: 1.1.0
homepage: https://github.com/rithik-dev/paginated_items_builder

environment:
Expand Down

0 comments on commit 9e91bfb

Please sign in to comment.