fix: fix channel list pagination spinner (#375)
Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
@@ -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();
|
||||||
|
|||||||
Reference in New Issue
Block a user