fix: removed stream_chat docs

This commit is contained in:
Deven Joshi
2021-06-30 17:29:33 +05:30
parent 3c4881daed
commit 3a6bb102b9
26 changed files with 0 additions and 1457 deletions
@@ -1,4 +0,0 @@
{
"label": "Stream Chat (LLC)",
"position": 2
}
@@ -1,35 +0,0 @@
---
id: channel_members
sidebar_position: 10
title: Channel Members
---
Manipulating Members In A Channel
### Adding & Removing Channel Members
Using the addMembers() method adds the given users as members, while removeMembers() removes them.
```dart
await channel.addMembers(["thierry", "josh"]);
await channel.removeMembers(["tommaso"]);
```
You can optionally include a message object that client-side SDKs will use to populate a system message.
This works for both add and remove members:
```dart
// using client-side client
await channel.addMembers(['tommaso'], Message(text: 'Tommaso joined'));
```
### Leaving a channel
It is possible for user to leave the channel without moderator-level permissions.
Make sure channel members have `RemoveOwnChannelMembership` permission.
```dart
// remove own channel membership
await channel.removeMembers(['my_user_id']);
```
@@ -1,47 +0,0 @@
---
id: creating_channels
sidebar_position: 6
title: Creating Channels
---
Create Channels In Your App
Both channel <b>channel.query</b> and <b>channel.watch</b> methods ensure that a channel exists and create one otherwise.
If all you need is to ensure that a channel exists, you can use <b>channel.create</b>.
Typically you use <b>channel.watch</b> client side and <b>channel.create</b> for a server side integration.
Channels are unique either by the specified channel id or by the list of members.
### Creating a Channel Using a Channel ID
This is typically the best approach if you already have some sort of object in your database that the channel is associated with.
As an example if you're building a live-streaming service like Twitch you have a channel for every streamer in your database.
```dart
final channel = client.channel(
"messaging",
id: "travel",
extraData: {
"name": "Founder Chat",
"image": "http://bit.ly/2O35mws",
"members": ["thierry", "tommaso"],
},
);
```
Note: Note that for client side integrations you'll typically prefer to use channel.watch() instead of channel.create.
Channel.watch both creates the channel and watches it at the same time.
### Creating a Channel for a List of Members
Channels can be used to create conversations between users.
In most cases, you want conversations to be unique and make sure that a group of users have only one channel.
You can achieve this by leaving the channel ID empty and provide channel type and members.
When you do so, the API will ensure that only one channel for the members you specified exists (the order of the members does not matter).
Note: You cannot add/remove members for channels created this way.
```dart
client.channel("messaging", extraData: {"members": ["thierry", "tommaso"]});
```
@@ -1,39 +0,0 @@
---
id: deleting_and_hiding_channel
sidebar_position: 13
title: Deleting And Hiding A Channel
---
Remove Channels By Deleting Or Hiding
### Deleting a Channel
You can delete a Channel using the delete method. This marks the channel as deleted and hides all the content.
```dart
await channel.delete();
```
Note: If you recreate this channel, it will show up empty. Recovering old messages is not currently supported via the Stream Chat API.
### Hiding a Channel
Hiding a channel will remove it from query channel requests for that user until a new message is added.
Please keep in mind that hiding a channel is only available to members of that channel.
Optionally you can also clear the entire message history of that channel for the user.
This way, when a new message is received, it will be the only one present in the channel.
```dart
// hides the channel until a new message is added there
await channel.hide();
// shows a previously hidden channel
await channel.show();
// hide the channel and clear the message history
await channel.hide(clearHistory: true);
```
Note: You can still retrieve the list of hidden channels using the { "hidden" : true } query parameter.
@@ -1,86 +0,0 @@
---
id: events
sidebar_position: 25
title: Events
---
Understand Low Level Messaging Events
Events allow the client to stay up to date with changes to the chat. Examples are a new message, a user's image that updated, a reaction, or a member joining the channel. There are a 4 different type of events. These first 2 types of events you receive if you're connected to Stream, no further action is needed to receive these events:
Client events: You always receive these events.
Examples are `connection.recovered`, `health.check` and `connection.changed`
Notification events: Notification events notify you when something changed on a channel you are a member of even if you're not explicitly watching that channel.
One example is someone starting a new channel to message you while you are currently in the app.
User presence events: `queryUsers`, `queryChannels` and `channel.watch()` allow you to specify `presence=True`,
if you specify this option you'll opt in to receiving updates about the users on these channels.
You'll receive events when they go online/offline or their data is updated
Channel events: if you call `queryChannels` with `watch=true`, or you call `channel.watch()` you'll opt-in to receiving events for the given channels.
Examples are new messages, people joining the chat etc.
### Listening To Events
As soon as you call watch on a Channel or queryChannels youll start to listen to these events. You can hook into specific events:
```dart
channel.on("message.deleted").listen((Event event) {
print("message ${event.message.id} was deleted");
});
```
You can also listen to all events at once:
```dart
channel.on().listen((Event event) {
print("received a new event of type ${event.type}");
});
```
### Connection Events
The official SDKs make sure that a connection to Stream is kept alive at all times and that chat state
is recovered when the user's internet connection comes back online.
Your application can subscribe to changes to the connection using client events.
```dart
client.on('connection.changed', (e) => {
if (e.online) {
print('the connection is up!');
} else {
print('the connection is down!');
}
});
```
### Stop Listening for Events
It is a good practice to unregister event handlers once they are not in use anymore. Doing so will save you from performance degradations coming from memory leaks or even from errors and exceptions (i.e. null pointer exceptions)
```dart
final subscription = channel.on().listen((Event event) {
print("received a new event of type ${event.type}");
});
subscription.cancel();
```
### Custom Events
Custom events allow you to build more complex interactions within a channel or with a user.
#### To a channel
Users connected to a channel, either as a watcher or member, can send custom events and have them delivered to all users watching the channel.
```dart
// sends an event for the current user to all connect clients on the channel
await channel.sendEvent(
Event(
type: 'friendship_request',
extraData: {
'text': 'Hey there, long time no see!',
},
),
);
```
@@ -1,23 +0,0 @@
---
id: introduction
sidebar_position: 1
title: Introduction
---
Exploring the Basics of the stream_chat package (LLC)
<h2> Official Dart Client for Stream Chat </h2>
The official Dart client for Stream Chat, a service for building chat applications.
This library can be used on any Dart project and on both mobile and web apps with Flutter.
The Low Level Client ([stream_chat]('https://pub.dev/packages/stream_chat')) provides the basic
bindings for integrating Stream Chat into your Flutter app with the ability to connect users,
listening to events, send and receive messages, channel CRUD operations, etc.
This allows you to control and customise your interface completely while using the
Stream Chat backend.
Check out our Core package ([stream_chat_flutter_core]('https://pub.dev/packages/stream_chat_flutter_core'))
for easier implementations of common uses such as retrieving channels,
retrieving channel message lists, seraching for messages, etc.
This section goes into detail on using the LLC and various things you can achieve using it.
@@ -1,63 +0,0 @@
---
id: invites
sidebar_position: 11
title: Invites
---
Invite A User To Join A Channel
### Inviting Users
Stream Chat provides the ability to invite users to a channel via the `channel` method with the `invites` array.
Upon invitation, the end-user will receive a notification that they were invited to the specified channel.
See the following for an example on how to invite a user by adding an invites array containing the user ID:
```dart
final invite = client.channel("messaging", id: "awesome-chat",
extraData: {
"name": "Founder Chat",
"members": ["thierry", "tommaso", "nick"],
"invites": ["nick"],
});
await invite.create();
```
### Accepting an Invite
In order to accept an invite, you must use call the `acceptInvite` method.
The `acceptInvite` method accepts and object with an optional `message` property.
Please see below for an example of how to call `acceptInvite`:
```dart
final channel = client.channel("messaging", id: "awesome-chat");
await channel.acceptInvite();
```
### Rejecting an Invite
To reject an invite, call the `rejectInvite` method.
This method does not require a user ID as it pulls the user ID from the current session in store from the `connectUser` call.
```dart
await channel.rejectInvite();
```
### Query for Accepted Invites
Querying for accepted invites is done via the `queryChannels` method.
This allows you to return a list of accepted invites with a single call. See below for an example:
```dart
final invites = await client.queryChannels(filter: {"invite": "accepted"});
```
### Query for Rejected Invites
Similar to querying for accepted invites, you can query for rejected invites with `queryChannels`.
See below for an example:
```dart
final rejected = await client.queryChannels(filter: {"invite": "rejected"});
```
@@ -1,127 +0,0 @@
---
id: messages
sidebar_position: 16
title: Messages
---
Send, Update And Delete Messages
Let's dive right into it, the example below shows how to send a simple message using Stream:
```dart
final message = Message(
text: '@Josh I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.'
);
await channel.sendMessage(message);
```
Note how server side SDKs require that you specify `user_id` to indicate who is sending the message.
You can add custom fields to both the message and the attachments.
There's a 5KB limit for the custom fields.
File uploads are uploaded to the CDN so don't count towards this 5KB limit.
A more complex example for creating a message is shown below:
```dart
final message = Message(
text: '@Josh I told them I was pesca-pescatarian. Which is one who eats solely fish who eat other fish.',
attachments: [
Attachment(
type: "image",
assetUrl: "https://bit.ly/2K74TaG",
thumbUrl: "https://bit.ly/2Uumxti",
extraData: {
"myCustomField": 123,
}
),
],
mentionedUsers: [
User(id: "josh")
],
extraData: {
"anotherCustomField": 234,
},
);
await channel.sendMessage(message);
```
By default Streams UI components support the following attachment types:
* Audio
* Video
* Image
* Text
You can specify different types as long as you implement the frontend rendering logic to handle them. Common use cases include:
* Embedding products (photos, descriptions, outbound links, etc.)
* Sharing of a users location
* The React tutorial for Stream Chat explains how to customize the Attachment component.
### Get a Message
You can get a single message by its ID using the `getMessage` call:
```dart
final message = await client.getMessage("message-id");
```
### Update a Message
You can edit a message by calling updateMessage and including a message with an ID the ID field is required when editing a message:
```dart
await client.updateMessage(Message(id: "123", text: "the edited version of my text"));
```
### Partial Update
A partial update can be used to set and unset specific fields when it is necessary to retain additional data fields on the object.
AKA a patch style update.
```dart
// partial update message text
const text = 'the text was partial updated';
const updated = await client.partiallyUpdateMessage(originalMessage.id, {
set: {
text
}
});
// unset color property
await client.partiallyUpdateMessage(originalMessage.id, {
'unset': ['color'],
});
// set nested property
await client.partiallyUpdateMessage(originalMessage.id, {
'set': {
'details.status': 'complete'
},
});
```
### Delete A Message
You can delete a message by calling deleteMessage and including a message with an ID. Messages can be soft deleted or hard deleted. Unless specified via the hard parameter, messages are soft deleted.
```dart
await client.deleteMessage("123");
```
### Soft delete
1. Can be done client-side by users
2. Message is still returned in the message list and all its data is kept as it is
3. Message type is set to "deleted"
4. Reactions and replies are kept in place
### Hard delete
1. Can be done client-side by users but be cautious this action is not recoverable
2. The message is removed from the channel and its data is wiped
3. All reactions are deleted
4. All replies and their reactions are deleted
5. By default messages are soft deleted, this is a great way to keep the channel history consistent.
@@ -1,120 +0,0 @@
---
id: moderation_tools
sidebar_position: 23
title: Moderation Tools
---
Moderation Tools For A Better Chat Experience
### Flag
Any user is allowed to flag a message.
Flagging does not perform any particular action on the chat.
The API will only trigger the related webhook event and make the message appear on your Stream Dashboard Chat Moderation view.
```dart
await client.flagMessage("messageID");
```
### Mutes
Any user is allowed to mute another user.
Mutes are stored at user level and returned with the rest of the user information when connectUser is called.
A user will be be muted until the user is unmuted or the mute is expired.
```dart
await client.muteUser("eviluser");
await client.unmuteUser("eviluser");
```
After muting a user messages will still be delivered via web-socket.
Implementing business logic such as hiding messages from muted users or display them differently is left to the developer to implement.
Messages from muted users are not delivered via push (APN/Firebase)
### Ban
Users can be banned from an app entirely or from a channel. When a user is banned, they will not be allowed to post messages until the ban is removed or expired but will be able to connect to Chat and to channels as before.
Users must be a member of a channel to be banned from that channel. Channel watchers cannot be banned.
It is also possible to ban the user's last known IP address to prevent creation of new "throw-away" accounts. This type of ban is only applicable on the app level. We do not recommend applying IP ban without reasonable timeout, however this is not restricted. The IP address will be unbanned either after reaching a timeout or with explicit user unban.
In most cases only admins or moderators are allowed to ban other users from a channel.
```dart
// ban a user for 60 minutes from all channel
await client.banUser('eviluser', {
'banned_by_id': userID, // ID of the user who is performing the ban (Server-side auth)
'timeout': 60,
'reason': 'Banned for one hour',
});
// ban a user and their IP address for 24 hours
await client.banUser('eviluser', {
'banned_by_id': userID,
'timeout': 24*60,
'ip_ban': true,
'reason': 'Please come back tomorrow',
});
// ban a user from the livestream:fortnite channel
await channel.banUser('eviluser', {
'banned_by_id': userID,
'reason': 'Profanity is not allowed here',
});
// remove ban from channel
await channel.unbanUser('eviluser');
// remove global ban
await authClient.unbanUser('eviluser');
```
### Query Banned Users
Banned users can be retrieved in different ways:
Using the dedicated query bans endpoint
User Search: you can add the banned:true condition to your search. Please note that this will only return users that were banned at the app-level and not the ones that were banned only on channels.
```dart
// retrieve the list of banned users
await client.queryUsers(filter: Filter.equal('banned', true), pagination: PaginationParams(limit:10, offset:0));
```
### Shadow Ban
Users can be shadow banned from a channel, set of channels, or an entire app. When a user is shadow banned, they will still be allowed to post messages, but any message sent during the ban, will have the shadowed: true field set; this will be invisible from the author of the message.
You will need to implement UI logic for how your application will handle shadowed messages. Having the client hide these messages for everybody other than the user sending them is a common approach.
```dart
// shadow ban a user from all channels
await client.shadowBan('eviluser');
// shadow ban a user from a channel
await channel.shadowBan('eviluser');
// remove shadow ban from channel
await channel.removeShadowBan('eviluser');
// remove global shadow ban
await client.removeShadowBan('eviluser');
Administrators can view shadow banned user status in queryChannels(), queryMembers() and queryUsers().
```
### Block Lists
A list of words you can define to moderate chat messages.
A block list can be assigned to each channel type to either block or flag messages that contain these words.
More information can be found [here](https://getstream.io/chat/docs/react/block_lists/?language=dart).
### Advanced Chat Moderation
Advanced Chat Moderation is currently in beta and accepting trial candidates. Please contact support to discuss your options.
Advanced Chat Moderation uses an AI-based classification system to detect various types of bad content.
The tool is powered by a machine learning model that provides a confidence interval (0-1) for a message,
in each of three categories: Spam, Explicit and Toxic.
The model is highly configurable for each channel type and removes the manual work of a human moderator. You can learn more [here](https://getstream.io/chat/docs/react/advanced_moderation_beta/?language=dart).
@@ -1,64 +0,0 @@
---
id: muting_channels
sidebar_position: 12
title: Muting Channels
---
Muting Channels For Users
Messages added to a channel will not trigger push notifications, nor change the unread count for the users that muted it.
By default, mutes stay in place indefinitely until the user removes it; however, you can optionally set an expiration time.
The list of muted channels and their expiration time is returned when the user connects.
### Channel Mute
```dart
// mute channel for current user
await channel.mute();
// mute a channel for 2 weeks
await channel.mute(expiration: Duration(days: 15));
// mute a channel for 10 seconds
await channel.mute(expiration: Duration(seconds: 10));
// check if channel is muted
channel.isMuted;
```
### Query Muted Channels
Muted channels can be filtered or excluded by using the `muted` in your query channels filter.
```dart
// retrieve all channels excluding muted ones
await client.queryChannels(
filter: {
'members': {
r'$in': [userId],
},
'muted': false,
}
);
// retrieve all muted channels
await client.queryChannels(
filter: {
'muted': true,
}
);
```
### Remove a Channel Mute
Whenever you need to unmute, you are able to.
```dart
// unmute channel for current user
await channel.unmute();
// unmute channel for a user (server-side)
await channel.unmute({ user_id: userId });
```
@@ -1,37 +0,0 @@
---
id: paginating_channels
sidebar_position: 15
title: Channel Pagination
---
Understanding Pagination For The Channel List
The channel query endpoint allows you to paginate the list of messages, watchers, and members for one channel.
To make sure that you are able to retrieve a consistent list of messages, pagination does not work with simple offset/limit parameters but instead,
it relies on passing the ID of the messages from the previous page.
For example: say that you fetched the first 100 messages from a channel and want to lead the next 100.
To do this you need to make a channel query request and pass the ID of the oldest message if you are paginating in descending order or the ID of the newest message if paginating in ascending order.
Use the `id_lt` parameter to retrieve messages older than the provided ID and `id_gt` to retrieve messages newer than the provided ID.
The terms `id_lt` and `id_gt` stand for ID less than and ID greater than.
ID-based pagination improves performance and prevents issues related to the list of messages changing while youre paginating. If needed, you can also use the inclusive versions of those two parameters: id_lte and id_gte.
```dart
final response = await channel.query(
messagesPagination: PaginationParams(limit: 2, lessThanOrEqual: "123"),
membersPagination: PaginationParams(limit: 2, offset: 0),
watchersPagination: PaginationParams(limit: 2, offset: 0),
);
```
For members and watchers, we use limit and offset parameters.
<b>Notes:</b>
1. Soon we will create friendlier aliases for `id_lt` and `id_gt`. Our best candidates are before_id and after_id,
let us know if you have any feedback or suggestion!
2. The maximum number of messages that can be retrieved at once from the API is 300.
@@ -1,66 +0,0 @@
---
id: pinned_messages
sidebar_position: 22
title: Pinned Messages
---
Pinning A Message In A Channel
Pinned messages allow users to highlight important messages, make announcements, or temporarily promote content.
Pinning a message is, by default, restricted to certain user roles, but this is flexible.
Each channel can have multiple pinned messages and these can be created or updated with or without an expiration.
### Pin and unpin a message
An existing message can be updated to be pinned or unpinned by using the `channel.pinMessage` and `channel.unpinMessage` methods.
Or a new message can be pinned when it is sent by setting the `pinned` and `pin_expires` fields when using `channel.sendMessage`.
```dart
// create pinned message
final message = await channel
.sendMessage(Message(
text: 'my message',
pinned: true,
pinExpires: DateTime.now().add(Duration(days: 3)),
))
.then((resp) => resp.message);
// unpin message
await channel.unpinMessage(message);
// pin message for 120 seconds
await channel.pinMessage(message, 120);
// change message expiration to 2077
await channel.pinMessage(message, DateTime(2077));
// remove expiration date from pinned message
await channel.pinMessage(message, null);
```
To pin the message user has to have PinMessage permission.
You can find the list of permissions and defaults in Permission Resources and Default Permissions sections
### Retrieve pinned messages
You can easily retrieve the last 10 pinned messages from the `channel.pinned_messages` field:
```dart
// get channel state
final channelState = await channel.query();
// get pinned messages from it
final pinnedMessages = channelState.pinnedMessages;
```
To learn more about channels you can visit Querying Channels page
Search for all pinned messages
Stream Chat also provides search filter in case if you need to display more than 10 pinned messages in specific channel.
```dart
// list all pinned messages of the channel
final response = await channel.search(
messageFilters: Filter.equal('pinned', true),
);
```
@@ -1,41 +0,0 @@
---
id: querying_channels
sidebar_position: 7
title: Querying Channels
---
More About Fetching A List Of Channels
If youre building a similar application to Facebook Messenger or Intercom, youll want to show a list of Channels.
The Chat API supports MongoDB style queries to make this easy to implement.
You can query channels based on built-in fields as well as any custom field you add to channels.
Multiple filters can be combined using AND, OR logical operators, each filter can use its comparison (equality, inequality, greater than, greater or equal, etc.). You can find the complete list of supported operators in the query syntax section of the docs.
As an example, let's say that you want to query the last conversations I participated in sorted by `last_message_at`.
Heres an example of how you can query the list of channels:
```dart
final filter = Filter.in_('members', ['thierry']);
final sort = [SortOption("last_message_at", direction: SortOption.DESC)];
final channels = await client.queryChannels(
filter: filter,
sort: sort,
options: {
"watch": true,
"state": true,
},
);
channels.forEach((Channel c) {
print("${c.extraData['name']} ${c.cid}");
});
```
The query channels endpoint will only return channels that the user can read,
you should make sure that the query uses a filter that includes such logic.
For example: messaging channels are readable only to their members,
such requirement can be included in the query filter (see below).
@@ -1,71 +0,0 @@
---
id: querying_users
sidebar_position: 4
title: Querying Users
---
Querying Users Across Channels
The Query Users method allows you to search for users and see if they are online/offline.
The example below shows how you can retrieve the details for 3 users in one API call:
```dart
final _result = client.queryUsers(
filter: Filter.in_('id', ['john', 'jack', 'jessie']),
);
```
You can also add sort options and pagination to the query:
```dart
final _result = client.queryUsers(
filter: Filter.in_('id', ['john', 'jack', 'jessie']),
sort: [SortOption('last_active')],
pagination: PaginationParams(
offset: 0,
limit: 20,
),
);
```
You can filter and sort on the custom fields you've set for your user, the user id, and when the user was last active.
The options for the queryUser method are presence, limit, and offset.
If presence is true this makes sure you receive the user.presence.changed event when a user goes online or offline.
### Querying using the autocomplete operator
You can autocomplete the results of your user query by username and/or ID.
### By Custom Field
```dart
final _result = client.queryUsers(
filter: Filter.autoComplete('name', 'ro'),
);
```
This would return an array of any matching users, such as:
```json
[
{
"id": "userID",
"name": "Curiosity Rover"
},
{
"id": "userID2",
"name": "Roxy"
},
{
"id": "userID3",
"name": "Roxanne"
}
]
```
### By ID
```dart
final _result = client.queryUsers(
filter: Filter.autoComplete('id', 'USER_ID'),
);
```
@@ -1,52 +0,0 @@
---
id: reactions
sidebar_position: 18
title: Reactions
---
Adding And Removing User Reactions
Stream Chat has built-in support for user Reactions. Common examples are likes, comments, loves, etc. Reactions can be customized so that you are able to use any type of reaction your application requires.
Similar to other objects in Stream Chat, reactions allow you to add custom data to the reaction of your choice. This is helpful if you want to customize the reaction logic.
<b>Note:</b> Custom data for reactions is limited to 1KB.
```dart
await channel.sendReaction("messageID", "like", extraData: {"customField": 1});
```
### Removing a Reaction
```dart
await channel.deleteReaction("messageID", "like");
```
### Paginating Reactions
Messages returned by the APIs automatically include the 10 most recent reactions.
You can also retrieve more reactions and paginate using the following logic:
```dart
// get the first 10 reactions
await channel.getReactions("messageID", PaginationParams(limit: 10));
// get 3 reactions past the first 10
await channel.getReactions("messageID", PaginationParams(limit: 3, offset:10));
```
### Cumulative (Clap) Reactions
You can use the Reactions API to build something similar to Medium's clap reactions.
If you are not familiar with this, Medium allows you to clap articles more than once and shows the sum of all claps from all users.
To do this, you only need to include a score for the reaction (ie. user X clapped 25 times) and the API will return the sum of all reaction scores as well as each user individual scores (ie. clapped 475 times, user Y clapped 14 times).
```dart
// user claps 5 times on a message
await channel.sendReaction("messageID", "like", score: 5);
// same user claps 20 times more
await channel.sendReaction("messageID", "like", score: 25);
```
@@ -1,33 +0,0 @@
---
id: searching_messages
sidebar_position: 20
title: Searching Messages
---
Searching For Messages Across Channels
Message search is built-in to the chat API. You can enable and/or disable the search indexing on a per channel type.
The command shown below selects the channels in which John is a member.
Next, it searches the messages in those channels for the keyword “'supercalifragilisticexpialidocious'”:
```dart
final search = await client.search(
Filter.in_('members', ['john']),
query: 'supercalifragilisticexpialidocious',
paginationParams: PaginationParams(
limit: 2,
offset: 0
),
);
```
Pagination works via the standard limit and offset parameters. The first argument, filter, uses a MongoDB style query expression.
We do not run MongoDB on the backend, so only a subset of the standard MongoDB filters are supported.
Additionally, this endpoint can be used to search for messages that have attachments.
```dart
// Search file of type videos
final response = await channel.search(messageFilter: Filter.in_('attachments.type', ['video']));
return response;
```
@@ -1,7 +0,0 @@
---
id: setup
sidebar_position: 2
title: Setup
---
Understanding Setup
@@ -1,39 +0,0 @@
---
id: silent_messages
sidebar_position: 21
title: Silent Messages
---
Pushing Silent Messages
Sometimes you want to add system or transactional messages to channels such as: "your ride is waiting for you",
"James updated the information for the trip", "You and Jane are now matched" and so on.
You may not want these messages to mark a channel as unread or increase the unread messages for users.
Silent messages are special messages that don't increase the unread messages count nor mark a channel as unread.
Creating a silent message is very simple, you only need to include the silent field boolean field and set it to true.
```dart
final text = 'You completed your trip';
const message = {
text: text,
user: systemUser,
silent: true,
attachments: tripAttachments,
};
await channel.sendMessage(message);
```
<b>Notes: </b>
1. Existing messages cannot be turned into a silent message or vice versa.
2. Silent messages do send push notifications by default. To skip our push notification service,
mark the message with `skip_push: true`.
@@ -1,17 +0,0 @@
---
id: slow_mode
sidebar_position: 14
title: Slow Mode
---
Using Slow Mode For Reduced Message Traffic
Slow mode helps reduce noise on a channel by limiting users to a maximum of 1 message per cooldown interval.
The cooldown interval is configurable and can be anything between 1 and 120 seconds. For instance, if you enable slow mode and set the cooldown interval to 30 seconds a user will be able to post at most 1 message every 30 seconds.
Moderators, admins and server-side API calls are not restricted by the cooldown period and can post messages as usual.
Slow mode is disabled by default and can be enabled/disabled by admins and moderators.
<b>Note:</b> SLOW MODE is in the works for the Flutter SDK
@@ -1,56 +0,0 @@
---
id: threads_and_replies
sidebar_position: 19
title: Threads And Replies
---
Creating And Paginating Threads
Threads and replies provide your users with a way to go into more detail about a specific topic.
This can be very helpful to keep the conversation organized and reduce noise.
To create a thread you simply send a message with a `parent_id`. Have a look at the example below:
```dart
final reply = await channel.sendMessage(
Message(text: 'Hey, I am replying to a message!',
parentId: parentID,
showInChannel: false,
));
```
If you specify `show_in_channel`, the message will be visible both in a thread of replies as well as the main channel.
Messages inside a thread can also have reactions, attachments and mention as any other message.
### Thread Pagination
When you read a channel you do not receive messages inside threads.
The parent message includes the count of replies which it is usually what apps show as the link to the thread screen.
Reading a thread and paginating its messages works in a very similar way as paginating a channel.
```dart
// retrieve the first 20 messages inside the thread
await channel.getReplies(parentMessageId, PaginationParams(limit: 20));
// retrieve the 20 more messages before the message with id "42"
await channel.getReplies(parentMessageId, PaginationParams(limit: 20, lessThanOrEqual: '42'));
```
### Quote Message
Instead of replying in a thread, it's also possible to quote a message. Quoting a message doesn't result in the creation of a thread;
the message is quoted inline.
To quote a message, simply provide the `quoted_message_id` field when sending a message:
```dart
// Create the initial message
await channel.sendMessage(Message(id: 'first_message_id', text: 'The initial message' ));
// Quote the initial message
final res = await channel.sendMessage(Message(
id: 'message_with_quoted_message',
text: 'This is the first message that quotes another message',
quotedMessageId: 'first_message_id',
));
```
@@ -1,62 +0,0 @@
---
id: typing_indicators
sidebar_position: 24
title: Typing Indicators
---
Adding Typing Indicators To Your App
All official SDKs support typing events out of the box and are handled on all channels with the typing_events featured enabled.
Typing indicators allow you to show to users who is currently typing in the channel.
This feature can be switched on/off on a channel-type basis using the CLI or directly from the Dashboard.
If you are using one of the official SDK libraries, you will only need to ensure that typing indicators are enabled to get this working.
If you are building your UI on top of one of our Chat Clients instead, you will need to take care of four things:
Send an event `typing.start` when the user starts typing
Send an event `typing.stop` after the user stopped typing
Handle the two events and use them to toggle the typing indicator UI
Use `parent_id` field of the event to indicate that typing is happening in a thread
### Sending start and stop typing events
```dart
// The Dart client keeps track of the typing state for you.
// Just call `channel.keystroke()` when the user types and
// `channel.stopTyping()` when the user sends the message (or aborts)
// sends a typing.start event at most once every two seconds
await channel.keystroke();
// sends a typing.start event for a particular thread
await channel.keystroke(thread_id);
// sends the typing.stop event
await channel.stopTyping();
```
When sending events on user input, you should make sure to follow some best-practices to avoid bugs.
Only send typing.start when the user starts typing
Send typing.stop after a few seconds since the last keystroke
### Receiving typing indicator events
```dart
// channels keep track of the users that are currently typing
// the `channel.state.typingEvents` is an immutable object which gets regenerated
// every time a new user is added or removed to this list
print(channel.state.typingEvents);
// add typing start event handling
channel.on('typing.start', (event) => {
print('${event.user.name} started typing');
});
// add typing stop event handling
channel.on('typing.stop', event => {
print('${event.user.name} stopped typing');
});
```
Because clients might fail at sending `typing.stop` event all Chat clients periodically prune the list of typing users.
@@ -1,48 +0,0 @@
---
id: updating_channels
sidebar_position: 9
title: Updating Channels
---
Exploring Multiple Ways To Update A Channel
There are two ways to update a channel using the Stream API - a partial or full update.
A partial update will retain any custom key-value data, whereas a complete update is going to remove any that are unspecified in the API request.
### Partial Update
A partial update can be used to set and unset specific fields when it is necessary to retain additional custom data fields on the object.
AKA a patch style update.
```dart
// Here's a channel with some custom field data that might be useful
var channel = client.channel(type, id: id, extraData: {
"source": "user",
"source_detail" :{ "user_id": 123 },
"channel_detail" :{ "topic": "Plants and Animals", "rating": "pg" }
});
// let's change the source of this channel
await channel.updatePartial({ "set" :{ "source": "system" } });
// since it's system generated we no longer need source_detail
await channel.updatePartial({ "unset": ["source_detail"] });
// and finally update one of the nested fields in the channel_detail
await channel.updatePartial({ "set": { "channel_detail.topic": "Nature" } });
// and maybe we decide we no longer need a rating
await channel.updatePartial({ "unset": ["channel_detail.rating"] });
```
### Full Update (overwrite)
The update function updates all of the channel data.
<b>Any data that is present on the channel and not included in a full update will be deleted.</b>
```dart
await channel.update({
"name": "myspecialchannel",
"color": "green",
}, Message(text: "Thierry changed the channel color to green"));
```
@@ -1,103 +0,0 @@
---
id: uploading_files
sidebar_position: 17
title: Uploading Files
---
Uploading Files And Using A Custom CDN
The `channel.sendImage` and `channel.sendFile` methods make it easy to upload files.
This functionality defaults to using the Stream CDN. If you would like, you can easily change the logic to upload to your own CDN of choice.
The maximum file size is 20mb for the Stream Chat CDN.
```dart
final client = StreamChatClient('api-key');
var attachment = Attachment();
// Upload an image without monitoring send progress
client.sendImage(image, channelId, channelType).then((response) {
// Successful upload, you can now attach this image
// to an message that you then send to a channel
final imageUrl = response.file;
attachment = attachment.copyWith(
type: 'image',
imageUrl: imageUrl,
);
final message = Message(attachments: [attachment]);
client.sendMessage(message, channelId, channelType);
}).catchError((error, stk) {
// Handle error
});
// Upload an file, monitoring the progress with a onSendProgress callback
await client.sendFile(
file,
channelId,
channelType,
onSendProgress: (sent, total) {
// Handle the send progress
attachment = attachment.copyWith(
uploadState: UploadState.inProgress(
uploaded: sent,
total: total,
),
);
},
).then((response) {
// Successful upload, you can now attach this file
// to an message that you then send to a channel
final fileUrl = response.file;
attachment = attachment.copyWith(
type: 'file',
assetUrl: fileUrl,
uploadState: UploadState.success(),
);
final message = Message(attachments: [attachment]);
client.sendMessage(message, channelId, channelType);
}).catchError((error, stk) {
// Handle error
attachment = attachment.copyWith(
uploadState: UploadState.failed(error: error),
);
});
// Alternatively you can call the sendMessage directly on the channel
// which will automatically handle all the upload process of the provided
// attachments.
final channel = client.channel(channelType, id: channelId);
// Creating a message object with multiple local attachments
final message = Message(text: 'Hello', attachments: [
Attachment(
type: 'image',
file: AttachmentFile(path: 'imagePath/imageName.png'),
),
Attachment(
type: 'file',
file: AttachmentFile(path: 'filePath/fileName.pdf'),
),
]);
// Sending the message to the channel
await channel.sendMessage(message);
```
In the code example above, note how the message attachments are created after the files are uploaded. The React components support regular uploads, clipboard pasting, drag and drop, as well as URL enrichment via built-in open-graph scraping. As a bonus, the Stream CDN will automatically handle image resizing for you.
### Using Your Own CDN
All 5 SDKs make it easy to use your own CDN for uploads. The code examples below show how to change where files are uploaded:
```dart
// Set a custom FileUploader implementation when building your client
final client = StreamChatClient(
'api-key',
attachmentFileUploader: MyFileUploader(),
);
```
You'll have to create your own implementation of the `AttachmentFileUploader` interface,
and any upload calls will be sent to that implementation.
Take a look [at the interface](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat/lib/src/attachment_file_uploader.dart#L7)
and [our own default implementation of it](https://github.com/GetStream/stream-chat-flutter/blob/master/packages/stream_chat/lib/src/attachment_file_uploader.dart#L58) for more info.
@@ -1,94 +0,0 @@
---
id: user_presence
sidebar_position: 5
title: User Presence
---
Check If A User Is Online / Check Last Active
User presence allows you to show when a user was last active and if they are online right now.
Whenever you read a user the data will look like this:
```json
{
id: 'unique_user_id',
online: true,
status: 'Eating a veggie burger...',
last_active: '2019-01-07T13:17:42.375Z'
}
```
Notes:
1. The online field indicates if the user is online. The status field stores text indicating the current user status.
2. The last_active field is updated when a user connects and then refreshed every 15 minutes.
### Invisible
To mark a user invisible simply set the invisible property to true. You can also set a custom status message at the same time:
```dart
await client.connectUser(
User(
id: 'super-band-9',
extraData: {
'invisible': true,
},
),
'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoic3VwZXItYmFuZC05In0.0L6lGoeLwkz0aZRUcpZKsvaXtNEDHBcezVTZ0oPq40A',
);
```
Notes:
1. When invisible is set to true, the current user will appear as offline to other users.
### Listening to Presence Changes
Of course, you want to listen to the user presence changes. This allows you to show a user as offline when they leave and update their status in real time.
These 3 endpoints allow you to watch user presence:
```dart
// If you pass presence: true to channel.watch it will watch the list of user presence changes.
// Note that you can listen to at most 10 users using this API call
final channel = client.channel(
'messaging',
id: 'flutterdevs',
extraData: {
'name': 'Flutter devs',
},
);
await channel.watch({
'presence': true,
});
// queryChannels allows you to listen to the members of the channels that are returned
// so this does the same thing as above and listens to online status changes for john and jack
final filter = Filter.in_('members', ['john']);
final sort = [SortOption("last_message_at", direction: SortOption.DESC)];
final channels = await client.queryChannels(
filter: filter,
sort: sort,
options: {
'presence': true,
},
);
// queryUsers allows you to listen to user presence changes for john and jack
final result = await client.queryUsers(
filter: Filter.in_('id', ['john', 'jack', 'jessie']),
sort: [SortOption('last_active')],
pagination: PaginationParams(
offset: 0,
limit: 20,
),
options: {
'presence': true,
},
);
```
@@ -1,7 +0,0 @@
---
id: user_types
sidebar_position: 3
title: User Types
---
Diving Into User Types
@@ -1,116 +0,0 @@
---
id: watching_channels
sidebar_position: 8
title: Watching Channels
---
More About Watching A Channel
The call to channel.watch does a few different things in one API call:
* It creates the channel if it doesn't exist yet (if this user has the right permissions to create a channel)
* It queries the channel state and returns members, watchers and messages
* It watches the channel state and tells the server that you want to receive events when anything in this channel changes
* To start watching a channel
The examples below show how to watch a channel. Note that you need to be connected as a user before you can watch a channel.
```dart
final state = await channel.watch();
```
### Watchers vs Members
The concepts of watchers vs members can require a bit of clarification:
* <b>Members</b>: a permanent association between a user and a channel. If the user is online and not watching the channel they will receive a notification event, if they are offline they will receive a push notification.
* <b>Watchers</b>: the list of watchers is temporary. It's anyone who is currently watching the channel.
Being able to send messages, and otherwise engage with a channel as a non-member requires certain permissions.
For example, we have pre-configured permissions on our livestream channel type to allow non-members to interact,
but in the messaging channel type, only members of the channel can interact.
### Watching Multiple Channels
The default queryChannels API returns channels and starts watching them.
There is no need to also use channel.watch on the channels returned from queryChannels
```dart
// first lets create a filter to make messaging channels that include a specific user
final filter = Filter.in_('members', [user_id]);
// we can also define a sort order of most recent messages first
final sort = [SortOption("last_message_at", direction: SortOption.DESC)];
// finally, we can query for those channels, automatically watching them for the
// currently connected user
final channels = await client.queryChannels(
filter: filter,
sort: sort,
options: {
"watch": true,
"state": true,
},
);
```
### Stop Watching a Channel
To stop receiving channel events:
```dart
// we can also stop watching a channel
final stopWatching = await channel.stopWatching();
```
### Watcher Count
To get the watcher count of a channel:
```dart
// create a new channel of type “livestream” with name “watch-this-channel”
final channel = client.channel("livestream", id: "watch-this-channel");
// retrieve our channels
channel.query();
// each channel object has a state collection with a watcher_count property
return channel.state.watcherCount;
```
### Paginating Channel Watchers with channel.query
```dart
// create a new channel of type “livestream” with name “watch-this-channel”
final channel = client.channel("livestream", id: "watch-this-channel");
// now query the newly created channel for watchers, retrieving the first 5
final result = await channel.query(
watchersPagination: PaginationParams(
limit: 5,
offset: 0,
),
);
return result.watchers;
```
### Listening to Changes in Watchers
A user already watching the channel can listen to users starting and stopping watching the channel with the realtime events:
```dart
final channel = client.channel("livestream", id: "watch-this-channel");
await channel.watch();
// handle watch started event
channel
.on("user.watching.start")
.listen((event) => print('${event.user.id} started watching'));
// handle watch stopped event
channel
.on("user.watching.stop")
.listen((event) => print('${event.user.id} stopped watching'));
```