From 7b4fd8910e06b97c19b960049e78d0caf9316500 Mon Sep 17 00:00:00 2001 From: Deven Joshi Date: Thu, 17 Jun 2021 15:35:28 +0530 Subject: [PATCH] feat: Added new docs --- .../docs/Flutter/stream_chat/events.mdx | 78 ++++++++++++ .../Flutter/stream_chat/moderation_tools.mdx | 112 ++++++++++++++++++ .../Flutter/stream_chat/pinned_messages.mdx | 58 +++++++++ .../Flutter/stream_chat/silent_messages.mdx | 31 +++++ .../Flutter/stream_chat/typing_indicators.mdx | 54 +++++++++ 5 files changed, 333 insertions(+) diff --git a/docusaurus/docs/Flutter/stream_chat/events.mdx b/docusaurus/docs/Flutter/stream_chat/events.mdx index e171b295..fb32233f 100644 --- a/docusaurus/docs/Flutter/stream_chat/events.mdx +++ b/docusaurus/docs/Flutter/stream_chat/events.mdx @@ -4,3 +4,81 @@ sidebar_position: 25 title: 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 you’ll 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!', + }, + ), +); +``` \ No newline at end of file diff --git a/docusaurus/docs/Flutter/stream_chat/moderation_tools.mdx b/docusaurus/docs/Flutter/stream_chat/moderation_tools.mdx index 7eb14af2..b7af0413 100644 --- a/docusaurus/docs/Flutter/stream_chat/moderation_tools.mdx +++ b/docusaurus/docs/Flutter/stream_chat/moderation_tools.mdx @@ -4,3 +4,115 @@ sidebar_position: 23 title: Moderation Tools --- +### 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). \ No newline at end of file diff --git a/docusaurus/docs/Flutter/stream_chat/pinned_messages.mdx b/docusaurus/docs/Flutter/stream_chat/pinned_messages.mdx index fba0ca07..7de1d999 100644 --- a/docusaurus/docs/Flutter/stream_chat/pinned_messages.mdx +++ b/docusaurus/docs/Flutter/stream_chat/pinned_messages.mdx @@ -4,3 +4,61 @@ sidebar_position: 22 title: Pinned Messages --- +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), +); +``` \ No newline at end of file diff --git a/docusaurus/docs/Flutter/stream_chat/silent_messages.mdx b/docusaurus/docs/Flutter/stream_chat/silent_messages.mdx index c2bb2172..52d05b2b 100644 --- a/docusaurus/docs/Flutter/stream_chat/silent_messages.mdx +++ b/docusaurus/docs/Flutter/stream_chat/silent_messages.mdx @@ -4,3 +4,34 @@ sidebar_position: 21 title: 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); +``` + +Notes: + +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`. \ No newline at end of file diff --git a/docusaurus/docs/Flutter/stream_chat/typing_indicators.mdx b/docusaurus/docs/Flutter/stream_chat/typing_indicators.mdx index 908854db..8323e46a 100644 --- a/docusaurus/docs/Flutter/stream_chat/typing_indicators.mdx +++ b/docusaurus/docs/Flutter/stream_chat/typing_indicators.mdx @@ -4,3 +4,57 @@ sidebar_position: 24 title: Typing Indicators --- +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. \ No newline at end of file