import 'package:flutter/material.dart'; import 'package:rxdart/rxdart.dart'; import 'package:stream_chat/stream_chat.dart'; import 'stream_chat.dart'; /// Widget dedicated to the management of a message list with pagination class MessageSearchBloc extends StatefulWidget { /// The widget child final Widget child; /// Instantiate a new MessageSearchBloc const MessageSearchBloc({ Key key, @required this.child, }) : super(key: key); @override MessageSearchBlocState createState() => MessageSearchBlocState(); /// Use this method to get the current [MessageSearchBlocState] instance static MessageSearchBlocState of(BuildContext context) { MessageSearchBlocState state; state = context.findAncestorStateOfType(); if (state == null) { throw Exception('You must have a MessageSearchBloc widget as ancestor'); } return state; } } /// The current state of the [MessageSearchBloc] class MessageSearchBlocState extends State with AutomaticKeepAliveClientMixin { /// The current messages list List get messageResponses => _messageResponses.value; /// The current messages list as a stream Stream> get messagesStream => _messageResponses.stream; final BehaviorSubject> _messageResponses = BehaviorSubject(); final BehaviorSubject _queryMessagesLoadingController = BehaviorSubject.seeded(false); /// The stream notifying the state of queryUsers call Stream get queryMessagesLoading => _queryMessagesLoadingController.stream; /// Calls [Client.search] updating [messageResponses] stream Future search({ Map filter, Map messageFilter, List sort, String query, PaginationParams pagination, }) async { _messageResponses.add(null); try { final messages = await _search( filter: filter, messageFilter: messageFilter, sort: sort, query: query, pagination: pagination, ); _messageResponses.add(messages.results); } catch (err, stk) { _messageResponses.addError(err, stk); } } /// Calls [Client.search] updating [queryMessagesLoading] stream Future loadMore({ Map filter, Map messageFilter, List sort, String query, PaginationParams pagination, }) async { if (_queryMessagesLoadingController.value == true) { return; } _queryMessagesLoadingController.add(true); try { final clear = pagination == null || pagination.offset == null || pagination.offset == 0; final oldMessages = List.from(messageResponses ?? []); final messages = await _search( filter: filter, messageFilter: messageFilter, sort: sort, query: query, pagination: pagination, ); if (clear) { _messageResponses.add(messages.results); } else { final temp = oldMessages + messages.results; _messageResponses.add(temp); } _queryMessagesLoadingController.add(false); } catch (err, stackTrace) { _queryMessagesLoadingController.addError(err, stackTrace); } } Future _search({ Map filter, Map messageFilter, List sort, String query, PaginationParams pagination, }) { final client = StreamChat.of(context).client; return client.search( filter, sort, query, pagination, messageFilters: messageFilter, ); } @override Widget build(BuildContext context) { super.build(context); return widget.child; } @override void dispose() { _messageResponses.close(); _queryMessagesLoadingController.close(); super.dispose(); } @override bool get wantKeepAlive => true; }