Home
/
Chat
/
Flutter

Open channel

An open channel is a Twitch-style public chat where users can easily join without permission. Sendbird Chat SDK now supports two operation systems for open channels, which are classic and dynamic partitioning. These two systems offer the same features and functions, except that dynamic partitioning allows open channels to accommodate a massive number of users.


Classic vs. Dynamic partitioning

Classic open channels are the original open channels Sendbird has been providing, and a single classic open channel can handle up to 1,000 participants.

Note: Sendbird applications created before December 15, 2020, are using classic open channels.

On the other hand, dynamic partitioning open channels are designed to accommodate an even larger number of users using a set number of subchannels, starting from 2,000 to 60,000 participants. This new system, called dynamic partitioning, enables flexible scaling of open channels by creating or merging subchannels within the open channels and evenly allocating participants among the subchannels while providing a seamless and well-paced chat experience to all users.

Note: The classic open channels will be deprecated at the end of March 2021 but the classic channels created before the deprecation will remain and function the same way. Meanwhile, all Chat SDK users will be automatically migrated to the new dynamic partitioning system when the deprecation takes place. If you wish to convert to dynamic partitioning open channels beforehand, contact our support team.

Learn more about how dynamic partitioning open channel operates in the Open channel guide of Platform API.


Create a channel

An open channel is ideal for use cases that require a small and static number of channels. To create an open channel from the Sendbird Dashboard, do the following:

  1. In your dashboard, go to the Chat > Open channels, and then click Create channel at the top-right corner.
  2. In the dialog box that appears, specify the name, unique URL, cover image, and custom type of a channel.

You can also create a channel on demand or dynamically through the Chat SDK or the Chat Platform API.

Light Color Skin
Copy
try{
    final params = OpenChannelParams()
        ..name = NAME
        ..data = DATA
        ..operatorUserIds = OPERATOR_USER_IDS
        ..coverImage = FileInfo.fromURL(url: COVER_URL);    // `coverImage` can also take image files.

    final channel = openChannel.createChannel(params: params);
    // An open channel is successfully created.
    // Through the `openChannel` parameter of the callback method, you can get the open channel's data from the result object that Sendbird server has passed.
} catch (e) {
    // Handle error.
}

Otherwise, you can create an open channel by configuring an OpenChannelParams object like the following.

