From 22d918da08dad49e141f2fec93c7c8ff4567f731 Mon Sep 17 00:00:00 2001 From: Yash Garg Date: Thu, 19 Dec 2024 15:58:03 +0530 Subject: [PATCH] docs(android-core): chat and stage v2 changes (MOB-1905, MOB-1908) (#406) * chore(android-core): update chat docs with v2 changes * chore(android-core): update stage docs with v2 changes * chore: docs review changes --- docs/android-core/chat/introduction.mdx | 11 ++- .../chat/receiving-chat-messages.mdx | 8 +- .../chat/sending-a-chat-message.mdx | 44 ++++++++-- .../stage-management/1-introduction.mdx | 83 ++++++++----------- .../stage-management/2-host-controls.mdx | 56 +++++-------- .../3-viewer-participants.mdx | 14 ++-- 6 files changed, 117 insertions(+), 99 deletions(-) diff --git a/docs/android-core/chat/introduction.mdx b/docs/android-core/chat/introduction.mdx index 924c34249..7fc1ab3d6 100644 --- a/docs/android-core/chat/introduction.mdx +++ b/docs/android-core/chat/introduction.mdx @@ -1,5 +1,5 @@ --- -title: Introducing chat +title: Introduction description: >- Learn the basics of integrating Dyte's chat functionality into your Android application – a step towards immersive real-time communication. @@ -29,7 +29,8 @@ class DyteTextMessage( pluginId: String?, val message: String, time: String, - channelId: String? = null, + createdAtMillis: Long, + targetUserIds: List?, ) ``` @@ -43,7 +44,8 @@ class DyteImageMessage( pluginId: String?, val link: String, time: String, - channelId: String? = null, + createdAtMillis: Long, + targetUserIds: List?, ) ``` @@ -57,9 +59,10 @@ class DyteFileMessage( pluginId: String?, val name: String, time: String, + createdAtMillis: Long, val link: String, val size: Long, - channelId: String? = null, + targetUserIds: List?, ) ``` diff --git a/docs/android-core/chat/receiving-chat-messages.mdx b/docs/android-core/chat/receiving-chat-messages.mdx index a8a4fd927..0d547a1c7 100644 --- a/docs/android-core/chat/receiving-chat-messages.mdx +++ b/docs/android-core/chat/receiving-chat-messages.mdx @@ -20,12 +20,16 @@ subscribe to this events by calling meeting.addChatEventsListener(object : DyteChatEventsListener { override fun onChatUpdates(messages: List) { - // to load chat messages + // to load chat messages } override fun onNewChatMessage(message: DyteChatMessage) { // when a new chat message is shared in the meeting } + + override fun onMessageRateLimitReset() { + // when the rate limit for sending messages of self is reset + } }) ``` @@ -33,6 +37,8 @@ The `onChatUpdates()` method will be called whenever there is a change in the ch The `onNewChatMessage()` method will be called whenever a new chat message is shared in the meeting. The `message` parameter is a `DyteChatMessage` object that has been sent in the chat. +The `onMessageRateLimitReset()` method will be called when the rate limit for sending messages of self is reset and you can send messages again. The default rate limit is 180 messages within 60 seconds. + Android Core Receiving chat \ No newline at end of file diff --git a/docs/android-core/chat/sending-a-chat-message.mdx b/docs/android-core/chat/sending-a-chat-message.mdx index 2b10b86be..9960a2fb4 100644 --- a/docs/android-core/chat/sending-a-chat-message.mdx +++ b/docs/android-core/chat/sending-a-chat-message.mdx @@ -28,9 +28,9 @@ You can send an image with the help of `meeting.chat.sendImageMessage()` and sends it to the participants in the meeting. ```kotlin -val filePath = "file_path_of_image" -val fileName = "file_name" -meeting.chat.sendImageMessage(filePath, fileName) +meeting.chat.sendImageMessage(imageUri) { err -> + // Handle error if any +} ``` ## Send a file @@ -38,9 +38,41 @@ meeting.chat.sendImageMessage(filePath, fileName) Sending a file is quite similar to sending an image. The only difference is that when you send an image, a preview will be shown in the meeting chat, which is not the case for sending files. That being said, an image can be sent as a file too using `meeting.chat.sendFileMessage()`. ```kotlin -val filePath = "file_path_of_image" -val fileName = "file_name" -meeting.chat.sendFileMessage(filePath, fileName) +meeting.chat.sendFileMessage(fileUri) { err -> + // Handle error if any +} +``` + +## Chat Errors + +The `sendTextMessage` method returns a `ChatTextError` if the operation fails, `null` if successful. The error can be the following: + +- `PermissionDenied`: The user does not have permission to send a message. +- `MessageIsBlank`: The message is empty. +- `CharacterLimitExceeded`: The message exceeds the character limit. Default limit is 2000 characters. +- `RateLimitBreached`: The user has sent too many messages in a short period of time. + +Both `sendImageMessage` and `sendFileMessage` methods accept a callback function that will be called with a `ChatFileError` if the operation is not successful, otherwise with `null` if successful. + +Possible `ChatFileError`s are: + +- `FileFormatNotAllowed`: The file format is not allowed. +- `PermissionDenied`: The user does not have permission to send a file. +- `RateLimitBreached`: The user has breached the rate limit for sending messages. +- `ReadFailed`: The file could not be read. +- `UploadFailed`: The file could not be uploaded. + +A `when` block can be used to handle these errors inside the callback, as shown below: + +```kotlin +when (err) { + is ChatFileError.FileFormatNotAllowed -> {} + is ChatFileError.PermissionDenied -> {} + is ChatFileError.RateLimitBreached -> {} + is ChatFileError.ReadFailed -> {} + is ChatFileError.UploadFailed -> {} + else -> {} +} ``` diff --git a/docs/android-core/stage-management/1-introduction.mdx b/docs/android-core/stage-management/1-introduction.mdx index 00f9b2f86..3442a3b6f 100644 --- a/docs/android-core/stage-management/1-introduction.mdx +++ b/docs/android-core/stage-management/1-introduction.mdx @@ -9,9 +9,9 @@ tags: _Below documentation is relevant for Interactive Livestream(LHLS) and Webinar(WebRTC) use cases._ -Instead of a traditional publish-subscribe model, where a user can publish their media and others can choose to subscribe, Dyte -comes with an optional managed configuration. In this managed configuration, a less privileged user can be configured with a -default behavior to not publish media. The user can then request permission to publish their media, which a privileged user can +Instead of a traditional publish-subscribe model, where a user can publish their media and others can choose to subscribe, Dyte +comes with an optional managed configuration. In this managed configuration, a less privileged user can be configured with a +default behavior to not publish media. The user can then request permission to publish their media, which a privileged user can choose to grant or deny. ### Accessing the Stage APIs @@ -21,27 +21,25 @@ permissions, and kicking participants from the stage. These APIs are accessible ### Stage Status -In meetings where stage management is enabled, a user's stage status can change within the values represented by the `DyteStageStatus` +In meetings where stage management is enabled, a user's stage status can change within the values represented by the `StageStatus` enum. These status values include: - `ON_STAGE`: Indicates that the user is currently on the stage and is allowed to publish media. - `OFF_STAGE`: Indicates that the user is a viewer and is not on the stage. They can see and listen to those on stage. -- `REQUESTED_TO_JOIN_STAGE`: Indicates that the user has a pending request to join the stage. This status is assigned to the user +- `REQUESTED_TO_JOIN_STAGE`: Indicates that the user has a pending request to join the stage. This status is assigned to the user until the host accepts or rejects their request. - `ACCEPTED_TO_JOIN_STAGE`: Indicates that the host has accepted the user's request to join the stage. -- `REJECTED_TO_JOIN_STAGE`: Indicates that the host has rejected the user's request to join the stage. The user can request again -to join from this status. -The `meeting.stage.status` property provides the current stage status of the local user. +The `meeting.stage.stageStatus` property provides the current stage status of the local user. ### Viewers -You can retrieve a list of off-stage participants (viewers) in a stage-enabled meeting by accessing the `meeting.stage.viewers` -property. This property provides a list of `DyteJoinedMeetingParticipant` objects whose stage status is not `ON_STAGE`. +You can retrieve a list of off-stage participants (viewers) in a stage-enabled meeting by accessing the `meeting.stage.viewers` +property. This property provides a list of `DyteRemoteParticipant` objects whose stage status is not `ON_STAGE`. ### Joining the Stage -To interact with peers and publish media, users can join the stage. This action is only possible if the user's preset allows them +To interact with peers and publish media, users can join the stage. This action is only possible if the user's preset allows them to publish media or if their request to join the stage has been accepted by a host (i.e., their stage status is `ACCEPTED_TO_JOIN_STAGE`). ```kotlin @@ -50,7 +48,7 @@ meeting.stage.join() ### Leaving the Stage -When users want to stop interacting with peers, they can leave the stage. This action stops their media from being published, +When users want to stop interacting with peers, they can leave the stage. This action stops their media from being published, and their audio and video are no longer received by others in the room. ```kotlin @@ -59,64 +57,55 @@ meeting.stage.leave() ### List of Stage Events -The `DyteStageEventListener` interface provides callback methods for various stage events. Implement these callbacks to handle +The `DyteStageEventListener` interface provides callback methods for various stage events. Implement these callbacks to handle stage-related events in your application: ```kotlin -meeting.addStageEventsListener(object : DyteStageEventListener { - override fun onPresentRequestReceived() { - // Called when the local user's stage access request is accepted by the host, - // or when the local user, who is a viewer, is invited to the stage by the host. +meeting.addStageEventListener(object : DyteStageEventListener { + override fun onStageAccessRequestAccepted() { + // Called when the local user is accepted to join the stage. } - override fun onAddedToStage() { - // Called when the local user successfully joins the stage. + override fun onStageAccessRequestRejected() { + // Called when the local user's request to join the stage is rejected by the host. } override fun onRemovedFromStage() { // Called when the local user is removed from the stage. } - override fun onPresentRequestAdded(participant: DyteJoinedMeetingParticipant) { - // Called when a participant requests to join the stage. Triggered only if the local user is a host. - } - - override fun onPresentRequestClosed(participant: DyteJoinedMeetingParticipant) { - // Called when a participant with a pending stage access request leaves the meeting. - // Triggered only if the local user is a host. - } - - override fun onPresentRequestRejected(participant: DyteJoinedMeetingParticipant) { - // Called when a participant's stage access request is denied by the host. + override fun onNewStageAccessRequest(participant: DyteRemoteParticipant) { + // Called when a new stage access request is received from a participant. // Triggered only if the local user is a host. } - override fun onPresentRequestWithdrawn(participant: DyteJoinedMeetingParticipant) { - // Called when a participant cancels their stage access request. + override fun onStageAccessRequestsUpdated(accessRequests: List) { + // Called when the list of stage access requests is updated. // Triggered only if the local user is a host. } - override fun onParticipantRemovedFromStage(participant: DyteJoinedMeetingParticipant) { - // Called when a participant is removed from the stage by the host. + override fun onStageStatusUpdated(oldStatus: StageStatus, newStatus: StageStatus) {} + // Called when the local user's stage status is updated. } - override fun onStageRequestsUpdated(accessRequests: List) { - // Called when the list of stage access requests is updated. + override fun onPeerStageStatusUpdated( + participant: DyteRemoteParticipant, + oldStatus: StageStatus, + newStatus: StageStatus, + ) { + // Called when a remote participant's stage status is updated. } +}) +``` - override fun onParticipantStartedPresenting(participant: DyteJoinedMeetingParticipant) { - // Called when a participant joins the stage. - } +### Stage Errors - override fun onParticipantStoppedPresenting(participant: DyteJoinedMeetingParticipant) { - // Called when a participant leaves the stage. - } +All the stage management APIs return a `StageError` if the operation fails. On success, they return `null`. The error type can be one of the following: - override fun onStageStatusUpdated(stageStatus: DyteStageStatus) { - // Called when the local user's stage status is updated. - } -}) -``` +- `StageDisabledForMeetingType`: The meeting type does not support stage management. +- `PermissionDenied`: The user does not have the required permissions to perform the operation. +- `ActionInvalidForStageStatus`: The operation is invalid for the current stage status. +- `NoRequestToCancel`: There is no pending request to cancel. Next, we'll explore the Stage Management APIs for hosts, allowing them to manage stage requests, participants in Dyte meetings. diff --git a/docs/android-core/stage-management/2-host-controls.mdx b/docs/android-core/stage-management/2-host-controls.mdx index ee9ebb03a..14a074d30 100644 --- a/docs/android-core/stage-management/2-host-controls.mdx +++ b/docs/android-core/stage-management/2-host-controls.mdx @@ -7,43 +7,41 @@ tags: - stage --- -In a stage management-enabled meeting, a user with the `selfPermissions.host.canAcceptStageRequests` permission as `true` is -considered a host. The `meeting.stage` object in Dyte's Android Core SDK provides stage management APIs that allow hosts to +In a stage management-enabled meeting, a user with the `permissions.host.canAcceptStageRequests` permission as `true` is +considered a host. The `meeting.stage` object in Dyte's Android Core SDK provides stage management APIs that allow hosts to manage stage access requests, invite participants to the stage, and remove participants from the stage. ### List of Stage Access Requests -You can retrieve the list of pending stage access requests by accessing the `meeting.stage.accessRequests` property. This property -provides a list of `DyteJoinedMeetingParticipant` objects who have requested stage access. +You can retrieve the list of pending stage access requests by accessing the `meeting.stage.accessRequests` property. This property +provides a list of `DyteRemoteParticipant` objects who have requested stage access. **Note**: If the local user is not a host, this property returns an empty list. ### Grant Access -To accept stage access requests or allow a participant directly to the stage, you can use the `grantAccess()` method. -Alternatively, the `grantAccessAll()` method can be used to grant stage access to all participants with pending stage access requests. +To accept stage access requests or allow a participant directly to the stage, you can use the `grantAccess()` method. ```kotlin // Grants stage access to a participant // id: peer id of the stage access requesting participant -meeting.stage.grantAccess(id) +meeting.stage.grantAccess(listOf(id)) -// Grants stage access to all participants with pending stage access requests -meeting.stage.grantAccessAll() +// Grants stage access to all pending stage access requests +meeting.stage.grantAccess(meeting.stage.accessRequests.map { it.userId }) ``` ### Deny Access -To reject stage access requests, you can use the `denyAccess()` method. Similarly, the `denyAccessAll()` method can be used to -deny all pending stage access requests. +To reject stage access requests, you can use the `denyAccess()` method. ```kotlin // Denies stage access request of a participant // id: peer id of the stage access requesting participant -meeting.stage.denyAccess(id) +meeting.stage.denyAccess(listOf(id)) // Denies all pending stage access requests -meeting.stage.denyAccessAll() +meeting.stage.denyAccess(meeting.stage.accessRequests.map { it.userId }) ``` ### Kick Users @@ -53,39 +51,25 @@ You can remove a participant from the stage by using the `kick()` method. ```kotlin // Kicks a participant from stage // id: peer id of the ON_STAGE participant to kick -meeting.stage.kick(id) +meeting.stage.kick(listOf(id)) ``` ### Listening to Stage Access Requests -You can listen to incoming stage access requests or changes in the access requests list if you are a host. The SDK provides the -following callbacks to `DyteStageEventsListener`: +You can listen to incoming stage access requests or changes in the access requests list if you are a host. The SDK provides the +following callbacks to `DyteStageEventListener`: ```kotlin -meeting.addStageEventsListener(object : DyteStageEventsListener { - override fun onPresentRequestAdded(participant: DyteStageParticipant) { - // Called when a user is requesting to join the stage +meeting.addStageEventListener(object : DyteStageEventListener { + override fun onNewStageAccessRequest(participant: DyteRemoteParticipant) { + // Called when a new stage access request is received from a participant. } - override fun onPresentRequestClosed(participant: DyteStageParticipant) { - // Called when a user who was trying to join the stage leaves the call - } - - override fun onPresentRequestRejected(participant: DyteStageParticipant) { - // Called when a join stage request is denied by the host - } - - override fun onPresentRequestWithdrawn(participant: DyteStageParticipant) { - // Called when a user who was trying to join the stage withdraws their request to join - } - - override fun onStageRequestsUpdated(accessRequests: List) { - // Called when the access requests list is updated + override fun onStageAccessRequestsUpdated(accessRequests: List) { + // Called when the list of stage access requests is updated. } }) ``` -These APIs enable you to manage stage access requests and participants effectively in Dyte meetings. Next, we'll explore the +These APIs enable you to manage stage access requests and participants effectively in Dyte meetings. Next, we'll explore the Stage APIs available to Viewer participants. - - diff --git a/docs/android-core/stage-management/3-viewer-participants.mdx b/docs/android-core/stage-management/3-viewer-participants.mdx index 4e92f5166..47d567c09 100644 --- a/docs/android-core/stage-management/3-viewer-participants.mdx +++ b/docs/android-core/stage-management/3-viewer-participants.mdx @@ -7,7 +7,7 @@ tags: - stage --- -Viewer participants in a stage-enabled meeting are users whose preset permission for media production is set as `CAN_REQUEST`. +Viewer participants in a stage-enabled meeting are users whose preset permission for media production is set as `CAN_REQUEST`. The `meeting.stage` object provides APIs for viewer participants to request stage access and withdraw their join stage request. ### Request Access @@ -18,14 +18,18 @@ To request access to the stage, you can call the `requestAccess()` method: meeting.stage.requestAccess() ``` -When a host accepts the user's stage access request or allows the user directly to the stage, the SDK triggers the -`onPresentRequestReceived` callback in `DyteStageEventListener`. You can listen to this event: +When a host accepts the user's stage access request or allows the user directly to the stage, the SDK triggers the +`onStageAccessRequestAccepted` callback and if the host rejects the request, the SDK triggers the `onStageAccessRequestRejected` callback. You can listen to these events by adding a `DyteStageEventListener`: ```kotlin -meeting.addStageEventsListener(object : DyteStageEventListener { - override fun onPresentRequestReceived() { +meeting.addStageEventListener(object : DyteStageEventListener { + override fun onStageAccessRequestAccepted() { // Host accepted the join stage request or invited user directly to stage } + + override fun onStageAccessRequestRejected() { + // Host rejected the join stage request + } }) ```