fix: fix channel list pagination spinner (#375)

Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
Sahil Kumar
2021-04-01 13:25:12 +02:00
committed by GitHub
parent 425fd5c4d8
commit 63705693dc
4 changed files with 39 additions and 18 deletions
@@ -628,13 +628,14 @@ class _ChannelListViewState extends State<ChannelListView> {
), ),
); );
} }
return Container( return snapshot.data
height: 100, ? Center(
padding: EdgeInsets.all(32), child: Padding(
child: Center( padding: const EdgeInsets.all(16.0),
child: snapshot.data ? CircularProgressIndicator() : Container(), child: const CircularProgressIndicator(),
), ),
); )
: Offstage();
}); });
} }
@@ -84,6 +84,8 @@ class ChannelsBlocState extends State<ChannelsBloc>
final List<Channel> _hiddenChannels = []; final List<Channel> _hiddenChannels = [];
bool _paginationEnded = false;
/// Calls [client.queryChannels] updating [queryChannelsLoading] stream /// Calls [client.queryChannels] updating [queryChannelsLoading] stream
Future<void> queryChannels({ Future<void> queryChannels({
Map<String, dynamic> filter, Map<String, dynamic> filter,
@@ -93,7 +95,9 @@ class ChannelsBlocState extends State<ChannelsBloc>
}) async { }) async {
final client = StreamChatCore.of(context).client; final client = StreamChatCore.of(context).client;
if (_queryChannelsLoadingController.value == true) return; if (_paginationEnded || _queryChannelsLoadingController.value == true) {
return;
}
if (_channelsController.hasValue) { if (_channelsController.hasValue) {
_queryChannelsLoadingController.add(true); _queryChannelsLoadingController.add(true);
@@ -104,12 +108,14 @@ class ChannelsBlocState extends State<ChannelsBloc>
paginationParams.offset == null || paginationParams.offset == null ||
paginationParams.offset == 0; paginationParams.offset == 0;
final oldChannels = List<Channel>.from(channels ?? []); final oldChannels = List<Channel>.from(channels ?? []);
var newChannels = <Channel>[];
await for (final channels in client.queryChannels( await for (final channels in client.queryChannels(
filter: filter, filter: filter,
sort: sortOptions, sort: sortOptions,
options: options, options: options,
paginationParams: paginationParams, paginationParams: paginationParams,
)) { )) {
newChannels = channels;
if (clear) { if (clear) {
_channelsController.add(channels); _channelsController.add(channels);
} else { } else {
@@ -121,6 +127,9 @@ class ChannelsBlocState extends State<ChannelsBloc>
_queryChannelsLoadingController.sink.add(false); _queryChannelsLoadingController.sink.add(false);
} }
} }
if (newChannels.isEmpty || newChannels.length < paginationParams.limit) {
_paginationEnded = true;
}
} catch (e, stk) { } catch (e, stk) {
if (_channelsController.hasValue) { if (_channelsController.hasValue) {
_queryChannelsLoadingController.addError(e, stk); _queryChannelsLoadingController.addError(e, stk);
@@ -47,6 +47,7 @@ class LazyLoadScrollView extends StatefulWidget {
class _LazyLoadScrollViewState extends State<LazyLoadScrollView> { class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
_LoadingStatus _loadMoreStatus = _LoadingStatus.stable; _LoadingStatus _loadMoreStatus = _LoadingStatus.stable;
double _scrollPosition = 0;
@override @override
Widget build(BuildContext context) => Widget build(BuildContext context) =>
@@ -84,15 +85,21 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
final extentBefore = notification.metrics.extentBefore; final extentBefore = notification.metrics.extentBefore;
final extentAfter = notification.metrics.extentAfter; final extentAfter = notification.metrics.extentAfter;
final scrollingDown = _scrollPosition < pixels;
if (extentAfter <= scrollOffset) { if (scrollingDown) {
_onEndOfPage(); if (extentAfter <= scrollOffset) {
return true; _onEndOfPage();
} return true;
if (extentBefore <= scrollOffset) { }
_onStartOfPage(); } else {
return true; if (extentBefore <= scrollOffset) {
_onStartOfPage();
return true;
}
} }
_scrollPosition = pixels;
} }
if (notification is OverscrollNotification) { if (notification is OverscrollNotification) {
if (notification.overscroll > 0) { if (notification.overscroll > 0) {
@@ -108,8 +115,8 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
void _onEndOfPage() { void _onEndOfPage() {
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) { if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) {
_loadMoreStatus = _LoadingStatus.loading;
if (widget.onEndOfPage != null) { if (widget.onEndOfPage != null) {
_loadMoreStatus = _LoadingStatus.loading;
widget.onEndOfPage().whenComplete(() { widget.onEndOfPage().whenComplete(() {
_loadMoreStatus = _LoadingStatus.stable; _loadMoreStatus = _LoadingStatus.stable;
}); });
@@ -119,8 +126,8 @@ class _LazyLoadScrollViewState extends State<LazyLoadScrollView> {
void _onStartOfPage() { void _onStartOfPage() {
if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) { if (_loadMoreStatus != null && _loadMoreStatus == _LoadingStatus.stable) {
_loadMoreStatus = _LoadingStatus.loading;
if (widget.onStartOfPage != null) { if (widget.onStartOfPage != null) {
_loadMoreStatus = _LoadingStatus.loading;
widget.onStartOfPage().whenComplete(() { widget.onStartOfPage().whenComplete(() {
_loadMoreStatus = _LoadingStatus.stable; _loadMoreStatus = _LoadingStatus.stable;
}); });
@@ -9,7 +9,7 @@ import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import 'mocks.dart'; import 'mocks.dart';
void main() { void main() {
const pagination = PaginationParams(offset: 0, limit: 25); const pagination = PaginationParams(offset: 0, limit: 3);
List<Channel> _generateChannels( List<Channel> _generateChannels(
StreamChatClient client, { StreamChatClient client, {
@@ -180,6 +180,7 @@ void main() {
emptyBuilder: (BuildContext context) => Offstage(), emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => errorBuilder: (BuildContext context, Object error) =>
Container(key: errorWidgetKey), Container(key: errorWidgetKey),
pagination: pagination,
); );
final mockClient = MockClient(); final mockClient = MockClient();
@@ -227,6 +228,7 @@ void main() {
loadingBuilder: (BuildContext context) => Offstage(), loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Container(key: emptyWidgetKey), emptyBuilder: (BuildContext context) => Container(key: emptyWidgetKey),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object error) => Offstage(),
pagination: pagination,
); );
final mockClient = MockClient(); final mockClient = MockClient();
@@ -274,6 +276,7 @@ void main() {
loadingBuilder: (BuildContext context) => Offstage(), loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(), emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object error) => Offstage(),
pagination: pagination,
); );
final mockClient = MockClient(); final mockClient = MockClient();
@@ -329,6 +332,7 @@ void main() {
loadingBuilder: (BuildContext context) => Offstage(), loadingBuilder: (BuildContext context) => Offstage(),
emptyBuilder: (BuildContext context) => Offstage(), emptyBuilder: (BuildContext context) => Offstage(),
errorBuilder: (BuildContext context, Object error) => Offstage(), errorBuilder: (BuildContext context, Object error) => Offstage(),
pagination: pagination,
); );
final mockClient = MockClient(); final mockClient = MockClient();