151 lines
3.9 KiB
Dart
151 lines
3.9 KiB
Dart
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<MessageSearchBlocState>();
|
|
|
|
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<MessageSearchBloc>
|
|
with AutomaticKeepAliveClientMixin {
|
|
/// The current messages list
|
|
List<GetMessageResponse> get messageResponses => _messageResponses.value;
|
|
|
|
/// The current messages list as a stream
|
|
Stream<List<GetMessageResponse>> get messagesStream =>
|
|
_messageResponses.stream;
|
|
|
|
final BehaviorSubject<List<GetMessageResponse>> _messageResponses =
|
|
BehaviorSubject();
|
|
|
|
final BehaviorSubject<bool> _queryMessagesLoadingController =
|
|
BehaviorSubject.seeded(false);
|
|
|
|
/// The stream notifying the state of queryUsers call
|
|
Stream<bool> get queryMessagesLoading =>
|
|
_queryMessagesLoadingController.stream;
|
|
|
|
/// Calls [Client.search] updating [messageResponses] stream
|
|
Future<void> search({
|
|
Map<String, dynamic> filter,
|
|
Map<String, dynamic> messageFilter,
|
|
List<SortOption> 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<void> loadMore({
|
|
Map<String, dynamic> filter,
|
|
Map<String, dynamic> messageFilter,
|
|
List<SortOption> 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<GetMessageResponse>.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<SearchMessagesResponse> _search({
|
|
Map<String, dynamic> filter,
|
|
Map<String, dynamic> messageFilter,
|
|
List<SortOption> 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;
|
|
}
|