Merge pull request #529 from GetStream/docusaurus
docs: docusaurus docs
@@ -0,0 +1,20 @@
|
||||
name: docusaurus
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
paths:
|
||||
- docusaurus/**
|
||||
jobs:
|
||||
push_docusaurus:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: push
|
||||
uses: GetStream/push-stream-chat-docusaurus-action@main
|
||||
with:
|
||||
target-branch: ${{ github.ref == 'refs/heads/master' && 'production' || 'staging' }}
|
||||
env:
|
||||
DOCUSAURUS_GH_TOKEN: ${{ secrets.DOCUSAURUS_GH_TOKEN }}
|
||||
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 876 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 9.2 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 459 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 242 KiB |
|
After Width: | Height: | Size: 564 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Introduction",
|
||||
"position": 1
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
id: choose_package
|
||||
sidebar_position: 2
|
||||
title: Choosing The Right Flutter Package
|
||||
---
|
||||
|
||||
### Why the SDK is split into different packages
|
||||
|
||||
Different applications need different levels of customization and integration with the Stream Chat SDK.
|
||||
To do this, the Flutter SDK is split into three different packages which build upon the last and give
|
||||
varying levels of control to the developer. The higher level packages offer better compatibility out of the
|
||||
box while the lower level SDKs offer fine grained control. There is also a separate package for persistence
|
||||
which allows you persist data locally which works with all packages.
|
||||
|
||||
### How do I choose?
|
||||
|
||||
#### The case for stream_chat_flutter
|
||||
|
||||
For the quickest way to integrate Stream Chat with your app, the UI SDK (`stream_chat_flutter`) is the
|
||||
way to go. `stream_chat_flutter` contains prebuilt components that manage most operations like data
|
||||
fetching, pagination, sending a message, and more. This ensures you have a nearly out-of-the-box
|
||||
experience adding chat to your applications. It is also possible to use this in conjunction with
|
||||
lower level operations of the SDK to get the best of both worlds.
|
||||
|
||||
:::note
|
||||
The package allows customization of components to a large extent making it easy to tweak the theme
|
||||
to match your app colors and such. If you require any additional feature or customization, feel free
|
||||
to request this through our support channels.
|
||||
:::
|
||||
|
||||
<b>Summary:</b>
|
||||
|
||||
For the quickest and easiest way to add Chat to your app with prebuilt UI components, use stream_chat_flutter
|
||||
|
||||
|
||||
#### The case for stream_chat_flutter_core
|
||||
|
||||
If your application involves UI that does not fit in with the stream_chat_flutter components, stream_chat_flutter_core
|
||||
strips away the UI associated with the components and provides the data fetching and manipulation
|
||||
capabilities while supplying builders for UI. This allows you to implement your own UI and themes
|
||||
completely independently while not worrying about writing functions for data and pagination.
|
||||
|
||||
<b>Summary:</b>
|
||||
|
||||
For implementing your own custom UI while not having to worry about lower level API calls, use stream_chat_flutter_core.
|
||||
|
||||
#### The case for stream_chat
|
||||
|
||||
The stream_chat package is the Low-level Client (LLC) of Stream Chat in Flutter. This package wraps
|
||||
the underlying functionality of Stream Chat and allows the most customization in terms of UI, data,
|
||||
and architecture.
|
||||
|
||||
<b>Summary:</b>
|
||||
|
||||
For the most control over the SDK and dealing with low level calls to the API, use stream_chat.
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
slug: /
|
||||
id: introduction
|
||||
sidebar_position: 1
|
||||
title: About The Flutter SDK
|
||||
---
|
||||
Exploring The Basics Of Stream Chat
|
||||
|
||||

|
||||
|
||||
Stream Chat is a service that helps you easily build a full chat experience in your Flutter (and more) apps.
|
||||
|
||||
This section of the documentation focuses on our Flutter SDK which helps you easily
|
||||
ship high quality messaging experiences in apps and programs built with the [Flutter toolkit made
|
||||
by Google](https://flutter.dev).
|
||||
|
||||
The Stream Chat Flutter SDK comprises of four different packages to choose from ranging from ones
|
||||
giving you complete control to ones that give you a rich out-of-the-box chat experience.
|
||||
|
||||
The packages that make up the Stream Chat SDK are:
|
||||
|
||||
1. <b>Low Level Client (stream_chat)</b>: a pure Dart package that can be used on any Dart project.
|
||||
It provides a low-level client to access the Stream Chat service.
|
||||
2. <b>Core (stream_chat_flutter_core)</b>: provides business logic to fetch common things required
|
||||
for integrating Stream Chat into your application.
|
||||
The core package allows more customisation and hence provides business logic but no UI components.
|
||||
3. <b>UI (stream_chat_flutter)</b>: this library includes both a low-level chat SDK and a set of
|
||||
reusable and customisable UI components.
|
||||
4. <b>Persistence (stream_chat_persistence)</b>: provides a persistence client for fetching and
|
||||
saving chat data locally.
|
||||
|
||||
We recommend building prototypes using the full UI package since it contains UI widgets already
|
||||
integrated with Stream's API. [stream_chat_flutter](https://pub.dev/packages/stream_chat_flutter)
|
||||
is the fastest way to get up and running using Stream chat in your app.
|
||||
|
||||
The Flutter SDK enables you to build any type of chat or messaging experience for Android, iOS, Web
|
||||
and Desktop.
|
||||
|
||||
If you're building a very custom UI and would prefer a more lean package,
|
||||
our [core package](https://pub.dev/packages/stream_chat_flutter) will be suited to this use case. Core allows you to build custom,
|
||||
expressive UIs while retaining the benefits of our full Flutter SDK.
|
||||
APIs for accessing and controlling users, sending messages, etc are seamlessly integrated into
|
||||
this package and accessible via providers and builders.
|
||||
|
||||
Before going into the docs, let's take a small detour to look at how the elements of Stream Chat are structured.
|
||||
|
||||
There are two core elements in chat, <b>Users and Channels.</b>
|
||||
Channels are groups of one or more users that can message each other.
|
||||
In an app, you need to have a user connected to query channels.
|
||||
|
||||
There is no specific distinction between a chat between two people and a group chat,
|
||||
but there is a way to create a unique chat between a certain number of people by creating a <b>distinct</b> channel.
|
||||
|
||||

|
||||
|
||||
In essence, a normal two-person chat would be a <b>distinct channel</b> created with two members (you cannot add or delete members in this channel), whereas a group created with two people would simply be a <b>non distinct channel</b> (possible to add or remove members).
|
||||
|
||||
Note: It is also possible to add more than two people in a distinct channel which retains the same add/removal properties and resembles the Slack DMs where you can DM one or more people as well.
|
||||
|
||||
In summary, if you were creating a Whatsapp-like app, the first screen would be a <b>list of channels</b> - which on opening would show a <b>list of messages</b> that were sent by the users in the Channel.
|
||||
|
||||
While this is a simplistic overview of the service, the Flutter SDK handles the UI and more time consuming things (media upload, offline storage, theming, etc.) for you.
|
||||
|
||||
Before reading the docs, consider trying our [online API tour](https://getstream.io/chat/get_started/),
|
||||
it is a nice way to learn how the API works.
|
||||
It's in-browser so Javascript-based but the ideas are pretty much the same as Dart.
|
||||
|
||||
You may also like to look at the [Flutter tutorial](https://getstream.io/chat/flutter/tutorial/)
|
||||
which focuses on using the UI package to get Stream Chat integrated into a Flutter app.
|
||||
|
||||
Further sections break down each individual packages and explain several common operations.
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Guides",
|
||||
"position": 2
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
---
|
||||
id: adding_custom_attachments
|
||||
sidebar_position: 4
|
||||
title: Adding Custom Attachments
|
||||
---
|
||||
|
||||
Adding Your Own Types Of Attachments To A Message
|
||||
|
||||
### Introduction
|
||||
|
||||
Stream Chat supports attachment types like images, video and files by default. You can also add your
|
||||
own types of attachments through the SDK such as location, audio, etc.
|
||||
|
||||
This involves doing three things:
|
||||
|
||||
1) Rendering the attachment thumbnail in the `MessageInput`
|
||||
|
||||
2) Sending a message with the custom attachment
|
||||
|
||||
3) Rendering the custom message attachment
|
||||
|
||||
To do this, let's check out an example to add location sharing to Stream Chat.
|
||||
|
||||
### Location Sharing
|
||||
|
||||
Let's build an example of location sharing option in the app:
|
||||
|
||||

|
||||
|
||||
* Show a "Share Location" button next to MessageInput Textfield.
|
||||
|
||||
* When the user presses this button, it should fetch the current location coordinates of the user, and send a message on the channel as follows:
|
||||
|
||||
```dart
|
||||
Message(
|
||||
text: 'This is my location',
|
||||
attachments: [
|
||||
Attachment(
|
||||
uploadState: UploadState.success(),
|
||||
type: 'location',
|
||||
extraData: {
|
||||
'latitude': 'fetched_latitude',
|
||||
'longitude': 'fetched_longitude',
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
```
|
||||
|
||||
For our example, we are going to use [geolocator](https://pub.dev/packages/geolocator) library.
|
||||
Please check their [setup instructions](https://pub.dev/packages/geolocator) on their docs.
|
||||
|
||||
NOTE: If you are testing on iOS simulator, you will need to set some dummy coordinates, as mentioned [here](https://stackoverflow.com/a/31238119/7489541).
|
||||
Also don't forget to enable "location update" capability in background mode, from XCode.
|
||||
|
||||
On the receiver end, `location` type attachment should be rendered in map view, in the `MessageListView`.
|
||||
We are going to use [Google Static Maps API](https://developers.google.com/maps/documentation/maps-static/overview) to render the map in the message.
|
||||
You can use other libraries as well such as [google_maps_flutter](https://pub.dev/packages/google_maps_flutter).
|
||||
|
||||
First, we add a button which when clicked fetches and shares location into the `MessageInput`:
|
||||
|
||||
```dart
|
||||
MessageInput(
|
||||
actions: [
|
||||
InkWell(
|
||||
child: Icon(
|
||||
Icons.location_on,
|
||||
size: 20.0,
|
||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||
),
|
||||
onTap: () {
|
||||
var channel = StreamChannel.of(context).channel;
|
||||
var user = StreamChat.of(context).user;
|
||||
|
||||
_determinePosition().then((value) {
|
||||
channel.sendMessage(
|
||||
Message(
|
||||
text: 'This is my location',
|
||||
attachments: [
|
||||
Attachment(
|
||||
uploadState: UploadState.success(),
|
||||
type: 'location',
|
||||
extraData: {
|
||||
'latitude': value.latitude.toString(),
|
||||
'longitude': value.longitude.toString(),
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}).catchError((err) {
|
||||
print('Error getting location!');
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Future<Position> _determinePosition() async {
|
||||
bool serviceEnabled;
|
||||
LocationPermission permission;
|
||||
|
||||
serviceEnabled = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceEnabled) {
|
||||
return Future.error('Location services are disabled.');
|
||||
}
|
||||
|
||||
permission = await Geolocator.checkPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.deniedForever) {
|
||||
return Future.error(
|
||||
'Location permissions are permanently denied, we cannot request permissions.');
|
||||
}
|
||||
|
||||
if (permission == LocationPermission.denied) {
|
||||
return Future.error(
|
||||
'Location permissions are denied');
|
||||
}
|
||||
}
|
||||
|
||||
return await Geolocator.getCurrentPosition();
|
||||
}
|
||||
```
|
||||
|
||||
Next, we build the Static Maps URL (Add your API key before using the code snippet):
|
||||
|
||||
```dart
|
||||
String _buildMapAttachment(String lat, String long) {
|
||||
var baseURL = 'https://maps.googleapis.com/maps/api/staticmap?';
|
||||
var url = Uri(
|
||||
scheme: 'https',
|
||||
host: 'maps.googleapis.com',
|
||||
port: 443,
|
||||
path: '/maps/api/staticmap',
|
||||
queryParameters: {
|
||||
'center': '${lat},${long}',
|
||||
'zoom': '15',
|
||||
'size': '600x300',
|
||||
'maptype': 'roadmap',
|
||||
'key': 'YOUR_API_KEY',
|
||||
'markers': 'color:red|${lat},${long}'
|
||||
});
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
```
|
||||
|
||||
And then modify the MessageListView and tell it how to build a location attachment:
|
||||
|
||||
```dart
|
||||
MessageListView(
|
||||
customAttachmentBuilders: {
|
||||
'location': (context, message, attachments) {
|
||||
var attachmentWidget = Image.network(
|
||||
_buildMapAttachment(
|
||||
attachments[0].extraData['latitude'],
|
||||
attachments[0].extraData['longitude'],
|
||||
),
|
||||
);
|
||||
|
||||
return wrapAttachmentWidget(context, attachmentWidget, null, true, BorderRadius.circular(8.0));
|
||||
}
|
||||
},
|
||||
),
|
||||
```
|
||||
|
||||
This gives us the final location attachment:
|
||||
|
||||

|
||||
|
||||
Additionally, you can also add a thumbnail if a message has a location attachment (unlike in this case, where we sent the message directly).
|
||||
|
||||
To do this, we will:
|
||||
|
||||
1) Add an attachment instead of sending a message
|
||||
|
||||
2) Customize the `MessageInput`
|
||||
|
||||
First, we add the attachment when the location button is clicked:
|
||||
|
||||
```dart
|
||||
GlobalKey<MessageInputState> _messageInputKey = GlobalKey();
|
||||
|
||||
MessageInput(
|
||||
key: _messageInputKey,
|
||||
actions: [
|
||||
InkWell(
|
||||
child: Icon(
|
||||
Icons.location_on,
|
||||
size: 20.0,
|
||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||
),
|
||||
onTap: () {
|
||||
_determinePosition().then((value) {
|
||||
_messageInputKey.currentState.addAttachment(
|
||||
Attachment(
|
||||
uploadState: UploadState.success(),
|
||||
type: 'location',
|
||||
extraData: {
|
||||
'latitude': value.latitude.toString(),
|
||||
'longitude': value.longitude.toString(),
|
||||
},
|
||||
),
|
||||
);
|
||||
}).catchError((err) {
|
||||
print('Error getting location!');
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
```
|
||||
|
||||
After this, we can build the thumbnail:
|
||||
|
||||
```dart
|
||||
MessageInput(
|
||||
key: _messageInputKey,
|
||||
actions: [
|
||||
InkWell(
|
||||
child: Icon(
|
||||
Icons.location_on,
|
||||
size: 20.0,
|
||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||
),
|
||||
onTap: () {
|
||||
_determinePosition().then((value) {
|
||||
_messageInputKey.currentState.addAttachment(
|
||||
Attachment(
|
||||
uploadState: UploadState.success(),
|
||||
type: 'location',
|
||||
extraData: {
|
||||
'latitude': value.latitude.toString(),
|
||||
'longitude': value.longitude.toString(),
|
||||
},
|
||||
),
|
||||
);
|
||||
}).catchError((err) {
|
||||
print('Error getting location!');
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
attachmentThumbnailBuilders: {
|
||||
'location': (context, attachment) {
|
||||
return Image.network(
|
||||
_buildMapAttachment(
|
||||
attachment.extraData['latitude'],
|
||||
attachment.extraData['longitude'],
|
||||
),
|
||||
);
|
||||
},
|
||||
},
|
||||
),
|
||||
```
|
||||
|
||||
And we can see the thumbnails in the MessageInput:
|
||||
|
||||

|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
id: local_data_persistence
|
||||
sidebar_position: 2
|
||||
title: Adding Local Data Persistence
|
||||
---
|
||||
|
||||
@@ -0,0 +1,234 @@
|
||||
---
|
||||
id: adding_push_notifications
|
||||
sidebar_position: 3
|
||||
title: Adding Push Notifications
|
||||
---
|
||||
|
||||
Adding Push Notifications To Your Application
|
||||
|
||||
### Introduction
|
||||
|
||||
Push notifications are a core part of the experience for a messaging app. Users often need to be notified
|
||||
of new messages and old notifications sometimes need to be updated silently as well.
|
||||
|
||||
This guide details how to add push notifications to your app.
|
||||
|
||||
Make sure to check [this section](https://getstream.io/chat/docs/flutter-dart/push_introduction/?language=dart) of the docs to read about the push delivery logic.
|
||||
|
||||
### Setup FCM
|
||||
|
||||
To integrate push notifications in your Flutter app you need to use the package [firebase_messaging](https://pub.dev/packages/firebase_messaging).
|
||||
|
||||
|
||||
Follow the [Firebase documentation](https://firebase.flutter.dev/docs/messaging/overview/) to know how to set up the plugin for both Android and iOS.
|
||||
|
||||
|
||||
Once that's done FCM should be able to send push notifications to your devices.
|
||||
|
||||
### Integration with Stream
|
||||
|
||||
#### Step 1
|
||||
|
||||
From the [Firebase Console](https://console.firebase.google.com/), select the project your app belongs to.
|
||||
|
||||
#### Step 2
|
||||
|
||||
Click on the gear icon next to `Project Overview` and navigate to **Project settings**
|
||||
|
||||

|
||||
|
||||
#### Step 3
|
||||
|
||||
Navigate to the `Cloud Messaging` tab
|
||||
|
||||
#### Step 4
|
||||
|
||||
Under `Project Credentials`, locate the `Server key` and copy it
|
||||
|
||||

|
||||
|
||||
#### Step 5
|
||||
|
||||
Upload the `Server Key` in your chat dashboard
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
|
||||
:::note
|
||||
We are setting up the Android section, but this will work for both Android and iOS if you're using Firebase for both of them!
|
||||
:::
|
||||
|
||||
#### Step 6
|
||||
|
||||
Save your push notification settings changes
|
||||
|
||||

|
||||
|
||||
**OR**
|
||||
|
||||
Upload the `Server Key` via API call using a backend SDK
|
||||
|
||||
```js
|
||||
await client.updateAppSettings({
|
||||
firebase_config: {
|
||||
server_key: 'server_key',
|
||||
notification_template: `{"message":{"notification":{"title":"New messages","body":"You have {{ unread_count }} new message(s) from {{ sender.name }}"},"android":{"ttl":"86400s","notification":{"click_action":"OPEN_ACTIVITY_1"}}}}`,
|
||||
data_template: `{"sender":"{{ sender.id }}","channel":{"type": "{{ channel.type }}","id":"{{ channel.id }}"},"message":"{{ message.id }}"}`
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
### Registering a device at Stream Backend
|
||||
|
||||
Once you configure Firebase server key and set it up on Stream dashboard a device that is supposed to receive push notifications needs to be registered at Stream backend. This is usually done by listening for Firebase device token updates and passing them to the backend as follows:
|
||||
|
||||
```dart
|
||||
firebaseMessaging.onTokenRefresh.listen((token) {
|
||||
client.addDevice(token, PushProvider.firebase);
|
||||
});
|
||||
```
|
||||
|
||||
### Possible issues
|
||||
|
||||
|
||||
We only send push notifications when the user doesn't have any active websocket connection (which is established when you call `client.connectUser`). If you set the [onBackgroundEventReceived](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/StreamChat/onBackgroundEventReceived.html) property of the StreamChat widget, when your app goes to background, your device will keep the ws connection alive for 1 minute, and so within this period, you won't receive any push notification.
|
||||
|
||||
Make sure to read the [general push docs](https://getstream.io/chat/docs/flutter-dart/push_introduction/?language=dart) in order to avoid known gotchas that may make your relationship with notifications go bad 😢
|
||||
|
||||
### Testing if Push Notifications are Setup Correctly
|
||||
|
||||
If you're not sure if you've set up push notifications correctly (e.g. you don't always receive them, they work unreliably), you can follow these steps to make sure your config is correct and working:
|
||||
|
||||
1. Clone our repo for push testing git clone git@github.com:GetStream/chat-push-test.git
|
||||
|
||||
2. `cd flutter`
|
||||
|
||||
3. In folder run `flutter pub get`
|
||||
|
||||
4. Input your api key and secret in `lib/main.dart`
|
||||
|
||||
5. Change the bundle identifier/application ID and development team/user so you can run the app in your device (**do not** run on iOS simulator, Android emulator is fine)
|
||||
|
||||
6. Add your `google-services.json/GoogleService-Info.plist`
|
||||
|
||||
7. Run the app
|
||||
|
||||
8. Accept push notification permission (iOS only)
|
||||
|
||||
9. Tap on `Device ID` and copy it
|
||||
|
||||
10. Send the app to background
|
||||
|
||||
11. After configuring [stream-cli](https://github.com/GetStream/stream-cli) paste the following command on command line using your user ID
|
||||
|
||||
```shell
|
||||
stream chat:push:test -u <USER-ID>
|
||||
```
|
||||
|
||||
You should get a test push notification
|
||||
|
||||
### App in the background but still connected
|
||||
|
||||
The [StreamChat](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/StreamChat-class.html) widget lets you define a [onBackgroundEventReceived](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/StreamChat/onBackgroundEventReceived.html) handler in order to handle events while the app is in the background, but the client is still connected.
|
||||
|
||||
This is useful because it lets you keep the connection alive in cases in which the app goes in the background just for some seconds (eg: multitasking, picking pictures from the gallery...)
|
||||
|
||||
You can even customize the [backgroundKeepAlive](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/StreamChat/backgroundKeepAlive.html) duration.
|
||||
|
||||
In order to show notifications in such a case we suggest using the package [flutter_local_notifications](https://pub.dev/packages/flutter_local_notifications); follow the package guide to successfully set up the plugin.
|
||||
|
||||
Once that's done you should set the [onBackgroundEventReceived](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/StreamChat/onBackgroundEventReceived.html); here is an example:
|
||||
|
||||
```dart
|
||||
...
|
||||
StreamChat(
|
||||
client: client,
|
||||
onBackgroundEventReceived: (e) {
|
||||
final currentUserId = client.state.user.id;
|
||||
if (![
|
||||
EventType.messageNew,
|
||||
EventType.notificationMessageNew,
|
||||
].contains(event.type) ||
|
||||
event.user.id == currentUserId) {
|
||||
return;
|
||||
}
|
||||
if (event.message == null) return;
|
||||
final flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
|
||||
final initializationSettingsAndroid =
|
||||
AndroidInitializationSettings('launch_background');
|
||||
final initializationSettingsIOS = IOSInitializationSettings();
|
||||
final initializationSettings = InitializationSettings(
|
||||
android: initializationSettingsAndroid,
|
||||
iOS: initializationSettingsIOS,
|
||||
);
|
||||
await flutterLocalNotificationsPlugin.initialize(initializationSettings);
|
||||
await flutterLocalNotificationsPlugin.show(
|
||||
event.message.id.hashCode,
|
||||
event.message.user.name,
|
||||
event.message.text,
|
||||
NotificationDetails(
|
||||
android: AndroidNotificationDetails(
|
||||
'message channel',
|
||||
'Message channel',
|
||||
'Channel used for showing messages',
|
||||
priority: Priority.high,
|
||||
importance: Importance.high,
|
||||
),
|
||||
iOS: IOSNotificationDetails(),
|
||||
),
|
||||
);
|
||||
},
|
||||
child: ....
|
||||
);
|
||||
...
|
||||
```
|
||||
|
||||
As you can see we generate a local notification whenever a message.new or notification.message_new event is received.
|
||||
|
||||
:::note
|
||||
Using `flutter_local_notifications` is a great way to implement notifications while the is in foreground too! You can generate a local notification listening to events using the method `streamChatClient.on()` and react to the events you want.
|
||||
:::
|
||||
|
||||
### Saving notification messages to the offline storage
|
||||
|
||||
You may want to save received messages when you receive them via a notification so that later on when you open the app they're already there.
|
||||
|
||||
To do this we need to update the push notification data payload at Stream Dashboard and clear the notification one:
|
||||
|
||||
```json
|
||||
{
|
||||
"message_id": "{{ message.id }}",
|
||||
"channel_id": "{{ channel.id }}",
|
||||
"channel_type": "{{ channel.type }}"
|
||||
}
|
||||
```
|
||||
|
||||
Then we need to integrate the package [stream_chat_persistence](https://pub.dev/packages/stream_chat_persistence) in our app that exports a persistence client, learn [here](https://pub.dev/packages/stream_chat_persistence#usage) how to set it up.
|
||||
|
||||
Then during the call `firebaseMessaging.configure(...)` we need to set the `onBackgroundMessage` parameter using a TOP-LEVEL or STATIC function to handle background messages; here is an example:
|
||||
|
||||
```dart
|
||||
Future<dynamic> myBackgroundMessageHandler(message) async {
|
||||
if (message.containsKey('data')) {
|
||||
final data = message['data'];
|
||||
final messageId = data['message_id'];
|
||||
final channelId = data['channel_id'];
|
||||
final channelType = data['channel_type'];
|
||||
final cid = '$channelType:$channelId';
|
||||
|
||||
final client = StreamChatClient(apiKey);
|
||||
final persistenceClient = StreamChatPersistenceClient();
|
||||
await persistenceClient.connect(userId);
|
||||
|
||||
final message = await client.getMessage(messageId).then((res) => res.message);
|
||||
|
||||
await persistenceClient.updateMessages(cid, [message]);
|
||||
persistenceClient.disconnect();
|
||||
|
||||
/// This can be done using the package flutter_local_notifications as we did before 👆
|
||||
_showLocalNotification();
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
id: introduction
|
||||
sidebar_position: 1
|
||||
title: Introduction
|
||||
---
|
||||
@@ -0,0 +1,298 @@
|
||||
---
|
||||
id: mig_guide_2_0
|
||||
sidebar_position: 5
|
||||
title: Migrating to 2.0 (Null-safety)
|
||||
---
|
||||
|
||||
A Migration Guide For Switching To v2.0 Of The Flutter SDK
|
||||
|
||||
### Overview
|
||||
|
||||
v2.0 of the Stream Chat Flutter SDK brings along several changes - primarily making the SDK null-safe.
|
||||
Null safety allows your apps to run faster, with fewer errors, and with less code.
|
||||
|
||||
Check [this link](https://flutter.dev/docs/null-safety) for more about Null Safety in Flutter.
|
||||
|
||||
This guide is intended to enumerate and better explain the changes in the SDK.
|
||||
|
||||
The changes will be listed by package and a concise changelog will follow with more info.
|
||||
|
||||
### Changelog of `stream_chat_flutter`
|
||||
|
||||
#### 🛑️ Breaking Changes from 1.5.4
|
||||
|
||||
* Migrate this package to null safety
|
||||
|
||||
* Renamed `ChannelImage` to `ChannelAvatar`
|
||||
|
||||
* Updated `StreamChatThemeData.reactionIcons` to accept custom builder
|
||||
|
||||
* Renamed `ColorTheme` properties to reflect the purpose of the colors
|
||||
|
||||
* `ColorTheme.black` -> `ColorTheme.textHighEmphasis`
|
||||
* `ColorTheme.grey` -> `ColorTheme.textLowEmphasis`
|
||||
* `ColorTheme.greyGainsboro` -> `ColorTheme.disabled`
|
||||
* `ColorTheme.greyWhisper` -> `ColorTheme.borders`
|
||||
* `ColorTheme.whiteSmoke` -> `ColorTheme.inputBg`
|
||||
* `ColorTheme.whiteSnow` -> `ColorTheme.appBg`
|
||||
* `ColorTheme.white` -> `ColorTheme.barsBg`
|
||||
* `ColorTheme.blueAlice` -> `ColorTheme.linkBg`
|
||||
* `ColorTheme.accentBlue` -> `ColorTheme.accentPrimary`
|
||||
* `ColorTheme.accentRed` -> `ColorTheme.accentError`
|
||||
* `ColorTheme.accentGreen` -> `ColorTheme.accentInfo`
|
||||
|
||||
* `ChannelListCore` options property is removed in favor of individual properties
|
||||
|
||||
* `options.state` -> `bool state`
|
||||
* `options.watch` -> `bool watch`
|
||||
* `options.presence` -> `bool presence`
|
||||
|
||||
* `UserListView` options property is removed in favor of individual properties
|
||||
|
||||
* `options.presence` -> `bool presence`
|
||||
|
||||
* Renamed `ImageHeader` to `GalleryHeader`
|
||||
|
||||
* Renamed `ImageFooter` to `GalleryFooter`
|
||||
|
||||
* `MessageBuilder` and `ParentMessageBuilder` signature is now
|
||||
|
||||
```
|
||||
typedef MessageBuilder = Widget Function(
|
||||
BuildContext,
|
||||
MessageDetails,
|
||||
List<Message>,
|
||||
MessageWidget defaultMessageWidget,
|
||||
);
|
||||
```
|
||||
|
||||
The last parameter is the default `MessageWidget`
|
||||
You can call `.copyWith` to customize just a subset of properties
|
||||
|
||||
#### ✅ Added
|
||||
|
||||
Added video compress options (frame and quality) to MessageInput
|
||||
`TypingIndicator` now has a property called `parentId` to show typing indicator specific to threads
|
||||
#493: add support for `MessageListView` header/footer
|
||||
`MessageWidget` accepts a `userAvatarBuilder`
|
||||
Added `pinMessage` ui support
|
||||
Added `MessageListView.threadSeparatorBuilder` property
|
||||
Added `MessageInput.onError` property to allow error handling
|
||||
Added `GalleryHeader`/`GalleryFooter` theme classes
|
||||
|
||||
#### 🐞 Fixed
|
||||
|
||||
#483: Keyboard covers input text box when editing message
|
||||
`Modals` are shown using the nearest `Navigator` to make using the SDK easier in a nested navigator use case
|
||||
#484: messages don't update without a reload
|
||||
`MessageListView` not rendering if the user is not a member of the channel
|
||||
Fix `MessageInput` overflow when there are no actions
|
||||
Minor fixes and improvements
|
||||
|
||||
### Migrating to 2.0 for `stream_chat_flutter`
|
||||
|
||||
:::note
|
||||
If you are migrating your full Flutter project to null-safety, first make sure you follow the
|
||||
instructions from the [official Null Safety migration guide](https://dart.dev/null-safety/migration-guide).
|
||||
:::
|
||||
|
||||
To migrate to v2.0 for `stream_chat_flutter`, first change the version of the package to the latest
|
||||
null-safe version.
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
stream_chat_flutter: ^2.0.0
|
||||
```
|
||||
|
||||
Upon doing this, all breaking changes from the package will take immediate effect. Here are steps to
|
||||
remedy the issues:
|
||||
|
||||
1) Replace the offending class names with the revised class names
|
||||
|
||||
* `ChannelImage` -> `ChannelAvatar`
|
||||
* `ImageHeader` -> `GalleryHeader`
|
||||
* `ImageFooter` -> `GalleryFooter`
|
||||
|
||||
2) The new version comes with revised color names since the previous names do not suit light/dark mode
|
||||
nomenclature. Make sure any old colors used from theme are changed over to the new theme color names:
|
||||
|
||||
* `ColorTheme.black` -> `ColorTheme.textHighEmphasis`
|
||||
* `ColorTheme.grey` -> `ColorTheme.textLowEmphasis`
|
||||
* `ColorTheme.greyGainsboro` -> `ColorTheme.disabled`
|
||||
* `ColorTheme.greyWhisper` -> `ColorTheme.borders`
|
||||
* `ColorTheme.whiteSmoke` -> `ColorTheme.inputBg`
|
||||
* `ColorTheme.whiteSnow` -> `ColorTheme.appBg`
|
||||
* `ColorTheme.white` -> `ColorTheme.barsBg`
|
||||
* `ColorTheme.blueAlice` -> `ColorTheme.linkBg`
|
||||
* `ColorTheme.accentBlue` -> `ColorTheme.accentPrimary`
|
||||
* `ColorTheme.accentRed` -> `ColorTheme.accentError`
|
||||
* `ColorTheme.accentGreen` -> `ColorTheme.accentInfo`
|
||||
|
||||
3) We decided to make messages easier to customize and now supply the default implementation of the
|
||||
messages in the builder - so you can now customize a single parameter without having to redo the
|
||||
entire implementation. Please reform your builders to take into account the new format:
|
||||
|
||||
```
|
||||
typedef MessageBuilder = Widget Function(
|
||||
BuildContext,
|
||||
MessageDetails,
|
||||
List<Message>,
|
||||
MessageWidget defaultMessageWidget,
|
||||
);
|
||||
```
|
||||
|
||||
To tweak any of the default properties individually, you can use `defaultMessageWidget.copyWith()`.
|
||||
|
||||
### Changelog of `stream_chat_flutter_core`
|
||||
|
||||
#### 🛑️ Breaking Changes from 1.5.3
|
||||
|
||||
* Migrate this package to null safety
|
||||
* `channelsBloc.queryChannels()`, `ChannelListCore` options param/property is removed in favor of individual params/properties
|
||||
* `options.state` -> `bool state`
|
||||
* `options.watch` -> `bool watch`
|
||||
* `options.presence` -> `bool presence`
|
||||
* `usersBloc.queryUsers()`, `UserListCore` options param/property is removed in favor of individual params/properties
|
||||
* `options.presence` -> `bool presence`
|
||||
|
||||
#### ✅ Added
|
||||
|
||||
* Monitor connection using `connectivity_plus` package
|
||||
|
||||
#### 🐞 Fixed
|
||||
|
||||
* Minor fixes
|
||||
* Performance improvements
|
||||
|
||||
### Migrating to 2.0 for `stream_chat_flutter_core`
|
||||
|
||||
:::note
|
||||
If you are migrating your full Flutter project to null-safety, first make sure you follow the
|
||||
instructions from the [official Null Safety migration guide](https://dart.dev/null-safety/migration-guide).
|
||||
:::
|
||||
|
||||
To migrate to v2.0 for `stream_chat_flutter_core`, first change the version of the package to the latest
|
||||
null-safe version.
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
stream_chat_flutter_core: ^2.0.0
|
||||
```
|
||||
|
||||
Upon doing this, all breaking changes from the package will take immediate effect. Here are steps to
|
||||
remedy the issue:
|
||||
|
||||
:::note
|
||||
The major changes in `stream_chat_flutter_core` consist of changing over from a map full of options
|
||||
to a more type safe and sound approach by changing over to explicit parameters.
|
||||
:::
|
||||
|
||||
1) Change over Core widget implementations by using the explicit parameters instead of the options map.
|
||||
Use these explicit parameters in the widget constructor instead of the option keys:
|
||||
|
||||
* `options.state` -> `bool state`
|
||||
* `options.watch` -> `bool watch`
|
||||
* `options.presence` -> `bool presence`
|
||||
|
||||
2) Change over query calls in the BLoCs in the same way (change from options map to explicit parameters
|
||||
in the constructor)
|
||||
|
||||
### Changelog of `stream_chat`
|
||||
|
||||
#### 🛑️ Breaking Changes from 1.5.3
|
||||
|
||||
* Migrate this package to null safety
|
||||
* `ConnectUserWithProvider` now requires `tokenProvider` as a required param. (Removed from the constructor)
|
||||
* `client.disconnect()` is now divided into two different functions
|
||||
* `client.closeConnection()` -> for closing user websocket connection.
|
||||
* `client.disconnectUser()` -> for disconnecting user and resetting client state.
|
||||
* `client.devToken()` now returns a Token model instead of String.
|
||||
* `ApiError` is removed in favor of `StreamChatError`
|
||||
* `StreamChatError` -> parent type for all the stream errors.
|
||||
* `StreamWebSocketError` -> for user websocket related errors.
|
||||
* `StreamChatNetworkError` -> for network related errors.
|
||||
* `client.queryChannels()`, `channel.query()` options param is removed in favor of individual params
|
||||
* `option.state` -> `bool state`
|
||||
* `option.watch` -> `bool watch`
|
||||
* `option.presence` -> `bool presence`
|
||||
* `client.queryUsers()` options param is removed in favor of individual params
|
||||
* `option.presence` -> `bool presence`
|
||||
* Added typed filters
|
||||
|
||||
#### 🐞 Fixed
|
||||
|
||||
* #369: Client does not return without internet connection
|
||||
* Several minor fixes
|
||||
* Performance improvements
|
||||
|
||||
#### ✅ Added
|
||||
|
||||
* New Location enum is introduced for easily changing the client location/baseUrl.
|
||||
* New `client.openConnection()` and `client.closeConnection()` is introduced to connect/disconnect user ws connection.
|
||||
* New `client.partialUpdateMessage` and `channel.partialUpdateMessage` methods
|
||||
* `connectWebSocket` parameter in connect user calls to use the client in "connection-less" mode.
|
||||
|
||||
#### 🔄 Changed
|
||||
|
||||
* `baseURL` is now deprecated in favor of using Location to change data location.
|
||||
|
||||
### Migrating to 2.0 for `stream_chat`
|
||||
|
||||
If you are migrating your full Flutter project to null-safety, first make sure you follow the
|
||||
instructions from the [official Null Safety migration guide](https://dart.dev/null-safety/migration-guide).
|
||||
:::
|
||||
|
||||
To migrate to v2.0 for `stream_chat`, first change the version of the package to the latest
|
||||
null-safe version.
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
stream_chat: ^2.0.0
|
||||
```
|
||||
|
||||
Upon doing this, all breaking changes from the package will take immediate effect. Here are steps to
|
||||
remedy the issues:
|
||||
|
||||
1) Change over the constructor of `connectUserWithProvider()` to the new format which has `tokenProvider` as a required param.
|
||||
|
||||
2) We added more nuance to `disconnectUser()` by adding two new methods - one to close the connection
|
||||
and the other to disconnect the user. This allows more fine-grained control of disconnection.
|
||||
|
||||
* `client.closeConnection()` -> for closing user websocket connection.
|
||||
* `client.disconnectUser()` -> for disconnecting user and resetting client state.
|
||||
|
||||
3) We refactored how we handle errors - new error types are now introduced that replace ApiError.
|
||||
|
||||
* `StreamChatError` -> parent type for all the stream errors.
|
||||
* `StreamWebSocketError` -> for user websocket related errors.
|
||||
* `StreamChatNetworkError` -> for network related errors.
|
||||
|
||||
4) We changed over from a map full of options to a more type-safe and sound approach by changing over to explicit parameters.
|
||||
|
||||
Use these explicit parameters in the query parameters instead of the option keys:
|
||||
|
||||
* `client.queryChannels()`, `channel.query()` options param is removed in favor of individual params
|
||||
* `option.state` -> `bool state`
|
||||
* `option.watch` -> `bool watch`
|
||||
* `option.presence` -> `bool presence`
|
||||
* `client.queryUsers()` options param is removed in favor of individual params
|
||||
* `option.presence` -> `bool presence`
|
||||
|
||||
5) We added type-safe filters to make filtering in the app easier. Change over the filters to the
|
||||
new implementation.
|
||||
|
||||
As an example, in the old app this filter:
|
||||
|
||||
```dart
|
||||
filter: {
|
||||
'members': {
|
||||
'\$in': [StreamChat.of(context).user.id],
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
Would turn into:
|
||||
|
||||
```dart
|
||||
filter: Filter.in_('members', [StreamChat.of(context).user.id])
|
||||
```
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Stream Chat Flutter",
|
||||
"position": 3
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
---
|
||||
id: channel_header
|
||||
sidebar_position: 10
|
||||
title: ChannelHeader
|
||||
---
|
||||
|
||||
A Widget To Display Common Channel Details
|
||||
|
||||
Find the pub.dev documentation [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/ChannelHeader-class.html)
|
||||
|
||||

|
||||
|
||||
### Background
|
||||
|
||||
When a user opens a channel, it is helpful to provide context of which channel they are in. This may
|
||||
be in the form of a channel name or the users in the channel. Along with that, there also needs to be
|
||||
a way for the user to look at more details of the channel (media, pinned messages, actions, etc.) and
|
||||
preferably also a way to navigate back to where they came from.
|
||||
|
||||
To encapsulate all of this functionality into one widget, the Flutter SDK contains a `ChannelHeader`
|
||||
widget which provides these out of the box.
|
||||
|
||||
### Basic Example
|
||||
|
||||
Let's just add a `ChannelHeader` to a page with a `MessageListView` and a `MessageInput` to display
|
||||
and send messages.
|
||||
|
||||
```dart
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: ChannelHeader(),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: MessageListView(
|
||||
threadBuilder: (_, parentMessage) {
|
||||
return ThreadPage(
|
||||
parent: parentMessage,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
MessageInput(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Customizing Parts Of The Header
|
||||
|
||||
The header works like a `ListTile` widget.
|
||||
|
||||
Use the `title`, `subtitle`, `leading`, or `actions` parameters to substitute the widgets for your own.
|
||||
|
||||
```dart
|
||||
//...
|
||||
ChannelHeader(
|
||||
title: Text('My Custom Name'),
|
||||
),
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Showing Connection State
|
||||
|
||||
The `ChannelHeader` can also display connection state below the tile which shows the user if they
|
||||
are connected or offline, etc. on connection events.
|
||||
|
||||
To enable this, use the `showConnectionStateTile` property.
|
||||
|
||||
```dart
|
||||
//...
|
||||
ChannelHeader(
|
||||
showConnectionStateTile: true,
|
||||
),
|
||||
```
|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
id: channel_list_header
|
||||
sidebar_position: 9
|
||||
title: ChannelListHeader
|
||||
---
|
||||
|
||||
A Header Widget For A List Of Channels
|
||||
|
||||
Find the pub.dev documentation [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/ChannelListHeader-class.html)
|
||||
|
||||

|
||||
|
||||
### Background
|
||||
|
||||
A common pattern for most messaging apps is to show a list of Channels (chats) on the first screen
|
||||
and navigate to an individual one on being clicked. On this first page where the list of channels are
|
||||
displayed, it is usual to have functionality such as adding a new chat, display the user logged in, etc.
|
||||
|
||||
To encapsulate all of this functionality into one widget, the Flutter SDK contains a `ChannelListHeader`
|
||||
widget which provides these out of the box.
|
||||
|
||||
### Basic Example
|
||||
|
||||
This is a basic example of a page which has a `ChannelListView` and a `ChannelListHeader` to recreate a
|
||||
common Channels Page.
|
||||
|
||||
```dart
|
||||
class DemoPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: ChannelListHeader(),
|
||||
body: ChannelsBloc(
|
||||
child: ChannelListView(
|
||||
filter: Filter.in_('members', [StreamChat.of(context).user.id]),
|
||||
sort: [SortOption('last_message_at')],
|
||||
pagination: PaginationParams(
|
||||
limit: 20,
|
||||
),
|
||||
channelWidget: ChannelPage(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Customizing Parts Of The Header
|
||||
|
||||
The header works like a `ListTile` widget.
|
||||
|
||||
Use the `titleBuilder`, `subtitle`, `leading`, or `actions` parameters to substitute the widgets for your own.
|
||||
|
||||
```dart
|
||||
//...
|
||||
ChannelListHeader(
|
||||
subtitle: Text('My Custom Subtitle'),
|
||||
),
|
||||
```
|
||||
|
||||

|
||||
|
||||
The `titleBuilder` param helps you build different titles depending on the connection state:
|
||||
|
||||
```dart
|
||||
//...
|
||||
ChannelListHeader(
|
||||
titleBuilder: (context, status, client) {
|
||||
switch(status) {
|
||||
/// Return your title widget
|
||||
}
|
||||
},
|
||||
),
|
||||
```
|
||||
|
||||
### Showing Connection State
|
||||
|
||||
The `ChannelListHeader` can also display connection state below the tile which shows the user if they
|
||||
are connected or offline, etc. on connection events.
|
||||
|
||||
To enable this, use the `showConnectionStateTile` property.
|
||||
|
||||
```dart
|
||||
//...
|
||||
ChannelListHeader(
|
||||
showConnectionStateTile: true,
|
||||
),
|
||||
```
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
id: channel_list_view
|
||||
sidebar_position: 4
|
||||
title: ChannelListView
|
||||
---
|
||||
|
||||
A Widget For Displaying A List Of Channels
|
||||
|
||||
Find the pub.dev documentation [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/ChannelListView-class.html)
|
||||
|
||||

|
||||
|
||||
### Background
|
||||
|
||||
Channels are fundamental elements of Stream Chat and constitute shared spaces which allow users to
|
||||
message each other.
|
||||
|
||||
1:1 conversations and groups are both examples of channels, albeit with some (distinct/non-distinct)
|
||||
differences. Displaying the list of channels that a user is a part of is a pattern present in most messaging apps.
|
||||
|
||||
The `ChannelListView` widget allows displaying a list of channels to a user. By default, this is NOT
|
||||
ONLY the channels that the user is a part of. This section goes into setting up and using a `ChannelListView`
|
||||
widget.
|
||||
|
||||
### Basic Example
|
||||
|
||||
Here is a basic example of the `ChannelListView` widget. It consists of the main widget itself, a `Filter`
|
||||
to filter only the channels that the user is a part of, sorting by last message time, pagination params,
|
||||
and the widget to use when a particular channel is clicked.
|
||||
|
||||
```dart
|
||||
class ChannelListPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: ChannelsBloc(
|
||||
child: ChannelListView(
|
||||
filter: Filter.in_('members', [StreamChat.of(context).user.id]),
|
||||
sort: [SortOption('last_message_at')],
|
||||
pagination: PaginationParams(
|
||||
limit: 20,
|
||||
),
|
||||
channelWidget: ChannelPage(),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This example by default displays the channels that a user is a part of. Now let's look at customizing
|
||||
the widget.
|
||||
|
||||
### Customizing the Channel Preview
|
||||
|
||||
A common aspect of the widget needed to be tweaked according to each app is the Channel Preview (the
|
||||
Channel tile in the list). To do this, we use the `channelPreviewBuilder` param like this:
|
||||
|
||||
```dart
|
||||
ChannelListView(
|
||||
...
|
||||
channelPreviewBuilder: (context, channel) {
|
||||
return ListTile(
|
||||
tileColor: Colors.amberAccent,
|
||||
title: Center(
|
||||
child: ChannelName(),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
```
|
||||
|
||||
Which gives you a new Channel preview in the list:
|
||||
|
||||

|
||||
|
||||
### Adding Swipe Actions
|
||||
|
||||
To add actions (such as delete, more info, etc) when Channel preview is swiped left, set the `swipeToAction`
|
||||
parameter to `true`.
|
||||
|
||||
```dart
|
||||
ChannelListView(
|
||||
...
|
||||
swipeToAction: true,
|
||||
),
|
||||
```
|
||||
|
||||
This adds two basic actions - info and delete:
|
||||
|
||||

|
||||
|
||||
To add custom actions of your own, use the `swipeActions` param:
|
||||
|
||||
```dart
|
||||
ChannelListView(
|
||||
...
|
||||
swipeToAction: true,
|
||||
swipeActions: [
|
||||
SwipeAction(
|
||||
color: Colors.blue,
|
||||
iconWidget: Icon(Icons.add),
|
||||
onTap: (channel) {
|
||||
// Things to do on icon tap
|
||||
},
|
||||
),
|
||||
// Other actions here
|
||||
]
|
||||
),
|
||||
```
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
id: introduction
|
||||
sidebar_position: 1
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
Understanding The UI Package Of The Flutter SDK
|
||||
|
||||
### What function does `stream_chat_flutter` serve?
|
||||
|
||||
The UI SDK (`stream_chat_flutter`) contains official Flutter components for Stream Chat, a service for building chat applications.
|
||||
|
||||
While the Stream Chat service provides the backend for messaging and the LLC provides an easy way to
|
||||
use it in your Flutter apps, we wanted to make sure that adding Chat functionality to your app was as quick as possible.
|
||||
|
||||
The UI package is built on top of the low-level client and the core package and allows you to build a
|
||||
full fledged app with either the inbuilt components, modify existing components, or easily add widgets
|
||||
of your own to match your app's style better.
|
||||
@@ -0,0 +1,170 @@
|
||||
---
|
||||
id: message_input
|
||||
sidebar_position: 6
|
||||
title: MessageInput
|
||||
---
|
||||
|
||||
A Widget Dealing With Everything Related To Sending A Message
|
||||
|
||||
Find the pub.dev documentation [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/MessageInput-class.html)
|
||||
|
||||

|
||||
|
||||
### Background
|
||||
|
||||
In Stream Chat, we can send messages in a channel. However, sending a message isn't as simple as adding
|
||||
a `TextField` and logic for sending a message. It involves additional processes like addition of media,
|
||||
quoting a message, adding a custom command like a GIF board, and much more. Moreover, most apps also
|
||||
need to customize the input to match their theme, overall color and structure pattern, etc.
|
||||
|
||||
To do this, we created a `MessageInput` widget which abstracts all expected functionality a modern input
|
||||
needs - and allows you to use it out of the box.
|
||||
|
||||
### Basic Example
|
||||
|
||||
A `StreamChannel` is required above the widget tree in which the `MessageInput` is rendered since the channel is
|
||||
where the messages sent actually go. Let's look at a common example of how we could use the `MessageInput`:
|
||||
|
||||
```dart
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: ChannelHeader(),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: MessageListView(
|
||||
threadBuilder: (_, parentMessage) {
|
||||
return ThreadPage(
|
||||
parent: parentMessage,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
MessageInput(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
It is common to put this widget in the same page of a `MessageListView` as the bottom widget.
|
||||
|
||||
### Quoting A Message
|
||||
|
||||
The quoting functionality allows us to 'reply' to a specific message without creating a thread out of it.
|
||||
It adds the other message as context when sending a message and also displays it above the sent message.
|
||||
|
||||
To quote a message, we provide a `quotedMessage` to the `MessageInput`.
|
||||
|
||||
```dart
|
||||
Message? message;
|
||||
|
||||
// ...
|
||||
MessageInput(
|
||||
quotedMessage: message,
|
||||
),
|
||||
```
|
||||
|
||||
This will add the message given above the message about to be sent.
|
||||
|
||||
While you can implement your own functionality to select which message to reply to, the `MessageListView`
|
||||
widget helps in this case since it has an inbuilt `onMessageSwiped` callback which we can use.
|
||||
|
||||
```dart
|
||||
|
||||
class ChannelPage extends StatefulWidget {
|
||||
@override
|
||||
_ChannelPageState createState() => _ChannelPageState();
|
||||
}
|
||||
|
||||
class _ChannelPageState extends State<ChannelPage> {
|
||||
Message? quotedMessage;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: MessageListView(
|
||||
// ...
|
||||
onMessageSwiped: (message) {
|
||||
setState(() {
|
||||
quotedMessage = message;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
MessageInput(
|
||||
quotedMessage: _quotedMessage,
|
||||
onQuotedMessageCleared: () {
|
||||
setState(() => _quotedMessage = null);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||

|
||||
|
||||
### Adding Custom Actions
|
||||
|
||||
By default, the `MessageInput` has two actions: one for attachments and one for commands like Giphy.
|
||||
To add your own action, we use the `actions` parameter like this:
|
||||
|
||||
```dart
|
||||
MessageInput(
|
||||
actions: [
|
||||
InkWell(
|
||||
child: Icon(
|
||||
Icons.location_on,
|
||||
size: 20.0,
|
||||
color: StreamChatTheme.of(context).colorTheme.grey,
|
||||
),
|
||||
onTap: () {
|
||||
// Do something here
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
```
|
||||
|
||||
This will add on your action to the existing ones.
|
||||
|
||||
### Disable Attachments
|
||||
|
||||
To disable attachments being added to the message, set the `disableAttachments` parameter to true.
|
||||
|
||||
```dart
|
||||
MessageInput(
|
||||
disableAttachments: true,
|
||||
),
|
||||
```
|
||||
|
||||
### Changing Position Of MessageInput Components
|
||||
|
||||
You can also change the position of the TextField, actions and 'send' button relative to each other.
|
||||
|
||||
To do this, use the `actionsLocation` or `sendButtonLocation` parameters which help you decide the location
|
||||
of the buttons in the input.
|
||||
|
||||
For example, if we want the actions on the right and the send button inside the TextField, we can do:
|
||||
|
||||
```dart
|
||||
MessageInput(
|
||||
sendButtonLocation: SendButtonLocation.inside,
|
||||
actionsLocation: ActionsLocation.right,
|
||||
),
|
||||
```
|
||||
|
||||

|
||||
@@ -0,0 +1,115 @@
|
||||
---
|
||||
id: message_list_view
|
||||
sidebar_position: 5
|
||||
title: MessageListView
|
||||
---
|
||||
|
||||
A Widget For Displaying A List Of Messages
|
||||
|
||||
Find the pub.dev documentation [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/MessageListView-class.html)
|
||||
|
||||

|
||||
|
||||
### Background
|
||||
|
||||
Every channel can contain a list of messages sent by users inside it. The `MessageListView` widget
|
||||
displays the list of messages inside a particular channel along with possible attachments and
|
||||
other message attributes (if the message is pinned for example). This sets it apart from the `MessageSearchListView`
|
||||
which may not contain messages only from a single channel and is used to search for messages across
|
||||
many.
|
||||
|
||||
### Basic Example
|
||||
|
||||
The `MessageListView` shows the list of messages of the current channel. It has inbuilt support for
|
||||
common messaging functionality: displaying and editing messages, adding / modifying reactions, support
|
||||
for quoting messages, pinning messages, and more.
|
||||
|
||||
An example of how you can use the MessageListView is:
|
||||
|
||||
```dart
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: ChannelHeader(),
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: MessageListView(
|
||||
threadBuilder: (_, parentMessage) {
|
||||
return ThreadPage(
|
||||
parent: parentMessage,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
MessageInput(),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Enable Threads
|
||||
|
||||
Threads are made of a parent message and replies linked to it. To enable threading, the SDK requires you
|
||||
to supply a `threadBuilder` which will supply the page when the thread is clicked.
|
||||
|
||||
```dart
|
||||
MessageListView(
|
||||
threadBuilder: (_, parentMessage) {
|
||||
return ThreadPage(
|
||||
parent: parentMessage,
|
||||
);
|
||||
},
|
||||
),
|
||||
```
|
||||
|
||||

|
||||
|
||||
The `MessageListView` itself can render the thread by supplying the `parentMessage` parameter.
|
||||
|
||||
```dart
|
||||
MessageListView(
|
||||
parentMessage: parent,
|
||||
),
|
||||
```
|
||||
|
||||
### Building Custom Messages
|
||||
|
||||
You can also supply your own implementation for displaying messages using the `messageBuilder` parameter.
|
||||
|
||||
:::note
|
||||
To customize the existing implementation, look at the `MessageWidget` documentation instead.
|
||||
:::
|
||||
|
||||
```dart
|
||||
MessageListView(
|
||||
messageBuilder: (context, details, messageList, defaultImpl) {
|
||||
// Your implementation of the message here
|
||||
// E.g: return Text(details.message.text ?? '');
|
||||
},
|
||||
),
|
||||
```
|
||||
|
||||
### Enabling Message Pinning
|
||||
|
||||
Message pins save and highlight the message in the `MessageListView`. To enable users to pin the message,
|
||||
make sure the pin permissions are granted for different types of users on the dashboard. After confirming
|
||||
the appropriate users have permissions, add the user types in the `pinPermissions` parameter.
|
||||
|
||||
```dart
|
||||
MessageListView(
|
||||
//...
|
||||
pinPermissions: ['admin', 'userType1', 'userType2'],
|
||||
),
|
||||
```
|
||||
|
||||
This will allow these user types to pin messages through the message actions modal.
|
||||
|
||||

|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
id: message_search_list_view
|
||||
sidebar_position: 8
|
||||
title: MessageSearchListView
|
||||
---
|
||||
|
||||
A Widget To Search For Messages Across Channels
|
||||
|
||||
Find the pub.dev documentation [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/MessageSearchListView-class.html)
|
||||
|
||||

|
||||
|
||||
### Background
|
||||
|
||||
Users in Stream Chat can have several channels and it can get hard to remember which channel has the
|
||||
message they are searching for. As such, there needs to be a way to search for a message across multiple
|
||||
channels. This is where `MessageSearchListView` comes in.
|
||||
|
||||
### Basic Example
|
||||
|
||||
While the MessageListView is tied to a certain `StreamChannel`, a `MessageSearchListView` is not.
|
||||
|
||||
```dart
|
||||
class MessageSearchPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: MessageSearchBloc(
|
||||
child: MessageSearchListView(
|
||||
filters: Filter.in_('members', [StreamChat.of(context).user!.id],),
|
||||
messageQuery: 'your query here',
|
||||
paginationParams: PaginationParams(limit: 20),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Customize The Result Tiles
|
||||
|
||||
You can use your own widget for the result items using the `itemBuilder` parameter.
|
||||
|
||||
```dart
|
||||
MessageSearchListView(
|
||||
// ...
|
||||
itemBuilder: (context, response) {
|
||||
return Text(response.message.text);
|
||||
},
|
||||
),
|
||||
```
|
||||
|
||||
### Show Result Count
|
||||
|
||||
You show the number of results via the `showResultCount` parameter.
|
||||
|
||||
```dart
|
||||
MessageSearchListView(
|
||||
// ...
|
||||
showResultCount: true,
|
||||
),
|
||||
```
|
||||
@@ -0,0 +1,98 @@
|
||||
---
|
||||
id: message_widget
|
||||
sidebar_position: 11
|
||||
title: MessageWidget
|
||||
---
|
||||
|
||||
A Widget For Displaying Messages And Attachments
|
||||
|
||||
Find the pub.dev documentation [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/MessageWidget-class.html)
|
||||
|
||||
### Background
|
||||
|
||||
There are several things that need to be displayed with text in a message in a modern messaging app:
|
||||
attachments, highlights if the message is pinned, user avatars of the sender, etc.
|
||||
|
||||
To encapsulate all of this functionality into one widget, the Flutter SDK contains a `MessageWidget`
|
||||
widget which provides these out of the box.
|
||||
|
||||
### Basic Example (Modifying `MessageWidget` in `MessageListView`)
|
||||
|
||||
Primarily, the `MessageWidget` is used in the `MessageListView`. To customize only a few properties
|
||||
of the `MessageWidget` without supplying all other properties, the `messageBuilder` builder supplies
|
||||
a default implementation of the widget for us to modify.
|
||||
|
||||
```dart
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: MessageListView(
|
||||
messageBuilder: (context, details, messageList, defaultMessageWidget) {
|
||||
return defaultMessageWidget.copyWith(
|
||||
showThreadReplyIndicator: false,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Building A Custom Attachment
|
||||
|
||||
When a custom attachment type (location, audio, etc.) is sent, the MessageWidget also needs to know
|
||||
how to build it. For this purpose, we can use the `customAttachmentBuilders` parameter.
|
||||
|
||||
As an example, if a message has a attachment type 'location', we do:
|
||||
|
||||
```dart
|
||||
MessageWidget(
|
||||
//...
|
||||
customAttachmentBuilders: {
|
||||
'location': (context, message, attachments) {
|
||||
var attachmentWidget = Image.network(
|
||||
_buildMapAttachment(
|
||||
attachments[0].extraData['latitude'],
|
||||
attachments[0].extraData['longitude'],
|
||||
),
|
||||
);
|
||||
|
||||
return wrapAttachmentWidget(context, attachmentWidget, null, true, BorderRadius.circular(8.0));
|
||||
}
|
||||
},
|
||||
)
|
||||
```
|
||||
|
||||
You can also override the builder for existing attachment types like `image` and `video`.
|
||||
|
||||
### Show User Avatar For Messages
|
||||
|
||||
You can decide to show, hide, or remove user avatars of the sender of the message. To do this, set
|
||||
the `showUserAvatar` property like this:
|
||||
|
||||
```dart
|
||||
MessageWidget(
|
||||
//...
|
||||
showUserAvatar = DisplayWidget.show,
|
||||
)
|
||||
```
|
||||
|
||||
### Reverse the message
|
||||
|
||||
In most cases, `MessageWidget` needs to be a different orientation depending upon if the sender is the
|
||||
user or someone else.
|
||||
|
||||
For this, we use the `reverse` parameter to change the orientation of the message:
|
||||
|
||||
```dart
|
||||
MessageWidget(
|
||||
//...
|
||||
reverse = true,
|
||||
)
|
||||
```
|
||||
@@ -0,0 +1,48 @@
|
||||
---
|
||||
id: setup
|
||||
sidebar_position: 2
|
||||
title: Setup
|
||||
---
|
||||
|
||||
Understanding Setup For `stream_chat_flutter`
|
||||
|
||||
### Add pub.dev dependency
|
||||
|
||||
First, you need to add the `stream_chat_flutter` dependency to your `pubspec.yaml`.
|
||||
|
||||
You can either run this command:
|
||||
|
||||
```shell
|
||||
flutter pub add stream_chat_flutter
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
Add this line in the dependencies section of your pubspec.yaml after substituting latest version:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
stream_chat_flutter: ^latest_version
|
||||
```
|
||||
|
||||
You can find the package details on [pub.dev](https://pub.dev/packages/stream_chat_flutter).
|
||||
|
||||
### Details On Platform Support
|
||||
|
||||
`stream_chat_flutter` was originally created for Android and iOS mobile platforms. As Flutter matured,
|
||||
support for additional platforms was added and the package now has experimental support for web and desktop as
|
||||
[detailed here](https://getstream.io/blog/announcing-experimental-multi-platform-support-for-the-stream-flutter-sdk/).
|
||||
|
||||
However, platforms other than mobile may have additional constraints due to not supporting all plugins,
|
||||
which will be addressed by the respective plugin creators over time.
|
||||
|
||||
### Setup: iOS
|
||||
|
||||
The library uses [flutter file picker plugin](https://github.com/miguelpruivo/flutter_file_picker) to pick files from the os.
|
||||
Follow [this wiki](https://github.com/miguelpruivo/flutter_file_picker/wiki/Setup#ios) to fulfill iOS requirements.
|
||||
|
||||
We also use [video_player](https://pub.dev/packages/video_player) to reproduce videos.
|
||||
Follow [this guide](https://pub.dev/packages/video_player#installation) to fulfill the requirements.
|
||||
|
||||
To pick images from the camera, we use the [image_picker](https://pub.dev/packages/image_picker) plugin.
|
||||
Follow [these instructions](https://pub.dev/packages/image_picker#ios) to check the requirements.
|
||||
@@ -0,0 +1,71 @@
|
||||
---
|
||||
id: stream_chat_and_theming
|
||||
sidebar_position: 3
|
||||
title: StreamChat And Theming
|
||||
---
|
||||
|
||||
Understanding How To Customize Widgets Using `StreamChatTheme`
|
||||
|
||||
Find the pub.dev documentation [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/StreamChatTheme-class.html) and [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/StreamChatThemeData-class.html)
|
||||
|
||||
### Background
|
||||
|
||||
Stream's UI SDK makes it easy for developers to add custom styles and attributes to our widgets. Like most Flutter frameworks, Stream exposes a dedicated widget for theming.
|
||||
|
||||
Using `StreamChatTheme`, users can customize most aspects of our UI widgets by setting attributes using `StreamChatThemeData`.
|
||||
|
||||
Similar to the `Theme` and `ThemeData` in Flutter, Stream Chat uses a top level [inherited widget](https://api.flutter.dev/flutter/widgets/InheritedWidget-class.html) to provide theming information throughout your application. This can be optionally set at the top of your application tree or at a localized point in your widget sub-tree.
|
||||
|
||||
If you'd like to customize the look and feel of Stream chat across your entire application, we recommend setting your theme at the top level. Conversely, users can customize specific screens or widgets by wrapping components in a `StreamChatTheme`.
|
||||
|
||||
### A closer look at StreamChatThemeData
|
||||
|
||||
Looking at the constructor for `StreamChatThemeData`, we can see the full list of properties and widgets available for customization.
|
||||
|
||||
Some high-level properties such as `textTheme` or `colorTheme` can be set application-wide directly from this class. In contrast, larger components such as `ChannelHeader`, `MessageInputs`, etc. have been broken up into smaller theme objects.
|
||||
|
||||
```dart
|
||||
factory StreamChatThemeData({
|
||||
Brightness? brightness,
|
||||
TextTheme? textTheme,
|
||||
ColorTheme? colorTheme,
|
||||
ChannelListHeaderTheme? channelListHeaderTheme,
|
||||
ChannelPreviewTheme? channelPreviewTheme,
|
||||
ChannelTheme? channelTheme,
|
||||
MessageTheme? otherMessageTheme,
|
||||
MessageTheme? ownMessageTheme,
|
||||
MessageInputTheme? messageInputTheme,
|
||||
Widget Function(BuildContext, Channel)? defaultChannelImage,
|
||||
Widget Function(BuildContext, User)? defaultUserImage,
|
||||
IconThemeData? primaryIconTheme,
|
||||
List<ReactionIcon>? reactionIcons,
|
||||
});
|
||||
```
|
||||
|
||||
### Stream Chat Theme in use
|
||||
|
||||
Let's take a look at customizing widgets using `StreamChatTheme`. In the example below, we can change the default color theme to yellow and override the channel header's typography and colors.
|
||||
|
||||
```dart
|
||||
builder: (context, child) => StreamChat(
|
||||
client: client,
|
||||
child: child,
|
||||
streamChatThemeData: StreamChatThemeData(
|
||||
colorTheme: ColorTheme.light(
|
||||
primaryAccent: const Color(0xffffe072),
|
||||
),
|
||||
channelTheme: ChannelTheme(
|
||||
channelHeaderTheme: ChannelHeaderTheme(
|
||||
color: const Color(0xffd34646),
|
||||
title: TextStyle(
|
||||
color: Colors.white,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
```
|
||||
|
||||
We are creating this class at the very top of our widget tree using the `streamChatThemeData` parameter found in the `StreamChat` widget.
|
||||
|
||||

|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
id: user_list_view
|
||||
sidebar_position: 7
|
||||
title: UserListView
|
||||
---
|
||||
|
||||
A Widget For Displaying And Selecting Users
|
||||
|
||||
Find the pub.dev documentation [here](https://pub.dev/documentation/stream_chat_flutter/latest/stream_chat_flutter/UserListView-class.html)
|
||||
|
||||

|
||||
|
||||
### Background
|
||||
|
||||
A list of users is required for many different purposes: showing a list of users in a Channel,
|
||||
selecting users to add in a channel, etc. The `UserListView` displays and allows selection of a list
|
||||
of users along with multiple display configurations like a list and grid.
|
||||
|
||||
### Basic Example
|
||||
|
||||
Let's take a look at an example where we use the widget to autocomplete user names:
|
||||
|
||||
```dart
|
||||
class UsersListPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: UsersBloc(
|
||||
child: UsersListView(
|
||||
filter: Filter.notEqual('id', StreamChat.of(context).user!.id),
|
||||
sort: [
|
||||
SortOption(
|
||||
'name',
|
||||
direction: 1,
|
||||
),
|
||||
],
|
||||
pagination: PaginationParams(
|
||||
limit: 25,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Customize The User Items
|
||||
|
||||
You can use your own widget for the user items using the `userItemBuilder` parameter.
|
||||
|
||||
```dart
|
||||
UsersListView(
|
||||
// ...
|
||||
userItemBuilder: (context, user, isSelected) {
|
||||
return Text(user.name);
|
||||
},
|
||||
),
|
||||
```
|
||||
|
||||
### Group Alphabetically
|
||||
|
||||
You can group alphabetically using the `groupAlphabetically` parameter:
|
||||
|
||||
```dart
|
||||
UsersListView(
|
||||
//...
|
||||
groupAlphabetically: true,
|
||||
),
|
||||
```
|
||||
|
||||
### Selecting Users
|
||||
|
||||
The `UserListView` widget allows selecting users in a list by supplying a selected users list and callbacks
|
||||
for when user items are tapped.
|
||||
|
||||
```dart
|
||||
Set<User>? selectedUsers = {};
|
||||
|
||||
UsersListView(
|
||||
//...
|
||||
selectedUsers: selectedUsers,
|
||||
onUserTap: (user, _) {
|
||||
setState(() {
|
||||
selectedUsers.add(user);
|
||||
});
|
||||
},
|
||||
),
|
||||
```
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"label": "Stream Chat Flutter Core",
|
||||
"position": 4
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
---
|
||||
id: channel_list_core
|
||||
sidebar_position: 4
|
||||
title: ChannelListCore
|
||||
---
|
||||
|
||||
A Widget For Building A List Of Channels
|
||||
|
||||
### Background
|
||||
|
||||
The UI SDK of Stream Chat supplies a `ChannelListView` class that builds a list of channels fetching
|
||||
according to the filters and sort order given. However, in some cases, implementing novel UI is necessary
|
||||
that cannot be done using the customization approaches given in the widget.
|
||||
|
||||
To do this, we extracted the logic required for fetching channels into a 'Core' widget - a widget that
|
||||
fetches channels in the expected way via the usual params but does not supply any UI and instead
|
||||
exposes builders to build the UI in situations such as loading, empty data, errors, and on data received.
|
||||
|
||||
### Basic Example
|
||||
|
||||
`ChannelListCore` is a simplified class that allows fetching a list of
|
||||
channels while exposing UI builders.
|
||||
|
||||
This allows you to construct your own UI while not having to
|
||||
worry about the specific logic of fetching channels in your app.
|
||||
|
||||
A `ChannelListController` is used to reload and paginate data.
|
||||
|
||||
```dart
|
||||
class ChannelListPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: ChannelListCore(
|
||||
filter: Filter.in_(
|
||||
'members',
|
||||
[StreamChat.of(context).user!.id],
|
||||
),
|
||||
sort: [SortOption('last_message_at')],
|
||||
pagination: PaginationParams(
|
||||
limit: 20,
|
||||
),
|
||||
errorBuilder: (context, err) {
|
||||
return Center(
|
||||
child: Text('An error has occured'),
|
||||
);
|
||||
},
|
||||
emptyBuilder: (context) {
|
||||
return Center(
|
||||
child: Text('Nothing here...'),
|
||||
);
|
||||
},
|
||||
loadingBuilder: (context) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
},
|
||||
listBuilder: (context, list) {
|
||||
return ChannelPage(list);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to have a `StreamChatCore` ancestor in order to provide the
|
||||
information about the channels.
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
id: channels_bloc
|
||||
sidebar_position: 7
|
||||
title: ChannelsBloc
|
||||
---
|
||||
|
||||
A Widget Dedicated To The Management Of A Channel List With Pagination.
|
||||
|
||||
### Background
|
||||
|
||||
Most widgets in the Core SDK are focused on fetching a particular type of object from Stream Chat - channels,
|
||||
messages, users, etc. The BLoC widgets bundle up the base functions used to fetch data as well as the current
|
||||
data fetched by the respective functions. Furthermore, the Core widgets use this BLoC to fetch new or
|
||||
existing data and build UI based on it.
|
||||
|
||||
All Core and UI widgets which focus on fetching a list of objects need to have their respective functions
|
||||
above them in the widget tree. The ChannelListCore and ChannelListView require the ChannelsBloc
|
||||
above them in the widget hierarchy without which they will fail.
|
||||
|
||||
### Understanding The Widget
|
||||
|
||||
`ChannelsBloc` is used together with `ChannelListCore` to manage a list of
|
||||
Channels with pagination, re-ordering, querying and other operations
|
||||
associated with Channels.
|
||||
|
||||
`ChannelsBloc` can be accessed at anytime by using the static `.of` method
|
||||
using Flutter's `BuildContext`.
|
||||
|
||||
```dart
|
||||
var _channelsBloc = ChannelsBloc.of(context);
|
||||
```
|
||||
|
||||
The `ChannelsBloc` widget encapsulates common functionality related to channel lists such as fetching
|
||||
the existing channels and querying new channels and also supplies them down the widget tree.
|
||||
|
||||
The widget is required for the respective core widget (`ChannelListCore`) to fetch channels and hence
|
||||
must be above the core widget in the tree.
|
||||
|
||||
Here is a basic implementation of `ChannelsBloc`:
|
||||
|
||||
```dart
|
||||
ChannelsBloc(
|
||||
child: // Further Widget Tree
|
||||
),
|
||||
```
|
||||
|
||||
The `ChannelsBloc` widget allows three customisations:
|
||||
|
||||
#### Lock Channels Order
|
||||
|
||||
ChannelsBloc may change the order of channels when new messages arrive. To lock this order, we can
|
||||
set the `lockChannelsOrder` property to true.
|
||||
|
||||
```dart
|
||||
ChannelsBloc(
|
||||
lockChannelsOrder: true,
|
||||
child: // Further Widget Tree
|
||||
),
|
||||
```
|
||||
|
||||
#### Set custom channel order
|
||||
|
||||
We can decide the order of the channels in the list by supplying a comparator to the `channelsComparator`
|
||||
parameter:
|
||||
|
||||
```dart
|
||||
ChannelsBloc(
|
||||
channelsComparator: (a, b) {
|
||||
return a.createdAt!.millisecondsSinceEpoch >
|
||||
b.createdAt!.millisecondsSinceEpoch
|
||||
? 1
|
||||
: -1;
|
||||
},
|
||||
child: // Further Widget Tree
|
||||
),
|
||||
```
|
||||
|
||||
#### Decide if channel should be added on new message event
|
||||
|
||||
When a new message arrives, a `message.new` event is received. We can decide if we want to add the channel
|
||||
to the list using the `shouldAddChannel` parameter which is a callback supplying the event data:
|
||||
|
||||
```dart
|
||||
ChannelsBloc(
|
||||
shouldAddChannel: (event) {
|
||||
return event.message!.extraData['priority'] == '1';
|
||||
},
|
||||
child: // Further Widget Tree
|
||||
),
|
||||
```
|
||||
@@ -0,0 +1,80 @@
|
||||
---
|
||||
id: introduction
|
||||
sidebar_position: 1
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
Understanding The Core Package Of The Flutter SDK
|
||||
|
||||
This package provides business logic to fetch common things required for integrating Stream Chat into your application.
|
||||
The core package allows more customisation and hence provides business logic but no UI components.
|
||||
Please use the `stream_chat_flutter` package for the full fledged suite of UI components or `stream_chat` for the low-level client.
|
||||
|
||||
### Background
|
||||
|
||||
In the early days of the Flutter SDK, the SDK was only split into the LLC (`stream_chat`) and
|
||||
the UI package (`stream_chat_flutter`). With this you could use a fully built interface with the UI package
|
||||
or a fully custom interface with the LLC. However, we soon recognised the need for a third intermediary
|
||||
package which made tasks like building and modifying a list of channels or messages easy but without
|
||||
the complexity of using low level components. The Core package (`stream_chat_flutter_core`) is a manifestation
|
||||
of the same idea and allows you to build an interface with Stream Chat without having to deal with
|
||||
low level code and architecture as well as implementing your own theme and UI effortlessly.
|
||||
Also, it has very few dependencies.
|
||||
|
||||
We will now explore the components of this intermediary package and understand how it helps you build
|
||||
the experience you want your users to have.
|
||||
|
||||
The package primarily contains three types of classes:
|
||||
|
||||
* Business Logic Components
|
||||
* Core Components
|
||||
* Core Controllers
|
||||
|
||||
### Business Logic Components
|
||||
|
||||
These components allow you to have the maximum and lower-level control of the queries being executed.
|
||||
|
||||
In BLoCs, the basic functionalities - such as queries for messages, channels or queries - are bundled up
|
||||
and passed along down the tree. Using a BLoC allows you to either create your own way to fetch and
|
||||
build UIs or use an inbuilt Core widget to do the work such as queries, pagination, etc for you.
|
||||
|
||||
The BLoCs we provide are:
|
||||
|
||||
* ChannelsBloc
|
||||
* MessageSearchBloc
|
||||
* UsersBloc
|
||||
|
||||
### Core Components
|
||||
|
||||
Core components usually are an easy way to fetch data associated with Stream Chat.
|
||||
Core components use functions exposed by the respective BLoCs (for example the ChannelListCore uses the ChannelsBloc)
|
||||
and use the respective controllers for various operations. Unlike heavier components from the UI
|
||||
package, core components are decoupled from UI and they expose builders instead to help you build
|
||||
a fully custom interface.
|
||||
|
||||
Data fetching can be controlled with the controllers of the respective core components.
|
||||
|
||||
* ChannelListCore (Fetch a list of channels)
|
||||
* MessageListCore (Fetch a list of messages from a channel)
|
||||
* MessageSearchListCore (Fetch a list of search messages)
|
||||
* UserListCore (Fetch a list of users)
|
||||
* StreamChatCore (This is different from the other core components - it is a version of StreamChat decoupled from theme and initialisations.)
|
||||
|
||||
### Core Controllers
|
||||
|
||||
Core Controllers are supplied to respective CoreList widgets which allows reloading and pagination of data whenever needed.
|
||||
|
||||
Unlike the UI package, the Core package allows a fully custom user interface built with the data. This
|
||||
in turn provides a few challenges: we do not know implicitly when to paginate your list or reload your data.
|
||||
|
||||
While this is handled out of the box in the UI package since the List implementation is inbuilt, a controller
|
||||
needs to be used in the core package notifying the core components to reload or paginate the data existing
|
||||
currently. For this, each core component has a respective controller which you can use to call the
|
||||
specific function (reload / paginate) whenever such an event is triggered through / needed in your UI.
|
||||
|
||||
* ChannelListController
|
||||
* MessageListController
|
||||
* MessageSearchListController
|
||||
* ChannelListController
|
||||
|
||||
This section goes into the individual core package widgets and their functional use.
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
id: message_list_core
|
||||
sidebar_position: 5
|
||||
title: MessageListCore
|
||||
---
|
||||
|
||||
A Widget For Building A List Of Messages
|
||||
|
||||
### Background
|
||||
|
||||
The UI SDK of Stream Chat supplies a `MessageListView` class that builds a list of channels fetching
|
||||
according to the filters and sort order given. However, in some cases, implementing novel UI is necessary
|
||||
that cannot be done using the customization approaches given in the widget.
|
||||
|
||||
To do this, we extracted the logic required for fetching channels into a 'Core' widget - a widget that
|
||||
fetches channels in the expected way via the usual params but does not supply any UI and instead
|
||||
exposes builders to build the UI in situations such as loading, empty data, errors, and on data received.
|
||||
|
||||
### Basic Example
|
||||
|
||||
`MessageListCore` is a simplified class that allows fetching a list of
|
||||
messages while exposing UI builders.
|
||||
|
||||
This allows you to construct your own UI while not having to
|
||||
worry about the specific logic of fetching messages in a channel.
|
||||
|
||||
A `MessageListController` is used to paginate data.
|
||||
|
||||
```dart
|
||||
class ChannelPage extends StatelessWidget {
|
||||
const ChannelPage({
|
||||
Key key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: Column(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: MessageListCore(
|
||||
emptyBuilder: (context) {
|
||||
return Center(
|
||||
child: Text('Nothing here...'),
|
||||
);
|
||||
},
|
||||
loadingBuilder: (context) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
},
|
||||
messageListBuilder: (context, list) {
|
||||
return MessagesPage(list);
|
||||
},
|
||||
errorWidgetBuilder: (context, err) {
|
||||
return Center(
|
||||
child: Text('Error'),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to have a `StreamChannel` ancestor in order to provide the
|
||||
information about the channels.
|
||||
@@ -0,0 +1,40 @@
|
||||
---
|
||||
id: message_search_list_block
|
||||
sidebar_position: 8
|
||||
title: MessageSearchListBloc
|
||||
---
|
||||
|
||||
A Widget Used To Manage A List Of Messages With Pagination.
|
||||
|
||||
### Background
|
||||
|
||||
Most widgets in the Core SDK are focused on fetching a particular type of object from Stream Chat - channels,
|
||||
messages, users etc. The BLoC widgets bundle up the base functions used to fetch data as well as the current
|
||||
data fetched by the respective functions. Furthermore, the Core widgets use this BLoC to fetch new or
|
||||
existing data and build UI based on it.
|
||||
|
||||
All Core and UI widgets which focus on fetching a list of objects need to have their respective functions
|
||||
above them in the widget tree. The MessageSearchListCore and MessageSearchListView require the
|
||||
MessageSearchListCore above them in the widget hierarchy without which they will fail.
|
||||
|
||||
### Understanding The Widget
|
||||
|
||||
This class can be used to load messages, perform queries, etc.
|
||||
|
||||
`MessageSearchBloc` can be accessed at anytime by using the static `.of` method
|
||||
using Flutter's BuildContext.
|
||||
|
||||
```dart
|
||||
var _searchBloc = MessageSearchBloc.of(context);
|
||||
```
|
||||
|
||||
The `MessageSearchBloc` widget encapsulates common functionality related to searching for messages
|
||||
across channels and also supplies them down the widget tree.
|
||||
|
||||
Here is a basic implementation of `ChannelsBloc`:
|
||||
|
||||
```dart
|
||||
MessageSearchBloc(
|
||||
child: // Further Widget Tree
|
||||
),
|
||||
```
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
id: message_search_list_core
|
||||
sidebar_position: 6
|
||||
title: MessageSearchListCore
|
||||
---
|
||||
|
||||
A Widget For Displaying Message Searches
|
||||
|
||||
### Background
|
||||
|
||||
The UI SDK of Stream Chat supplies a `MessageSearchListView` class that builds a list of channels fetching
|
||||
according to the filters and sort order given. However, in some cases, implementing novel UI is necessary
|
||||
that cannot be done using the customization approaches given in the widget.
|
||||
|
||||
To do this, we extracted the logic required for fetching channels into a 'Core' widget - a widget that
|
||||
fetches channels in the expected way via the usual params but does not supply any UI and instead
|
||||
exposes builders to build the UI in situations such as loading, empty data, errors, and on data received.
|
||||
|
||||
### Basic Example
|
||||
|
||||
`MessageSearchListCore` is a simplified class that allows searching for
|
||||
messages across channels while exposing UI builders.
|
||||
A `MessageSearchListController` is used to load and paginate data.
|
||||
|
||||
```dart
|
||||
class MessageSearchPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: MessageSearchListCore(
|
||||
messageQuery: _messageFilter,
|
||||
filters: _channelsFilter,
|
||||
paginationParams: PaginationParams(limit: 20),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Make sure to have a `MessageSearchBloc` ancestor in order to provide the
|
||||
information about the messages.
|
||||
@@ -0,0 +1,28 @@
|
||||
---
|
||||
id: setup
|
||||
sidebar_position: 2
|
||||
title: Setup
|
||||
---
|
||||
|
||||
Understanding Setup For `stream_chat_flutter_core`
|
||||
|
||||
### Add pub.dev dependency
|
||||
|
||||
First, you need to add the `stream_chat_flutter_core` dependency to your pubspec.yaml
|
||||
|
||||
You can either run this command:
|
||||
|
||||
```shell
|
||||
flutter pub add stream_chat_flutter_core
|
||||
```
|
||||
|
||||
OR
|
||||
|
||||
Add this line in the dependencies section of your pubspec.yaml after substituting latest version:
|
||||
|
||||
```yaml
|
||||
dependencies:
|
||||
stream_chat_flutter_core: ^latest_version
|
||||
```
|
||||
|
||||
You can find the package details on [pub.dev](https://pub.dev/packages/stream_chat_flutter_core).
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
id: stream_chat_core
|
||||
sidebar_position: 3
|
||||
title: StreamChatCore
|
||||
---
|
||||
|
||||
`StreamChatCore` is a version of `StreamChat` found in `stream_chat_flutter` that is decoupled from
|
||||
theme and initialisations.
|
||||
|
||||
`StreamChatCore` is used to provide information about the chat client to the widget tree.
|
||||
This Widget is used to react to life cycle changes and system updates.
|
||||
When the app goes into the background, the websocket connection is automatically closed and when it goes back to foreground the connection is opened again.
|
||||
|
||||
Like the `StreamChat` widget in the higher level UI package, the `StreamChatCore` widget should
|
||||
be on the top level before using any Stream functionality:
|
||||
|
||||
```dart
|
||||
return MaterialApp(
|
||||
title: 'Stream Chat Core Example',
|
||||
home: HomeScreen(),
|
||||
builder: (context, child) => StreamChatCore(
|
||||
client: client,
|
||||
child: child!,
|
||||
),
|
||||
);
|
||||
```
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
id: user_list_core
|
||||
sidebar_position: 10
|
||||
title: UserListCore
|
||||
---
|
||||
|
||||
A Widget For Building A List Of Users
|
||||
|
||||
### Background
|
||||
|
||||
The UI SDK of Stream Chat supplies a `UserListView` class that builds a list of channels fetching
|
||||
according to the filters and sort order given. However, in some cases, implementing novel UI is necessary
|
||||
that cannot be done using the customization approaches given in the widget.
|
||||
|
||||
To do this, we extracted the logic required for fetching channels into a 'Core' widget - a widget that
|
||||
fetches channels in the expected way via the usual params but does not supply any UI and instead
|
||||
exposes builders to build the UI in situations such as loading, empty data, errors, and on data received.
|
||||
|
||||
### Basic Example
|
||||
|
||||
`UserListCore` is a simplified class that allows fetching users while
|
||||
exposing UI builders.
|
||||
A `UserListController` is used to load and paginate data.
|
||||
|
||||
```dart
|
||||
class UsersListPage extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: UsersListCore(
|
||||
sort: [SortOption('last_active')],
|
||||
pagination: PaginationParams(
|
||||
limit: 20,
|
||||
),
|
||||
errorBuilder: (err) {
|
||||
return Center(
|
||||
child: Text('An error has occured'),
|
||||
);
|
||||
},
|
||||
emptyBuilder: (context) {
|
||||
return Center(
|
||||
child: Text('Nothing here...'),
|
||||
);
|
||||
},
|
||||
emptyBuilder: (context) {
|
||||
return Center(
|
||||
child: CircularProgressIndicator(),
|
||||
);
|
||||
},
|
||||
listBuilder: (context, list) {
|
||||
return UsersPage(list);
|
||||
}
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
`UsersBloc` must be the ancestor of this widget. This is necessary since
|
||||
`UserListCore` depends on functionality contained within `UsersBloc`.
|
||||
|
||||
The parameters `listBuilder`, `loadingBuilder`, `emptyBuilder` and
|
||||
`errorBuilder` must all be supplied and not null.
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
id: users_bloc
|
||||
sidebar_position: 9
|
||||
title: UsersBloc
|
||||
---
|
||||
|
||||
A Widget Dedicated To The Management Of A Users List With Pagination.
|
||||
|
||||
### Background
|
||||
|
||||
Most widgets in the Core SDK are focused on fetching a particular type of object from Stream Chat - channels,
|
||||
messages, users, etc. The BLoC widgets bundle up the base functions used to fetch data as well as the current
|
||||
data fetched by the respective functions. Furthermore, the Core widgets use this BLoC to fetch new or
|
||||
existing data and build UI based on it.
|
||||
|
||||
All Core and UI widgets which focus on fetching a list of objects need to have their respective functions
|
||||
above them in the widget tree. The UserListCore and UserListView require the UserListCore
|
||||
above them in the widget hierarchy without which they will fail.
|
||||
|
||||
### Understanding The Widget
|
||||
|
||||
`UsersBloc` can be accessed at anytime by using the static `.of` method
|
||||
using Flutter's `BuildContext`.
|
||||
|
||||
```dart
|
||||
var _userBloc_ = UsersBloc.of(context);
|
||||
```
|
||||
|
||||
The `UsersBloc` widget encapsulates common functionality related to user lists and also supplies them down the widget tree.
|
||||
|
||||
Here is a basic implementation of `UsersBloc`:
|
||||
|
||||
```dart
|
||||
UsersBloc(
|
||||
child: // Further Widget Tree
|
||||
),
|
||||
```
|
||||
@@ -19,16 +19,15 @@ import 'package:stream_chat_flutter_core/src/typedef.dart';
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return Scaffold(
|
||||
/// body: ChannelListCore(
|
||||
/// filter: {
|
||||
/// 'members': {
|
||||
/// '\$in': [StreamChat.of(context).user.id],
|
||||
/// }
|
||||
/// },
|
||||
/// filter: Filter.in_(
|
||||
/// 'members',
|
||||
/// [StreamChat.of(context).user!.id],
|
||||
/// ),
|
||||
/// sort: [SortOption('last_message_at')],
|
||||
/// pagination: PaginationParams(
|
||||
/// limit: 20,
|
||||
/// ),
|
||||
/// errorBuilder: (err) {
|
||||
/// errorBuilder: (context, err) {
|
||||
/// return Center(
|
||||
/// child: Text('An error has occured'),
|
||||
/// );
|
||||
@@ -38,7 +37,7 @@ import 'package:stream_chat_flutter_core/src/typedef.dart';
|
||||
/// child: Text('Nothing here...'),
|
||||
/// );
|
||||
/// },
|
||||
/// emptyBuilder: (context) {
|
||||
/// loadingBuilder: (context) {
|
||||
/// return Center(
|
||||
/// child: CircularProgressIndicator(),
|
||||
/// );
|
||||
|
||||
@@ -17,12 +17,8 @@ import 'package:stream_chat_flutter_core/src/typedef.dart';
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return Scaffold(
|
||||
/// body: MessageSearchListCore(
|
||||
/// messageQuery: _channelQuery,
|
||||
/// filters: {
|
||||
/// 'members': {
|
||||
/// r'$in': [user.id]
|
||||
/// }
|
||||
/// },
|
||||
/// messageQuery: _messageFilter,
|
||||
/// filters: _channelsFilter,
|
||||
/// paginationParams: PaginationParams(limit: 20),
|
||||
/// ),
|
||||
/// );
|
||||
|
||||