Skip to main content
Version: v7

Message Search

A Widget For Controlling A List Of Searched Messages

Find the pub.dev documentation here

Background

The StreamMessageSearchListController is a controller class that allows you to control a list of searched messages. StreamMessageSearchListController is a required parameter of the StreamMessageSearchListView widget. Check the StreamMessageSearchListView documentation to read more about that.

Basic Example

Building a custom message search feature is a common task. Here is an example of how to use the StreamMessageSearchListController to build a simple search list with pagination.

First of all we should create an instance of the StreamMessageSearchListController and provide it with the StreamChatClient instance. You can also add a Filter, a list of SortOptions and other pagination-related parameters.

class SearchListPageState extends State<SearchListPage> {
/// Controller used for loading more data and controlling pagination in
/// [StreamMessageSearchListController].
late final messageSearchListController = StreamMessageSearchListController(
client: StreamChatCore.of(context).client,
);

Make sure you call messageSearchListController.doInitialLoad() to load the initial data and messageSearchListController.dispose() when the controller is no longer required.

@override
void initState() {
messageSearchListController.doInitialLoad();
super.initState();
}

@override
void dispose() {
messageSearchListController.dispose();
super.dispose();
}

The StreamMessageSearchListController is basically a PagedValueNotifier that notifies you when the list of responses has changed. You can use a PagedValueListenableBuilder to build your UI depending on the latest responses.

@override
Widget build(BuildContext context) => Scaffold(
body: Column(
children: [
TextField(
/// This is just a sample implementation of a search field.
/// In a real-world app you should throttle the search requests.
/// You can use our library [rate_limiter](https://pub.dev/packages/rate_limiter).
onChanged: (s) {
messageSearchListController..searchQuery = s..doInitialLoad();
},
),
Expanded(
child: PagedValueListenableBuilder<String, GetMessageResponse>(
valueListenable: messageSearchListController,
builder: (context, value, child) {
return value.when(
(responses, nextPageKey, error) => LazyLoadScrollView(
onEndOfPage: () async {
if (nextPageKey != null) {
messageSearchListController.loadMore(nextPageKey);
}
},
child: ListView.builder(
/// We're using the responses length when there are no more
/// pages to load and there are no errors with pagination.
/// In case we need to show a loading indicator or and error
/// tile we're increasing the count by 1.
itemCount: (nextPageKey != null || error != null)
? responses.length + 1
: responses.length,
itemBuilder: (BuildContext context, int index) {
if (index == responses.length) {
if (error != null) {
return TextButton(
onPressed: () {
messageSearchListController.retry();
},
child: Text(error.message),
);
}
return const CircularProgressIndicator();
}

final _item = responses[index];
return ListTile(
title: Text(_item.channel?.name ?? ''),
subtitle: Text(_item.message.text ?? ''),
);
},
),
),
loading: () => const Center(
child: SizedBox(
height: 100,
width: 100,
child: CircularProgressIndicator(),
),
),
error: (e) => Center(
child: Text(
'Oh no, something went wrong. '
'Please check your config. $e',
),
),
);
},
),
),
],
),
);

In this case we're using the LazyLoadScrollView widget to load more data when the user scrolls to the bottom of the list.

Did you find this page helpful?