Light Color Skin
Copy
try {
    final params = OpenChannelParams()
        ..operatorUserIds = ['Jeff']    // You can list more 'OPERATOR_USER_IDS' to register users as channel operators.
        ..name = NAME
        ..channelUrl = UNIQUE_CHANNEL_URL
        // In an open channel, you can create a new channel by specifying its unique channel URL.
        ..coverImage = FileInfo.fromData(data: COVER_IMAGE, name: NAME, mimeType: 'image/jpeg')
        // `coverImage` can also take image URLs.
        ..data = DATA
        ..customType = CUSTOM_TYPE;

    final channel = await OpenChannel.createChannel(params: params);
    // An open channel with detailed configuration is successfully created.
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

NAME

Type: String
Specifies the channel topic, or the name of the channel.

UNIQUE_CHANNEL_URL

Type: String
Specifies a unique channel URL given when a new open channel is created.

DATA

Type: String
Specifies additional channel information such as a long description of the channel or JSON formatted string.

OPERATOR_USER_IDS

Type: List<String>
Specifies an array of one or more users to register as operators of the channel. Operators can delete any messages, and also view all messages in the channel without any filtering or throttling.

CUSTOM_TYPE

Type: String
Specifies the custom channel type which is used for channel grouping.

Note: See the Advanced section for more information on cover images and custom types.


Enter a channel

A user must enter an open channel to receive messages. The user can enter up to 10 open channels at once, which are valid only within a current connection. When a user is disconnected from Sendbird server with disconnect() method and reconnected to the server with connect(), you should make sure the user re-enters the open channels for them to continue receiving messages.

When a user who is already a participant in an open channel moves the app to the background, the user will be disconnected from Sendbird server. But when the user's app returns to the foreground, the Chat SDK will automatically re-enter the user to the particpating channel.

Note: When a user is reconnected by attempts of the SendbirdSdk instance from a temporary unstable connection, the Chat SDK will automatically re-enter the user to the participating channel.

Light Color Skin
Copy
try {
    final channel = await OpenChannel.getChannel(CHANNEL_URL);
    await channel.enter();
    // The current user successfully enters the open channel.
} catch (e) {
    // Handle error.
}

Exit a channel

If a user exits an open channel, the user can't receive any messages from that channel.

Light Color Skin
Copy
try {
    final channel = await OpenChannel.getChannel(CHANNEL_URL);
    await channel.exit();
    // The current user successfully exits the open channel.
} catch (e) {
    // Handle error.
}

Delete a channel

Only the operators of an open channel can delete the channel and the following code only works in the operators' client apps. Otherwise, an error will be thrown, which should be handled through the try and catch blocks.

Light Color Skin
Copy
try {
    await openChannel.deleteChannel();
    // The channel is successfully deleted.
} catch (e) {
    // Handle error.
}

Freeze and unfreeze a channel

An open channel can be freezed only with the Sendbird Dashboard or Chat Platfrom API as opposed to a group channel which operators of the channel can do that through the Chat SDK.

To freeze, go to your dashboard and do the following: on the Chat > Open channels, select an open channel to freeze, and click the Freeze icon at the upper right corner. To unfreeze, click the icon again with the frozen channel selected.

Note: In a frozen channel, participants can't chat with each other but the operators can send a message to the channel.


Retrieve a list of channels

You can retrive a list of open channels by using the OpenChannelListQuery's loadNext() method, which returns a list of OpenChannel objects.

Light Color Skin
Copy
try {
    final listQuery = OpenChannelListQuery()
        ..channelUrl = channel.channelUrl;

    final result = await listQuery.loadNext();
    // A list of open channels is successfully retrieved.
    // Through the `openChannel` parameter of the callback method, you can access the data
    // of each open channel from the result list that Sendbird server has passed.
} catch (e) {
    // Handle error.
}

Retrieve a channel by URL

Since a channel URL is a unique identifier of an open channel, you can use a URL when retrieving a channel object.

Light Color Skin
Copy
try {
    final channel = await OpenChannel.getChannel(CHANNEL_URL);
    // Through the `openChannel` parameter of the callback method, Sendbird server returns
    // the open channel object identified with the `CHANNEL_URL`.
    // You can also get the open channel's data from the result object.
} catch (e) {
    // Handle error.
}

Note: We recommend that you store a user's channel URLs to handle the lifecycle or state changes of your app, or any other unexpected situations. For example, when a user is disconnected from Sendbird server due to switching to another app temporarily, you can provide a smooth restoration of the user's state using a stored URL to fetch the appropriate channel instance.


Send a message

To an entered open channel, a user can send messages of the following types:

Message typeDescription

UserMessage

A text message sent by a user

FileMessage

A binary file message sent by a user

In addition to these message types, you can further subclassify a message by specifying its custom type. This custom type takes on the form of a String and can be used to search or filter messages. It allows you to append information to your message and customize message categorization.

The following code shows several types of parameters that you can configure to customize text messages by using UserMessageParams. Under the UserMessageParams object, you can assign specific values to message, data and other properties. By assigning arbitrary string to the data property, you can set custom font size, font type or JSON object. To send your messages, you need to pass the UserMessageParams object as an argument to the parameter in the sendUserMessage() method.

Through the onCompleted callback of the sendUserMessage() method, Sendbird server always notifies whether your message has been successfully sent to the channel. When there is a delivery failure due to network issues, an exception is returned through the callback method.

Light Color Skin
Copy
final params = UserMessageParams()
    ..message = MESSAGE
    ..customType = CUSTOM_TYPE
    ..data = DATA
    ..mentionType = MentionType.users   // This could be either `MentionType.users` or `MentionType.channel`.
    ..mentionedUserIds = ['Jeff', 'Julia']
    ..metaArrays = [
        MessageMetaArray(key: 'itemType', value: ['tablet']),
        MessageMetaArray(key: 'quality', value: ['best', 'good'])
    ]
    ..targetLanguages = ['fr', 'de']    // French and German, respectively.
    ..pushOption = PushNotificationDeliveryOption.normal;   // Acceptable values are `normal`, which is the default, and `suppress`.

try {
    final preMessage = openChannel.sendUserMessage(params: params, onCompleted: (message, error) {
        If (error != null) {
            // Handle error.
        } else {
            // A text message with detailed configuration is successfully sent to the channel.
            // By using `userMesage.messageId`, `userMessage.message` or `userMessage.customType`,
            // you can access the result object from Sendbird server to check your `UserMessageParams` configuration.
            // The current user can receive messages from other users through the `onMessageReceived()` method of an event handler.
        }
    });
} catch (e) {
    // Handle error.
}

A user can also send binary files through the Chat SDK. The two ways to send a binary file are: sending the file itself, or sending a URL.

Sending a raw file means you're uploading it to Sendbird server where it can be downloaded in client apps. When you upload a file directly to the server, there is a size limit imposed on the file depending on your plan. You can see the limit in the Sendbird Dashboard and adjust it with our sales team.

The other option is to send a file hosted on your server. You can pass the file's URL, which represents its location, as an argument to a parameter. In this case, your file is not hosted on Sendbird server and it can only be downloaded from your own server. When you send a file message with a URL, there is no limit on the file size since it's not directly uploaded to Sendbird server.

The following code shows several types of parameters that you can configure to customize file messages by using FileMessageParams. Under the FileMessageParams object, you can assign specific values to customType and other properties. To send your messages, you need to pass the FileMessageParams object as an argument to the parameter in the sendFileMessage() method.

Through the onCompleted callback of the sendFileMessage() method, Sendbird server always notifies whether your message has been successfully sent to the channel. When there is a delivery failure due to network issues, an exception is returned through the callback method.

Light Color Skin
Copy
try {
    // Sending a file message with a raw file
    final params = FileMessageParams()
        ..uploadFile = FileInfo.fromData(
            data: FILE,
            name: FILE_NAME,
            size: FILE_SIZE,
            mimeType: MIME_TYPE
        )
        ..thumbnailSizes =  [Size(100, 100), Size(40, 40)];
        ..customType = CUSTOM_TYPE
        ..mentionType = MentionType.users       // This could be either `MentionType.users` or `MentionType.channel`.
        ..mentionedUserIds = ['Jeff', 'Julia']
        ..pushOption = PushNotificationDeliveryOption.normal;
        // Acceptable values are `normal`, which is the default, and `suppress`.

    final preMessage = await openChannel.sendFileMessage(params: params, onCompleted: (message, error) {
        If (error != null) {
            // Handle error.
        }
        // A file message with detailed configuration is successfully sent to the channel.
        // By using `fileMesage.messageId`, `fileMessage.fileName` or `fileMessage.customType`,
        // you can access the result object from Sendbird server to check your `FileMessageParams` configuration.
        // The current user can receive messages from other users through the `onMessageReceived()` method of an channel event handler.
    });
} catch (e) {
    // Handle error.
}

Receive messages through a channel event handler

Messages sent from other participants can be received through the onMessageReceived() method in the channel event handler, which can be used as a mixin. A BaseMessage object for each received message is one of the following three message types.

Message typeDescription

UserMessage

A text message sent by a user

FileMessage

A binary file message sent by a user

AdminMessage

A text message sent by an admin through the Chat Platform API

The UNIQUE_HANDLER_ID is a unique identifier to register multiple concurrent handlers.

Light Color Skin
Copy
class MyClass with ChannelEventHandler {
    // Add this class through sendbird.addChannelEventHandler(UNIQUE_HANDLER_ID, this).
    // Or remove it through sendbird.removeChannelEventHandler(UNIQUE_HANDLER_ID) when it's no longer needed.

    
    void onMessageReceived(BaseChannel channel, BaseMessage message) {
        // You can customize how to display different types of messages with the result object in the `message` parameter.
        if (message is UserMessage) {

        }
        else if (message is FileMessage {

        }
        else if (message is AdminMessage {

        }
    }
}

If the UI is no longer valid, remove the channel event handler.

Light Color Skin
Copy
sendbird.removeChannelEventHandler(UNIQUE_HANDLER_ID);

Reply to a message

Users can reply to a specific message in a channel through either the sendUserMessage() or sendFileMessage() method. To do so, create a UserMessageParams or a FileMessageParams object and specify the parentMessageId property of the object. Sending reply messages works the same way as sending regular messages to a channel except replies have an additional parentMessageId property.

Reply with a text message

When replying to a message through the sendUserMessage() method, specify and pass a UserMessageParams object as an argument to the parameter in the method.

Light Color Skin
Copy
// Create a `UserMessageParams` object.
final params = UserMessageParams()
    ..message = MESSAGE_TEXT
    ..parentMessageId = PARENT_MESSAGE_ID;

// Pass the params to the parameter in the `sendUserMessage()` method.
try {
    final preMessage = openChannel.sendUserMessage(params: params, onCompleted:(message, error) {
        // A reply to a specific message in the form of a text message is successfully sent if error is null.
    });
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

PARENT_MESSAGE_ID

Type: int
Specifies the unique ID of a parent message. A parent message is a message that has a thread of replies. If the message sent through the sendUserMessage() method is a parent message, the value of this property is 0. If the message is a reply to a parent message, the value is the message ID of the parent message.

Reply with a file message

When replying with a file message through the sendFileMessage() method, specify and pass a FileMessageParams object as an argument to the parameter in the method.

Light Color Skin
Copy
// Create a `FileMessageParams` object.
final params = FileMessageParams.fromData(data: FILE)
    ..parentMessageId = PARENT_MESSAGE_ID;

// Pass the params to the parameter in the `sendFileMessage()` method.
try {
    final preMessage = openChannel.sendFileMessage(params: params, onCompleted:(message, error) {
        // A reply to a specific message in the form of a file message is successfully sent if error is null.
    });
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

PARENT_MESSAGE_ID

Type: int
Specifies the unique ID of a parent message. A parent message is a message that has a thread of replies. If the message sent through the sendFileMessage() method is a parent message, the value of this property is 0. If the message is a reply to a parent message, the value is the message ID of the parent message.


Mention other participants in a message

When a participant wants to call the attention of other participants in an open channel where push notifications are not allowed by default, they can mention those participants in a message. To do so, you should:

  1. Specify a list of the user IDs to mention.
  2. Add the list to either UserMessageParams or FileMessageParams, which may contain options for further action.
  3. Pass the params to either sendUserMessage() or sendFileMessage().
  4. Then only up to 10 participants mentioned in the message will be notified.
Light Color Skin
Copy
try {
    final userIDsToMention = ['Harry', 'Jay', 'Jin'];   // Only the mentioned users in the list will receive the message.
    final params = UserMessageParams()
        ..message = MESSAGE
        ..mentionedUserIds = userIDsToMention;

    final preMessage = openChannel.sendUserMessage(params: params, onCompleted:(message, error) {
        // A message has been sent successfully if error is null.
    });
} catch (e) {
    // Handle error.
}

Load previous messages

Using the loadNext() method of a PreviousMessageListQuery instance which returns a list of BaseMessage objects, you can retrieve a set number of previous messages in an open channel. With a returned list, you can display the past messages in your UI once they have loaded.

Light Color Skin
Copy
// There should be only one single instance per channel.
try {
    final listQuery = PreviousMessageListQuery()
        ..channelType = channel.channelType
        ..channelUrl = channel.channelUrl
        ..limit = LIMIT
        ..reverse = REVERSE;
        ..includeReplies = INCLUDE_REPLIES
        ..includeThreadInfo = INCLUDE_THREAD_INFO
        ..includeParentMessageText = INCLUDE_PARENT_MESSAGE_TEXT;

    final result = await listQuery.loadNext();
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

LIMIT

Type: int
Specifies the number of results to return per call. Acceptable values are 1 to 100, inclusive. The recommended value for this parameter is 30.

REVERSE

Type: bool
Determines whether to sort the retrieved messages in reverse order. If true, returns a list of messages which the latest comes at first and the earliest at last. the results are sorted in reverse order. If false, returns a list of messages which the earliest comes at first and the latest at last.

INCLUDE_REPLIES

Type: bool
Determines whether to include replies in the results.

INCLUDE_THREAD_INFO

Type: bool
Determines whether to include the thread information of the messages in the results when the results contain parent messages.

INCLUDE_PARENT_MESSAGE_TEXT

Type: bool
Determines whether to include the parent message text in the results when the retrieved messages are replies in a thread. If the type of the parent message is UserMessage, the value is a message property. If it is a FileMessage, the value is the name of the uploaded file.

A limit parameter determines how many messages should be included in a returned list. A PreviousMessageListQuery instance itself does pagination of a result set based on the value of the limit parameter, and internally manages a token to retrieve the next page in the result set.

Each time the loadNext() method is called, the instance retrieves a set number of messages in the next page and then updates the value of the token to complete the current call and prepare a next call.

If you create a new query instance and call the loadNext() method, a set number of the most recent messages are retrieved because its token has nothing to do with the previously created instance. So we recommend that you create a single query instance and store it as a member variable for traversing through the entire message history.

Note: Before calling the loadNext() method again, the previous call should have been completed.


Load messages by timestamp or message ID

Using the getMessagesByTimestamp() method, you can retrieve a set number of previous and next messages on both sides of a specific timestamp in an open channel.

The following code shows several types of parameters that you can configure to customize a message query by using MessageListParams. Under the MessageListParams object, you can assign values to previousResultSize, messageType, customType, and other properties. To retrieve messages in a channel, you need to pass the MessageListParams object as an argument to the parameter in the getMessagesByTimestamp() method.

Light Color Skin
Copy
try {
    final params = MessageListParams()
        ..isInclusive = IS_INCLUSIVE
        ..previousResultSize = PREVIOUS_RESULT_SIZE
        ..nextResultSize = NEXT_RESULT_SIZE
        ..reverse = REVERSE
        ..messageType = MESSAGE_TYPE    // The default value is `MessageTypeFilter.all`.
        ..customType = CUSTOM_TYPE
        ..includeReplies = INCLUDE_REPLIES
        ..includeThreadInfo = INCLUDE_THREAD_INFO
        ..includeParentMessageText = INCLUDE_PARENT_MESSAGE_TEXT;

    final result = await channel.getMessagesByTimestamp(
        TIMESTAMP,
        params,
    );
    // The result includes replies.
} catch (e) {
    // Handle error.
})

List of arguments

ArgumentDescription

IS_INCLUSIVE

Type: bool
Determines whether to include the messages with the matching timestamp or message ID in the results.

PREVIOUS_RESULT_SIZE

Type: int
Specifies the number of messages to retrieve that were sent before the specified timestamp or message ID.

NEXT_RESULT_SIZE

Type: int
Specifies the number of messages to retrieve that were sent after the specified timestamp or message ID.

REVERSE

Type: bool
Determines whether to sort the retrieved messages in reverse order. If false, the results are in ascending order.

MESSAGE_TYPE

Type: MessageTypeFilter
Specifies the message type to filter the messages with the corresponding type. Acceptable values are MessageTypeFilter.all, MessageTypeFilter.user, MessageTypeFilter.file and MessageTypeFilter.admin. (Default: MessageTypeFilter.all)

CUSTOM_TYPE

Type: String
Specifies the custom type of messages to retrieve.

INCLUDE_REPLIES

Type: bool
Determines whether to include replies in the results.

INCLUDE_THREAD_INFO

Type: bool
Determines whether to include the thread information of the messages in the results when the results contain parent messages.

INCLUDE_PARENT_MESSAGE_TEXT

Type: bool
Determines whether to include the parent message text in the results when the messages are replies in a thread. If the type of the parent message is UserMessage, the value is a message property. If it is FileMessage, the value is the name of the uploaded file.


List messages along with their replies

The PreviousMessageListQuery's loadNext() method, the getMessagesByTimestamp() method or the getMessagesById() method can be used to retrieve messages and their replies in a specific thread.

Load channel messages

The loadNext() method of the PreviousMessageListQuery instance returns a list of BaseMessage objects. With this method, you can retrieve previous messages in a specific channel.

To include the replies of the target messages in the results, change the value of the includeReplies property set to true.

Light Color Skin
Copy
try {
    final listQuery = PreviousMessageListQuery()
        ..channelType = ChannelType.open
        ..channelUrl = CHANNEL_URL
        ..limit = LIMIT
        ..reverse = REVERSE
        ..includeReplies = INCLUDE_REPLIES
        ..includeThreadInfo = INCLUDE_THREAD_INFO
        ..includeParentMessageText = INCLUDE_PARENT_MESSAGE_TEXT;

    final messages = await listQuery.loadNext();
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

CHANNEL_URL

Type: String
Specifies the URL of the channel to retrieve previous messages.

LIMIT

Type: int
Specifies the number of results to return per call. Acceptable values are 1 to 100, inclusive. The recommended value for this parameter is 30.

REVERSE

Type: bool
Determines whether to sort the retrieved messages in reverse order. If false, the results are in ascending order.

INCLUDE_REPLIES

Type: bool
Determines whether to include replies in the results.

INCLUDE_THREAD_INFO

Type: bool
Determines whether to include the thread information of the messages in the results when the results contain parent messages.

INCLUDE_PARENT_MESSAGE_TEXT

Type: bool
Determines whether to include the parent message text in the results when the retrieved messages are replies in a thread. If the type of the parent message is UserMessage, the value is a messageproperty. If it is a FileMessage, the value is the name of the uploaded file.

Load messages by timestamp or message ID

The getMessagesByTimestamp() and getMessagesById() methods of a BaseChannel instance return a list of BaseMessage objects.

When using either of the methods above, you can also pass a MessageListParams object as an argument to the parameter in those methods.

Light Color Skin
Copy
final params = MessageListParams()
    ..previousResultSize = PREV_RESULT_SIZE
    ..nextResultSize = NEXT_RESULT_SIZE
    ..isInclusive = INCLUSIVE
    ..reverse = REVERSE
    ..messageType = MESSAGE_TYPE    // The default value is `MessageTypeFilter.all`.
    ..customType = CUSTOM_TYPE
    ..includeReplies = INCLUDE_REPLIES
    ..includeThreadInfo = INCLUDE_THREAD_INFO
    ..includeParentMessageText = INCLUDE_PARENT_MESSAGE_TEXT;

List of parameters

Parameter nameDescription

previousResultSize

Type: int
Specifies the number of messages to retrieve that were sent before the specified timestamp or message ID.

nextResultSize

Type: int
Specifies the number of messages to retrieve that were sent after the specified timestamp or message ID.

isInclusive

Type: bool
Determines whether to include the messages with the matching timestamp or message ID in the results.

reverse

Type: bool
Determines whether to sort the retrieved messages in reverse order. If false, the results are in ascending order.

messageType

Type: MessageTypeFilter
Specifies the message type to filter the messages with the corresponding type. Acceptable values are MessageTypeFilter.all, MessageTypeFilter.user, MessageTypeFilter.file and MessageTypeFilter.admin. (Default: MessageTypeFilter.all)

customType

Type: String
Specifies the custom type of messages to retrieve.

includeReplies

Type: bool
Determines whether to include replies in the results.

includeThreadInfo

Type: bool
Determines whether to include the thread information of the messages in the results when the results contain parent messages.

includeParentMessageText

Type: bool
Determines whether to include the parent message text in the results when the messages are replies in a thread. If the type of the parent message is UserMessage, the value is a message property. If it is FileMessage, the value is the name of the uploaded file.

By timestamp

The getMessagesByTimestamp() method returns a set number of messages of previous and next messages on both sides of a specific timestamp in a channel.

Light Color Skin
Copy
try {
    final messages = await openChannel.getMessagesByTimestamp(TIMESTAMP, params);
    // A list of previous and next messages on both sides of a specified timestamp is successfully retrieved.
    // You can access and display the data of each message.
} catch (e) {
    // Handle error
}

List of arguments

ArgumentDescription

TIMESTAMP

Type: int
Specifies the timestamp to be the reference point for messages to retrieve, in Unix milliseconds format. Messages sent before or after the timestamp can be retrieved.

By message ID

The getMessagesById() method returns a set number of previous and next messages on both sides of a specific message ID in a channel.

Light Color Skin
Copy
try {
    final messages = await openChannel.getMessagesById(MESSAGE_ID, params);
    // A list of previous and next messages on both sides of a specified timestamp is successfully retrieved.
    // You can access and display the data of each message.
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

MESSAGE_ID

Type: int
Specifies the message ID to be the reference point for messages to retrieve. Messages sent before or after the message with the matching message ID can be retrieved.


List replies of a parent message

With the timestamp of the parent message, you can retrieve a single message with its replies by creating and passing a ThreadedMessageListParams object into the getThreadedMessagesByTimestamp() method as an argument.

Light Color Skin
Copy
// Create a `ThreadedMessageListParams` object.
final params = ThreadedMessageListParams()
    ..previousResultSize = PREV_RESULT_SIZE
    ..nextResultSize = NEXT_RESULT_SIZE
    ..isInclusive = INCLUSIVE
    ..reverse = REVERSE
    ..includeParentMessageText = INCLUDE_PARENT_MESSAGE_TEXT;

// Pass the params to the parameter in the `getThreadedMessagesByTimestamp()` method.
try {
    final threadResponse = await parentMessage.getThreadedMessagesbyTimestamp(TIMESTAMP, params);
    // A list of replies of the specified parent message timestamp is successfully retrieved.
    // You can access and display the data of each message.
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

TIMESTAMP

Type: int
Specifies the timestamp to be the reference point of the retrieval, in Unix milliseconds format.

PREV_RESULT_SIZE

Type: int
Specifies the number of messages to retrieve that were sent before the specified timestamp.

NEXT_RESULT_SIZE

Type: int
Specifies the number of messages to retrieve that were sent after the specified timestamp.

INCLUSIVE

Type: bool
Determines whether to include the messages with the matching timestamp in the results.

REVERSE

Type: bool
Determines whether to sort the retrieved messages in reverse order. If false, the results are in ascending order.

INCLUDE_PARENT_MESSAGE_TEXT

Type: bool
Determines whether to include the parent message text in the results when the messages are replies in a thread. If the type of the parent message is UserMessage, the value is a message property. If it is FileMessage, the value is the name of the uploaded file.


Retrieve a message

You can retrieve a specific message by creating and passing the MessageRetrievalParams object as an argument into the getMessage() method.

Light Color Skin
Copy
try {
    // Create a `MessageRetrievalParams` object.
    final params = MessageRetrievalParams()
        ..messageId = MESSAGE_ID
        ..channelType = ChannelType.open
        ..channelUrl = CHANNEL_URL;

    // Pass the params to the parameter of the `getMessage()` method.
    final message = await BaseMessage.getMessage(params);
    // The specified message is successfully retrieved.
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

MESSAGE_ID

Type: int
Specifies the unique ID of the message to retrieve.

CHANNEL_URL

Type: String
Specifies the URL of the channel to retrieve the message.


Update a message

A user can update any of their own sent text and file messages. An error is returned if a user attempts to update another user's messages. In addition, channel operators can update any messages sent in the channel.

Light Color Skin
Copy
try {
    // For a text message
    final params = UserMessageParams()
        ..message = NEW_TEXT_MESSAGE
        ..customType = NEW_CUSTOM_TYPE
        ..data = NEW_DATA;

    final message = await openChannel.updateUserMessage(USER_MESSAGE_ID, params);
    // The message is successfully updated.
    // You can check if the update operation has been performed correctly.
} catch (e) {
    // Handle error.
}

try {
    // For a file message
    final params = FileMessageParams
        .fromUrl(
            NEW_FILE_URL,
            mimeType: 'image/jpeg',
            name: NEW_FILE_NAME,
            size: NEW_FILE_SIZE
        )
        ..customType = NEW_CUSTOM_TYPE;

    final message = await openChannel.updateFileMessage(FILE_MESSAGE_ID, params);
    // The message is successfully updated.
    // You can check if the update operation has been performed correctly.
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

USER_MESSAGE_ID

Type: int
Specifies the unique ID of the text message to update.

FILE_MESSAGE_ID

Type: int
Specifies the unique ID of the file message to update.

If a message is updated, the onMessageUpdated() method in the channel event handler will be invoked on all channel participants' devices except the one that updated the message.

Light Color Skin
Copy
class MyClass with ChannelEventHandler {
    // Add this class through sendbird.addChannelEventHandler(UNIQUE_HANDLER_ID, this).
    // Or remove it through sendbird.removeChannelEventHandler(UNIQUE_HANDLER_ID) when it's no longer needed.
    
    void onMessageUpdated(BaseChannel channel, BaseMessage message) {

    }
}

Delete a message

A user can delete any messages sent by themselves. An error is returned if a user attempts to delete the messages of other participants. Also operators of an open channel can delete any messages in a channel.

Light Color Skin
Copy
// The `MESSAGE_ID` below indicates a `BaseMessage` object’s `messageId` to delete.
try {
    await openChannel.deleteMessage(MESSAGE_ID);
    // The message is successfully deleted from the channel.
} catch (e) {
    // Handle error.
}

If a message is deleted, the onMessageDeleted() method in the channel event handler will be invoked on all channel participants' devices including the one that deleted the message.

Light Color Skin
Copy
class MyClass with ChannelEventHandler {
    // Add this class through sendbird.addChannelEventHandler(UNIQUE_HANDLER_ID, this).
    // Or remove it through sendbird.removeChannelEventHandler(UNIQUE_HANDLER_ID) when it's no longer needed.
    
    void onMessageDeleted(BaseChannel channel, int messageId) {

    }
}

Copy a message

A user can copy and send their own message in the same channel or to another channel.

Light Color Skin
Copy
try {
    // `MESSAGE_TO_COPY` can be either `UserMessage` or `FileMessage`.
    final preMessage = openChannel.copyMessage(MESSAGE_TO_COPY, TARGET_CHANNEL, onCompleted: (msg, error) {
        // The message is successfully copied to the target channel.
    });
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

MESSAGE_TO_COPY

Type: BaseMessage
Specifies a message to copy.

TARGET_CHANNEL

Type: BaseChannel
Specifies a target channel to send a copied message to.

onCompleted

Type: onMessageCallback
Specifies the callback handler to receive the response from Sendbird server for a message copy request.


Retrieve a list of participants

You can retrieve a list of participants who are currently online and receiving all messages from an open channel.

Light Color Skin
Copy
try {
    final listQuery = UserListQuery()
        ..queryType = UserListQueryType.participants;
    final participants = await listQuery.loadNext();
} catch (e) {
    // Handle error.
}

Retrieve the latest information on participants

To retrieve the latest and updated information on each online participant in an open channel, you need another UserListQuery instance for the channel. Like the Retrieve a list of participants section above, create a new query instance using the UserListQuery, and then call its loadNext() method consecutively to retrieve the latest.

When retrieving the online connection status of a user, by checking the connectionStatus of each User object in a returned list, you can get the user's current connection status.

connectionStatus

The connectionStatus has one of the following two values:

ValueDescription

UserConnectionStatus.offline

The user is not connected to Sendbird server.

UserConnectionStatus.online

The user is connected to Sendbird server.

Note: If you need to keep track of the connection status of some users in real time, we recommend that you periodically call the loadNext() method of a ApplicationUserListQuery instance after specifying its userIds filter, perhaps in intervals of one minute or more.


Retrieve a list of operators

You can follow the simple implementation below to retrieve a list of operators who monitor and control the activities in an open channel.

Light Color Skin
Copy
try {
    final channel = await OpenChannel.getChannel(CHANNEL_URL);
    // Retrieving operators.
    channel.operators.forEach((operator) {

    });
}

You can also create an OperatorListQuery instance and use the loadNext() method to retrieve the list like the following.

Light Color Skin
Copy
try {
    final listQuery = OperatorListQuery()
        ..channelType = ChannelType.open
        ..channelUrl = CHANNEL_URL;

    final operators = await listQuery.loadNext();
    // Retrieving operators.
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

CHANNEL_URL

Type: String
Specifies the URL of the channel to retrieve a list of operators from.


Register operators

You can register participants as an operator of an open channel.

Light Color Skin
Copy
try {
    await openChannel.addOperators([USER_ID_1, USER_ID_2]);
    // The participants are successfully registered as operators of the channel.
} catch (e) {
    // Handle error.
}

Cancel the registration of operators

You can cancel the registration of operators from an open channel but leave them as participants.

Light Color Skin
Copy
try {
    await openChannel.addOperators([USER_ID_1, USER_ID_2]);
    // Successfully removed operators from the channel.
    // You can display some messages to those who are no longer operators.
} catch (e) {
    // Handle error.
}

If you want to cancel the registration of all operators in a channel at once, use the following code.

Light Color Skin
Copy
try {
    await openChannel.removeAllOperators();
} catch (e) {
    // Handle error.
}

Retrieve a list of banned or muted users

You can create a query to retrieve a list of banned or muted users from an open channel. This query is only available for users who are registered as operators of an open channel.

Light Color Skin
Copy
try {
    // Retrieving banned users.
    final listQuery = UserListQuery()
        ..queryType = UserListQueryType.banned;

    final users = await listQuery.loadNext();
} catch (e) {
    // Handle error.
}

try {
    // Retrieving muted users.
    final listQuery = UserListQuery()
        ..queryType = UserListQueryType.muted;

    final users = await listQuery.loadNext();
} catch (e) {
    // Handle error.
}

Ban and unban a user

Operators of an open channel can remove any users that behave inappropriately in the channel by using our Ban feature. Banned users are immediately expelled from a channel and allowed to participate in the channel again after the time period set by the operators. Operators can ban and unban users from open channels using the following code.

Light Color Skin
Copy
try {
    final channel = await OpenChannel.getChannel(CHANNEL_URL);
    // Ban a user.
    await channel.banUser(USER_ID, seconds: SECONDS);
    // The user is successfully banned from the channel.
    // You can notify the user of being banned by displaying a prompt.

    // Unban a user.
    await channel.unbanUser(USER_ID);
    // The user is successfully unbanned from the channel.
    // You can notify the user of being unbanned by displaying a prompt.
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

CHANNEL_URL

Type: String
Specifies the URL of the channel to ban or unban a user from.

USER_ID

Type: String
Specifies the ID of the user to ban or unban.


Mute and unmute a user

Operators of an open channel can prohibit selected users from sending messages using our Mute feature. Muted users remain in the channel and are allowed to view the messages, but can't send any messages until the operators unmute them. Operators can mute and unmute users in open channels using the following code:

Light Color Skin
Copy
try {
    final channel = await OpenChannel.getChannel(CHANNEL_URL);
    // Mute a user.
    await channel.muteUser(USER_ID, seconds: SECONDS);
    // The user is successfully muted from the channel.
    // You can notify the user of being muted by displaying a prompt.

    // Unmute a user.
    await channel.unmuteUser(USER_ID);
    // The user is successfully unmuted from the channel.
    // You can notify the user of being unmuted by displaying a prompt.
} catch (e) {
    // Handle error.
}

List of arguments

ArgumentDescription

CHANNEL_URL

Type: String
Specifies the URL of the channel to mute or unmute a user from.

USER_ID

Type: String
Specifies the ID of the user to mute or unmute.

SECONDS

Type: int
Specifies how many seconds the user is muted for.


Report a message, a user, or a channel

In an open channel, a user can report suspicious or harassing messages as well as the other users who use abusive language. The user can also report channels if there are any inappropriate content or activity within the channel. Based on this feature and our report API, you can build your own in-app system for managing objectionable content and subject.

Report a message
Report a user
Report a channel
Light Color Skin
Copy
try {
    await openChannel.reportMessage(
        message: MESSAGE_TO_REPORT,
        category: REPORT_CATEGORY,
        description: DESCRIPTION
    );
} catch (e) {
    // Handle error.
}
Light Color Skin
Copy
try {
    await openChannel.reportUser(
        userId: OFFENDING_USER_ID,
        category: REPORT_CATEGORY,
        description: DESCRIPTION
    );
} catch (e) {
    // Handle error.
}
Light Color Skin
Copy
try {
    await openChannel.reportChannel(
        category: REPORT_CATEGORY,
        description: DESCRIPTION
    );
} catch (e) {
    // Handle error.

List of arguments

ArgumentDescription

MESSAGE_TO_REPORT

Type: BaseMessage
Specifies the message to report for its suspicious, harassing, or inappropriate content.

OFFENDING_USER_ID

Type: String
Specifies the user who uses offensive or abusive language such as sending explicit messages or inappropriate comments.

REPORT_CATEGORY

Type: ReportCategory
Specifies a report category which indicates the reason for reporting. Acceptable values are ReportCategorySuspicious, ReportCategoryHarassing, ReportCategoryInappropriate, and ReportCategorySpam.

DESCRIPTION

Type: String
Specifies additional information to include in the report.

Specify the report category in the code to report a message, user, or channel. The following table lists the categories you can use.

List of report categories

CategoryDescription

suspicious

Messages, users, and channels that attempt to conspire, plot, or organize dangerous and illegal activities that could harm other people, including crime and terrorism.

harassing

Messages, users, and channels that are intended to intimidate, harass, bully, or insult other people.

inappropriate

Messages, users, and channels that are disrespectful, offensive, and hurtful toward other people.

spam

A cascade of repetitive messages that contain identical, and irrelevant content to the interaction and context of the channel. They can also entice people to install malicious software in their devices.