From 2b227ebab288bfe5ed4daa365c833144fd5adc99 Mon Sep 17 00:00:00 2001 From: Shaunak Jagtap Date: Wed, 17 Apr 2024 10:54:35 +0530 Subject: [PATCH 01/19] WIP: add new structure for ios-core docs --- docs/ios-core-new/Introduction.mdx | 41 ++ docs/ios-core-new/advanced/_category_.json | 6 + docs/ios-core-new/advanced/advance.mdx | 141 ++++ docs/ios-core-new/chat/_category_.json | 5 + docs/ios-core-new/chat/edit-chat-messages.mdx | 92 +++ docs/ios-core-new/chat/introduction.mdx | 55 ++ .../chat/other-chat-functions.mdx | 100 +++ .../chat/receiving-chat-messages.mdx | 39 ++ .../chat/sending-a-chat-message.mdx | 90 +++ docs/ios-core-new/error-codes/_category_.json | 5 + .../error-codes/error-code-zero-ten.mdx | 82 +++ docs/ios-core-new/error-codes/error-code.mdx | 46 ++ docs/ios-core-new/livestreaming.mdx | 59 ++ docs/ios-core-new/local-user/_category_.json | 5 + docs/ios-core-new/local-user/events.mdx | 194 ++++++ docs/ios-core-new/local-user/extras.mdx | 97 +++ docs/ios-core-new/local-user/introduction.mdx | 148 +++++ .../local-user/manage-media-devices.mdx | 49 ++ .../local-user/media-permission-errors.mdx | 43 ++ .../ios-core-new/participants/_category_.json | 5 + docs/ios-core-new/participants/events.mdx | 192 ++++++ .../participants/participant-object.mdx | 119 ++++ .../ios-core-new/participants/permissions.mdx | 52 ++ docs/ios-core-new/participants/pip.mdx | 42 ++ .../participants/remote-participants.mdx | 117 ++++ docs/ios-core-new/plugins/_category_.json | 5 + docs/ios-core-new/plugins/disable-plugin.mdx | 75 +++ docs/ios-core-new/plugins/enable-plugin.mdx | 76 +++ docs/ios-core-new/plugins/extra.mdx | 47 ++ docs/ios-core-new/plugins/introduction.mdx | 84 +++ docs/ios-core-new/polls/_category_.json | 5 + docs/ios-core-new/polls/creating-a-poll.mdx | 36 + docs/ios-core-new/polls/introduction.mdx | 44 ++ .../polls/other-poll-functions.mdx | 52 ++ docs/ios-core-new/polls/voting-on-a-poll.mdx | 31 + .../ios-core-new/pre-call/1-media-preview.mdx | 111 ++++ .../pre-call/2-handling-permissions.mdx | 50 ++ docs/ios-core-new/pre-call/3-virtual-bg.mdx | 117 ++++ docs/ios-core-new/pre-call/4-meeting-meta.mdx | 17 + docs/ios-core-new/pre-call/5-waiting-room.mdx | 46 ++ docs/ios-core-new/pre-call/_category_.json | 6 + docs/ios-core-new/quickstart.mdx | 254 ++++++++ docs/ios-core-new/recording.mdx | 159 +++++ docs/ios-core-new/reference/DyteAi.md | 12 + docs/ios-core-new/reference/DyteChat.md | 212 ++++++ docs/ios-core-new/reference/DyteClient.md | 151 +++++ docs/ios-core-new/reference/DyteLivestream.md | 30 + docs/ios-core-new/reference/DyteMeta.md | 102 +++ .../ios-core-new/reference/DyteParticipant.md | 247 +++++++ .../reference/DyteParticipantMap.md | 14 + .../reference/DyteParticipants.md | 615 ++++++++++++++++++ .../reference/DytePermissionsPreset.md | 291 +++++++++ docs/ios-core-new/reference/DytePlugin.md | 126 ++++ docs/ios-core-new/reference/DytePluginMap.md | 14 + docs/ios-core-new/reference/DytePlugins.md | 29 + docs/ios-core-new/reference/DytePolls.md | 56 ++ docs/ios-core-new/reference/DyteRecording.md | 44 ++ docs/ios-core-new/reference/DyteRemote.md | 49 ++ docs/ios-core-new/reference/DyteSelf.md | 262 ++++++++ docs/ios-core-new/reference/DyteSelfMedia.md | 177 +++++ docs/ios-core-new/reference/DyteStage.md | 90 +++ .../ios-core-new/reference/DyteThemePreset.md | 85 +++ docs/ios-core-new/reference/_category_.json | 5 + docs/ios-core-new/release-notes.mdx | 18 + docs/ios-core-new/room-metadata.mdx | 64 ++ docs/ios-core-new/stage.mdx | 108 +++ docusaurus.config.js | 10 + src/sections.ts | 19 +- 68 files changed, 5862 insertions(+), 7 deletions(-) create mode 100644 docs/ios-core-new/Introduction.mdx create mode 100644 docs/ios-core-new/advanced/_category_.json create mode 100644 docs/ios-core-new/advanced/advance.mdx create mode 100644 docs/ios-core-new/chat/_category_.json create mode 100644 docs/ios-core-new/chat/edit-chat-messages.mdx create mode 100644 docs/ios-core-new/chat/introduction.mdx create mode 100644 docs/ios-core-new/chat/other-chat-functions.mdx create mode 100644 docs/ios-core-new/chat/receiving-chat-messages.mdx create mode 100644 docs/ios-core-new/chat/sending-a-chat-message.mdx create mode 100644 docs/ios-core-new/error-codes/_category_.json create mode 100644 docs/ios-core-new/error-codes/error-code-zero-ten.mdx create mode 100644 docs/ios-core-new/error-codes/error-code.mdx create mode 100644 docs/ios-core-new/livestreaming.mdx create mode 100644 docs/ios-core-new/local-user/_category_.json create mode 100644 docs/ios-core-new/local-user/events.mdx create mode 100644 docs/ios-core-new/local-user/extras.mdx create mode 100644 docs/ios-core-new/local-user/introduction.mdx create mode 100644 docs/ios-core-new/local-user/manage-media-devices.mdx create mode 100644 docs/ios-core-new/local-user/media-permission-errors.mdx create mode 100644 docs/ios-core-new/participants/_category_.json create mode 100644 docs/ios-core-new/participants/events.mdx create mode 100644 docs/ios-core-new/participants/participant-object.mdx create mode 100644 docs/ios-core-new/participants/permissions.mdx create mode 100644 docs/ios-core-new/participants/pip.mdx create mode 100644 docs/ios-core-new/participants/remote-participants.mdx create mode 100644 docs/ios-core-new/plugins/_category_.json create mode 100644 docs/ios-core-new/plugins/disable-plugin.mdx create mode 100644 docs/ios-core-new/plugins/enable-plugin.mdx create mode 100644 docs/ios-core-new/plugins/extra.mdx create mode 100644 docs/ios-core-new/plugins/introduction.mdx create mode 100644 docs/ios-core-new/polls/_category_.json create mode 100644 docs/ios-core-new/polls/creating-a-poll.mdx create mode 100644 docs/ios-core-new/polls/introduction.mdx create mode 100644 docs/ios-core-new/polls/other-poll-functions.mdx create mode 100644 docs/ios-core-new/polls/voting-on-a-poll.mdx create mode 100644 docs/ios-core-new/pre-call/1-media-preview.mdx create mode 100644 docs/ios-core-new/pre-call/2-handling-permissions.mdx create mode 100644 docs/ios-core-new/pre-call/3-virtual-bg.mdx create mode 100644 docs/ios-core-new/pre-call/4-meeting-meta.mdx create mode 100644 docs/ios-core-new/pre-call/5-waiting-room.mdx create mode 100644 docs/ios-core-new/pre-call/_category_.json create mode 100644 docs/ios-core-new/quickstart.mdx create mode 100644 docs/ios-core-new/recording.mdx create mode 100644 docs/ios-core-new/reference/DyteAi.md create mode 100644 docs/ios-core-new/reference/DyteChat.md create mode 100644 docs/ios-core-new/reference/DyteClient.md create mode 100644 docs/ios-core-new/reference/DyteLivestream.md create mode 100644 docs/ios-core-new/reference/DyteMeta.md create mode 100644 docs/ios-core-new/reference/DyteParticipant.md create mode 100644 docs/ios-core-new/reference/DyteParticipantMap.md create mode 100644 docs/ios-core-new/reference/DyteParticipants.md create mode 100644 docs/ios-core-new/reference/DytePermissionsPreset.md create mode 100644 docs/ios-core-new/reference/DytePlugin.md create mode 100644 docs/ios-core-new/reference/DytePluginMap.md create mode 100644 docs/ios-core-new/reference/DytePlugins.md create mode 100644 docs/ios-core-new/reference/DytePolls.md create mode 100644 docs/ios-core-new/reference/DyteRecording.md create mode 100644 docs/ios-core-new/reference/DyteRemote.md create mode 100644 docs/ios-core-new/reference/DyteSelf.md create mode 100644 docs/ios-core-new/reference/DyteSelfMedia.md create mode 100644 docs/ios-core-new/reference/DyteStage.md create mode 100644 docs/ios-core-new/reference/DyteThemePreset.md create mode 100644 docs/ios-core-new/reference/_category_.json create mode 100644 docs/ios-core-new/release-notes.mdx create mode 100644 docs/ios-core-new/room-metadata.mdx create mode 100644 docs/ios-core-new/stage.mdx diff --git a/docs/ios-core-new/Introduction.mdx b/docs/ios-core-new/Introduction.mdx new file mode 100644 index 0000000000..d37cfb0a4a --- /dev/null +++ b/docs/ios-core-new/Introduction.mdx @@ -0,0 +1,41 @@ +--- +title: Introduction +sidebar_position: 1 +--- + +import ProductSection from '/docs/partials/_product-section.mdx'; + +# Introduction + +The Dyte Core SDK is designed to provide you with an easy way to incorporate live video, voice, livestream and chat capabilities +into your Android apps. The Core SDK acts as a data-only layer. It provides simple APIs offering high-level primitives and +abstracting away complex media and networking optimizations. + +## Why Core SDK? + +The Core SDK was developed with a user-friendly approach to eliminate the complexity of managing streams. Unlike traditional +SDKs that require knowledge of WebRTC functioning, Dyte's Core SDK provides a simple API that abstracts out the complexity, +making it easier for developers to use. For instance, enabling video with Dyte's Core SDK is as easy as calling +`meeting.localUser.enableVideo()`. + +## Utility Modules + +The Core SDK includes various modules for in-call utilities like chat, polls, and recording that enable building a UI on top of +it. The following are the core SDK modules: + +- **meeting.localUser**: This consists of properties and methods corresponding to the current (local) user, such as enabling or + disabling their audio and video, getting a list of media devices or changing the device, or sharing your mobile screen. +- **meeting.participants**: Use this module to get useful information about the other participants that are present in the + meeting. A host can use this module for access control. For example, the host can mute or kick a participant. +- **meeting.chat**: It provides the methods to integrate chat features such as sending/receiving text, images, and files. +- **meeting.polls**: Meetings can have polls. This module lets you perform actions related to polls, that is create and manage + a poll within a meeting. +- **meeting.recording**: When a meeting needs to be recorded, this module can be used. It lets you start or stop a recording, + and get the current status of an ongoing recording. +- **meeting.meta**: This object consists of all the metadata related to the current meeting, such as the title, the timestamp + of when it started, and more. +- **meeting.plugins**: Provides the list of available plugins and active plugins. Use this module to enable or disable plugins as needed. + + + iOS Core Introduction + diff --git a/docs/ios-core-new/advanced/_category_.json b/docs/ios-core-new/advanced/_category_.json new file mode 100644 index 0000000000..bb693ac563 --- /dev/null +++ b/docs/ios-core-new/advanced/_category_.json @@ -0,0 +1,6 @@ +{ + "position": 5, + "label": "Initialization", + "collapsible": true, + "className": "top-border" +} diff --git a/docs/ios-core-new/advanced/advance.mdx b/docs/ios-core-new/advanced/advance.mdx new file mode 100644 index 0000000000..5979db8712 --- /dev/null +++ b/docs/ios-core-new/advanced/advance.mdx @@ -0,0 +1,141 @@ +--- +title: Advance +sidebar_position: 1 +--- + +## Defaults Configuration + +```js +await DyteClient.init({ + defaults: { + ... + } +}) +``` + +While initializing DyteClient you can pass configuration overrides, the available options are + +```ts +type DefaultOptions { + video?: boolean; + audio?: boolean; + screenShare?: { + displaySurface?: 'window' | 'monitor' | 'browser'; + }; + mediaConfiguration?: { + video?: VideoQualityConstraints, + audio?: AudioQualityConstraints, + } + isNonPreferredDevice?: (device: MediaDeviceInfo) => boolean; + /** + * If true, will automatically switch audio input and output device + * to a new device connected mid call. (In case of disconnection switch + * will happen automatically in both cases) + */ + autoSwitchAudioDevice?: boolean; + recording?: RecordingConfig; +} +``` + +### audio, video + +This optional propery is true by default and defines whether audio or video would be acquired and enabled on SDK initialization + +** Change default audio / video settings (()) + +By default as soon as you join the meeting the SDK will produce your video and +audio streams. + +```ts {5} +const meeting = await DyteClient.init({ + authToken, + defaults: { + audio: false, // Disable user's audio by default + video: true, // Enable user's video by default + }, +}); +``` +### screenShare.displaySurface + +Specifies the _preferred_ screenshare surface, user will still be shown all possible options but the one configured here will be preselected + +Allowed values: `window`, `monitor`, `browser` + +[https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#displaysurface](https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints#displaysurface) + +### mediaConfiguration + +Defines media quality configuration + +For audio - + +```ts +{ + echoCancellation?: boolean, // default true + noiseSupression?: boolean, // default true + autoGainControl?: boolean, // default true + enableStereo?: boolean, // default false + enableHighBitrate?: boolean // default false +} +``` + +For applications where audio quality needs to be high and as loseless as possible + +```js +{ + echoCancellation: false, + noiseSupression: false, + autoGainControl: false, + enableStereo: true, + enableHighBitrate: true, +} +``` + +For video - + +```ts +{ + width: { ideal: number }, + height: { ideal: number }, + frameRate?: { ideal: number }, +} +``` + +### isNonPreferredDevice + +Our SDK will acquire media devices preferring virtual devices to not be selected by default (OBS, iPhone continuity) +You can override this logic by using your own function to decide the preference + +```ts +defaults: { + ... + isNonPreferredDevice: (device: MediaDeviceInfo) => { + if(device.label.startsWith("Virtual")) { + return false + } + } +} +``` + +### autoSwitchAudioDevice + +By default, when a new audio device is plugged in our SDK switches to that device. You can configure that behaviour + +### recording + +```ts +{ + fileNamePrefix?: string; + videoConfig?: { + height?: number; + width?: number; + codec?: string; + }; +} +``` + +Refer to [recording codec guide](/guides/capabilities/recording/configure-codecs#configure-codecs) for info the `codec` parameter + + + Web Core Advance + diff --git a/docs/ios-core-new/chat/_category_.json b/docs/ios-core-new/chat/_category_.json new file mode 100644 index 0000000000..50bf23d1b2 --- /dev/null +++ b/docs/ios-core-new/chat/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 8, + "label": "Chat", + "collapsible": true +} diff --git a/docs/ios-core-new/chat/edit-chat-messages.mdx b/docs/ios-core-new/chat/edit-chat-messages.mdx new file mode 100644 index 0000000000..82924105fd --- /dev/null +++ b/docs/ios-core-new/chat/edit-chat-messages.mdx @@ -0,0 +1,92 @@ +--- +title: Editing Chat Messages +description: Edit chat messages that you have sent in a meeting. +sidebar_position: 4 +tags: + - web-core + - chat +--- + +As mentioned in introduction, there are 3 types of chat messages - text +messages, images, and files. There is a method in meeting.chat to edit a message +of each type. + +## Edit a text message + +To edit a text message, the `meeting.chat.editTextMessage()` method can be used. +This accepts a `messageId` (type `string`) and a `message` (type `string`). + +```ts +const message = meeting.chat.messages[0]; +const messageId = message?.id; +const newMessage = 'Is this the real life?'; +await; +meeting.chat.editTextMessage(messageId, newMessage); +``` + +## Edit an image + +You can send an image with the help of meeting.chat.editImageMessage(). This +accepts a `messageId` of type `string` and an image of type `File`. + +```ts + + + +``` + +```ts +async function onEditImage() { + const messageId = '...'; + const image = document.getElementById('img'); + await meeting.chat.editImageMessage(messageId, image.files[0]); +} +``` + +## Edit a file + +Editing a file is quite similar to editing an image. To edit a file use +`meeting.chat.editFileMessage()`. + +```ts + + + +``` + +```ts +async function onEditFile() { + const messageId = '...'; + const file = document.getElementById('file'); + await meeting.chat.editFileMessage(messageId, file.files[0]); +} +``` + +## Extra + +There is also a common method called `meeting.chat.editMessage()` that can be +used to edit any of the 3 types of messages displayed above. It essentially +calls one of the methods from above depending upon the type of payload you send +to the method. The `editMessage()` method accepts a parameters `messageId` +`message` of the following type: + +```ts +async function editMessage( + messageId: string, + message: { type: 'text', message: string } + | { type: 'image', image: File } + | { type: 'file', file: File }, +) {...} +``` + +Here's how you would use the `editMessage()` method to edit a text message. + +```ts +const messageId = '...'; +const message = 'Is this just fantasy?'; +await meeting.chat.sendMessage(messageId, { type: 'text', message }); +``` + + + Web Core Editing Chat Messages + diff --git a/docs/ios-core-new/chat/introduction.mdx b/docs/ios-core-new/chat/introduction.mdx new file mode 100644 index 0000000000..a1c2407bba --- /dev/null +++ b/docs/ios-core-new/chat/introduction.mdx @@ -0,0 +1,55 @@ +--- +title: Introducing chat +description: Send and receive chat messages in a meeting. +sidebar_position: 1 +tags: + - web-core + - chat +--- + +# Introducing chat + +The meeting chat object is stored in `meeting.chat`, which has methods for +sending and receiving messages. There are 3 types of messages that can be sent +in chat - text messages, images, and files. + +The `meeting.chat.messages` array contains all the messages that have been sent +in the chat. This is an array of objects, where each object is of type +`Message`. + +The type `Message` is defined in the following manner. + +```ts +interface BaseMessage { + type: T; + userId: string; + displayName: string; + time: Date; + id: string; + isEdited?: boolean; + read?: boolean; + pluginId?: string; + pinned?: boolean; + targetUserIds?: string[]; +} + +interface TextMessage extends BaseMessage { + message: string; +} + +interface ImageMessage extends BaseMessage { + link: string; +} + +interface FileMessage extends BaseMessage { + name: string; + size: number; + link: string; +} + +type Message = TextMessage | ImageMessage | FileMessage; +``` + + + Web Core Introducing chat + diff --git a/docs/ios-core-new/chat/other-chat-functions.mdx b/docs/ios-core-new/chat/other-chat-functions.mdx new file mode 100644 index 0000000000..974a140296 --- /dev/null +++ b/docs/ios-core-new/chat/other-chat-functions.mdx @@ -0,0 +1,100 @@ +--- +title: Other chat functions +description: Other functionality associated with chat. +sidebar_position: 5 +tags: + - web-core + - chat +--- + +# Other chat functions + +The `meeting.chat` object exposes certain other methods for convenience when +working with chat. + +## Get messages by a user + +You can get messages by a particular user by passing the user's ID to the +`meeting.chat.getMessagesByUser()` method. + +```ts +// Find the userId of the user with name "Freddie". +const { userId } = meeting.participants.joined + .toArray() + .find((p) => p.name === 'Freddie'); + +const messages = meeting.chat.getMessagesByUser(userId); +``` + +## Get messages of a particular type + +You can also get messages of a particular type using the +`meeting.chat.getMessagesByType()` method. For example, you can get all image +messages present in the chat using the following snippet. + +```ts +const imageMessages = meeting.chat.getMessagesByType('image'); +``` + +## Pinning a chat message + +You can `pin` a number of messages to the chat. When you pin a message, the +message object will have the attribute `pinned: true`, using which you can +identify if a message is pinned. + +To pin a message, run the following snippet. + +```ts +// Let's say we want to pin the first message in the chat (could be a text, image, or file). +const { id } = meeting.chat.messages[0]; + +await meeting.chat.pin(id); +``` + +Once you pin a message, it will be added to `meeting.chat.pinned`. + +```ts +const { id } = meeting.chat.messages[0]; + +await meeting.chat.pin(id); + +console.log(meeting.chat.pinned); +console.log(meeting.chat.pinned.length > 0); // Should be true +``` + +You can also unpin a pinned message, by using the `meeting.chat.unpin()` method. + +```ts +// Unpin the first pinned message. + +const { id } = meeting.chat.pinned[0]; +await meeting.chat.unpin(id); +``` + +You can listen for events to know when a message is pinned or unpinned. + +```ts +meeting.chat.on('pinMessage', ({ message }) => { + console.log('A message was pinned', JSON.stringify(message)); +}); +``` + +```ts +meeting.chat.on('unpinMessage', ({ message }) => { + console.log('A message was unpinned', JSON.stringify(message)); +}); +``` + +## Deleting a chat message + +The `meeting.chat` namespace exposes a method called `deleteMessage()`. It takes +a parameter `meesageId` of type `string`. + +```ts +const messageId = '...'; +await meeting.chat.deleteMessage(messageId); +``` + + + Web Core Other chat functions + diff --git a/docs/ios-core-new/chat/receiving-chat-messages.mdx b/docs/ios-core-new/chat/receiving-chat-messages.mdx new file mode 100644 index 0000000000..4d4a77a854 --- /dev/null +++ b/docs/ios-core-new/chat/receiving-chat-messages.mdx @@ -0,0 +1,39 @@ +--- +title: Receiving chat messages +description: Receive chat messages that have been sent in a meeting. +sidebar_position: 3 +tags: + - web-core + - chat +--- + +# Receiving chat messages + +The `meeting.chat` object emits events when new chat messages are received. You +can listen for the `chatUpdate` event to log when a new chat message is +received. + +```ts +meeting.chat.on('chatUpdate', ({ message, messages }) => { + console.log(`Received message ${message}`); + console.log(`All messages in chat: ${messages.join(', ')}`); +}); +``` + +Here, the `message` is of type `Message`, as defined in +[introduction](./introduction). `messages` is a list of all chat messages in the +meeting, which is the same as `meeting.chat.messages`. + +When a chat message is received, the `meeting.chat.messages` list is also +updated. + +```ts +console.log(JSON.stringify(meeting.chat.messages)); +meeting.chat.on('chatUpdate', () => { + console.log(JSON.stringify(meeting.chat.messages)); +}); +``` + + + Web Core Receiving chat messages + diff --git a/docs/ios-core-new/chat/sending-a-chat-message.mdx b/docs/ios-core-new/chat/sending-a-chat-message.mdx new file mode 100644 index 0000000000..dc875e782b --- /dev/null +++ b/docs/ios-core-new/chat/sending-a-chat-message.mdx @@ -0,0 +1,90 @@ +--- +title: Sending a chat message +description: Send a chat message in a meeting. +sidebar_position: 2 +tags: + - web-core + - chat +--- + +# Sending a chat message + +As mentioned in [introduction](./introduction), there are 3 types of chat +messages - text messages, images, and files. There is a method in `meeting.chat` +to send a message of each type. + +## Send a text message + +To send a text message, the `meeting.chat.sendTextMessage()` method can be used. +This accepts a string `message` and sends it to the room. + +```ts +const message = 'Is this the real life?'; +await meeting.chat.sendTextMessage(message); +``` + +## Send an image + +You can send an image with the help of `meeting.chat.sendImageMessage()`. This +accepts an image of type `File`, and sends it to the participants in the +meeting. + +```html + + + +``` + +```ts +async function onSendImage() { + const image = document.getElementById('img'); + await meeting.chat.sendImageMessage(image.files[0]); +} +``` + +## Send a file + +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()`. + +```html + + + +``` + +```ts +async function onSendFile() { + const file = document.getElementById('file'); + await meeting.chat.sendFileMessage(file.files[0]); +} +``` + +## Extra + +There is also a common method called `meeting.chat.sendMessage()` that can be +used to send any of the 3 types of messages displayed above. It essentially +calls one of the methods from above depending upon the type of payload you send +to the method. The `sendMessage()` method accepts a parameter `message` of the +following type: + +```ts +async function sendMessage( + message: { type: 'text', message: string } + | { type: 'image', image: File } + | { type: 'file', file: File }, +) {...} +``` + +Here's how you would use the `sendMessage()` method to send a text message. + +```ts +const message = 'Is this just fantasy?'; +await meeting.chat.sendMessage({ type: 'text', message }); +``` + + + Web Core Sending a chat message + diff --git a/docs/ios-core-new/error-codes/_category_.json b/docs/ios-core-new/error-codes/_category_.json new file mode 100644 index 0000000000..f04ac45173 --- /dev/null +++ b/docs/ios-core-new/error-codes/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 99, + "label": "System Error Codes", + "collapsible": true +} diff --git a/docs/ios-core-new/error-codes/error-code-zero-ten.mdx b/docs/ios-core-new/error-codes/error-code-zero-ten.mdx new file mode 100644 index 0000000000..bcb997a4fc --- /dev/null +++ b/docs/ios-core-new/error-codes/error-code-zero-ten.mdx @@ -0,0 +1,82 @@ +--- +title: System Error Codes (0-16) +sidebar_position: 2 +--- + +This topic describes web core system error codes 0-16. + +## Error code: 0001 + +- **Error message**: Failed to initialize +- **Possible reason**: `DyteClient` is not getting initialized. +- **Possible solution**: Verify if you initialized the `DyteClient` correctly `await DyteClient.init({ ... })`. See [DyteClient](/web-core/reference/DyteClient). If you continue to experience issue, please [reach out](https://dyte.io/contact) to us for the help. + +## Error code: 0002 + +- **Error message**: Failed to join room +- **Possible reason**: Indicates a problem with the `DyteClient`. +- **Possible solution**: The `joinRoom()` method is used to join a meeting room in Dyte. Try calling this method on the `DyteClient`: + +```bash +await meeting.joinRoom(); +``` + +Once the join room process completes, you'll see the `roomJoined` event is emitted on the `meeting.self` namespace. + +## Error code: 0003 + +- **Error message**: Failed to leave room +- **Possible reason**: Indicates a problem with the `DyteClient`. +- **Possible solution**: The `leaveRoom()` method is used to leave a meeting room in Dyte. Try calling this method on the `DyteClient`: + +```bash +meeting.leaveRoom(); +``` + +## Error code: 0501 + +- **Error message**: Permission denied +- **Possible reason**: Indicates a problem with chat. +- **Possible solution**: Please check if you've added the required permissions to your organization for your [preset](https://dev.dyte.io/). + +error-chat-preset + +## Error code: 0502 + +- **Error message**: Invalid message body +- **Possible reason**: Indicates a problem with chat. +- **Possible solution**: The type `Message` is not defined correctly. See [Chat](/web-core/chat/introduction). + +## Error code: 1601 + +- **Error message**: Failed to get audio track +- **Possible reason**: Indicates a problem with the audio track of the device. +- **Possible solution**: Verify if you've subscribed to the [Audio update event](/web-core/local-user/events#audio-update). Check your audio track status. If the problem persists, please [contact us](https://dyte.io/contact) for the help. + +## Error code: 1602 + +- **Error message**: Failed to get video track +- **Possible reason**: Indicates a problem with the video track of the device. +- **Possible solution**: Verify if you've subscribed to the [Video update event](/web-core/local-user/events#video-update). Check your video track status. If the problem persists, please [contact us](https://dyte.io/contact) for the help. + +## Error code: 1603 + +- **Error message**: Incorrect device +- **Possible reason**: Indicates a problem with the device. +- **Possible solution**: Verify if you're connected to the correct device. See [Device update](/web-core/local-user/events#device-update). If the problem persists, please [contact us](https://dyte.io/contact) for the help. + +## Error code: 1604 + +- **Error message**: Failed to change device +- **Possible reason**: Indicates a problem with the device. +- **Possible solution**: Please [contact us](https://dyte.io/contact) for the help. + + + Web Core System Error Codes (0-16) + diff --git a/docs/ios-core-new/error-codes/error-code.mdx b/docs/ios-core-new/error-codes/error-code.mdx new file mode 100644 index 0000000000..cd3d03deec --- /dev/null +++ b/docs/ios-core-new/error-codes/error-code.mdx @@ -0,0 +1,46 @@ +--- +title: Debug System Error Codes +sidebar_position: 1 +--- + +:::info Note + +This information is intended for developers debugging or troubleshooting Dyte's web core system errors. + +::: + +Error codes are a standardized method for developers to convey application errors and issues to users or other developers in a structured manner. Error codes typically consist of a numerical or alphanumeric code and a description that provides more information about the error. + +This document lists Dyte's web core error codes that you may encounter in various scenarios. System error codes can arise in different parts of the system, and their descriptions may not always provide exact details. To address these codes effectively, you must first understand the programmatic and runtime contexts in which these errors occurred. + +## Error codes and format + +Error codes consist of four-digit numbers that are categorized by the type of error. The first two digits denote the module in which the error occurred, and the remaining digits specify the type of error. + +## Error codes prefixes + +Here is a list of error code prefixes corresponding to each Dyte modules: + +| **Module** | **Error Code Prefix** | +| ------------------------------ | --------------------- | +| DyteClient | 00xx | +| Controller | 01xx | +| RoomNodeClient | 02xx | +| HiveNodeClient | 03xx | +| SocketService | 04xx | +| Chat | 05xx | +| Plugins | 06xx | +| Polls | 07xx | +| Meta | 08xx | +| Permissions/Presets | 09xx | +| Recording | 10xx | +| Self (or local media handling) | 11xx | +| Participant | 12xx | +| Spotlight | 13xx | +| Remote Request | 14xx | +| Webinar | 15xx | +| Device | 16xx | + + + Web Core Debug System Error Codes + diff --git a/docs/ios-core-new/livestreaming.mdx b/docs/ios-core-new/livestreaming.mdx new file mode 100644 index 0000000000..9995e929ce --- /dev/null +++ b/docs/ios-core-new/livestreaming.mdx @@ -0,0 +1,59 @@ +--- +title: Livestreaming +sidebar_position: 10 +--- + +- Livestreaming is often used for events, such as concerts, conferences, and sports games, as well as for online classes, gaming, and social media platforms. +- Dyte uses LHLS to deliver low latency one way streams +- The Interactive Livestream product delivers interactivity via chat, polls, reactions etc +- Viewer can also be pulled in the livestream by the host using Stage Management APIs + +This topic talks about how you can use livestreaming properties, events, and functions. + +## Properties + +### Playlist URL + +`meeting.livestream.playbackUrl` - This URL allows you to watch the live stream. It is the location of the video playlist file and can be accessed through a web browser or any media player. + +### Livestream Status + +`meeting.livestream.status` - The current status of the livestream. This field can assume the following values: + +- IDLE +- STARTING +- LIVESTREAMING +- STOPPING + +### Viewer Count + +`meeting.livestream.viewerCount` - The number of people viewing the livestream, including hosts and viewers. + +## Methods + +Use the following methods to start and stop the livestreaming. + +### Start Livestream + +Users with the permission `canLivestream` set to true can start a livestream. + +`await meeting.livestream.start();` + +### Stop Livestream + +Users with the permission `canLivestream` set to true can stop a livestream. + +`await meeting.livestream.stop();` + +## Events + +Here is a list of events that the `meeting.livestream` module emits: + +| **Event** | **Description** | +| ------------------- | ------------------------------------------------------------------------------------------------------------- | +| `livestreamUpdate` | This event is triggered when the state of the livestream changes, specifically when it is started or stopped. | +| `viewerCountUpdate` | Emitted when a new viewer joins or a viewer leaves the livestream. | + + + Web Core Livestreaming + diff --git a/docs/ios-core-new/local-user/_category_.json b/docs/ios-core-new/local-user/_category_.json new file mode 100644 index 0000000000..2c78a8e824 --- /dev/null +++ b/docs/ios-core-new/local-user/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 6, + "label": "Local User", + "collapsible": true +} diff --git a/docs/ios-core-new/local-user/events.mdx b/docs/ios-core-new/local-user/events.mdx new file mode 100644 index 0000000000..eea96b78fd --- /dev/null +++ b/docs/ios-core-new/local-user/events.mdx @@ -0,0 +1,194 @@ +--- +title: Events +description: Local user events guide. +sidebar_position: 2 +tags: + - web-core + - local-user + - self + - self events +--- + +# Local User - Events + +You can subscribe to various events on the local user by calling +`meeting.self.on(EVENT_NAME)`. + +## Room joined + +Triggered when the room join event completes and now the `meeting` is ready to +produce and consume media. + +```ts +meeting.self.on('roomJoined', () => { + console.log( + 'User has joined the meeting and ready to produce and consume media' + ); +}); +``` + +## Room left + +Triggered when the local user leaves the meeting. + +```js +meeting.self.on('roomLeft', ({ state }) => { + // state is a string whose values are explained below + if (state === 'left') { + console.log('User has left the meeting'); + } +}); +``` + +Here are all the possible values of the `state` variable. + +| Event | Description | +| ---------- | ----------------------------------------------------------------------------------- | +| `left` | Participant has left the room. | +| `kicked` | Participant is removed from the meeting. | +| `ended` | Everyone is removed from the meeting, and the session has ended. | +| `rejected` | Participant's request to join the room is rejected (when you're in a waiting room). | + +## Video update + +Triggered when the user starts / stops the video using `enableVideo` or +`disableVideo` + +```ts +const videoElem = document.getElementById('my-video'); + +meeting.self.on('videoUpdate', async ({ videoEnabled, videoTrack }) => { + if (videoEnabled) { + const stream = new MediaStream(); + stream.addTrack(videoTrack); + videoElem.srcObject = stream; + videoElem.play(); + } else { + videoElem.stop(); + } +}); +``` + +## Audio update + +Triggered when the user starts / stops the audio using `enableAudio` or +`disableAudio` + +```ts +const audioElem = document.getElementById('my-audio'); + +meeting.self.on('audioUpdate', async ({ audioEnabled, audioTrack }) => { + if (audioEnabled) { + const stream = new MediaStream(); + stream.addTrack(audioTrack); + audioElem.srcObject = stream; + audioElem.play(); + } else { + audioElem.stop(); + } +}); +``` + +## Screenshare update + +Triggered when the user starts / stops the screen share using +`enableScreenShare()` or `disableScreenShare()`. + +```ts +const screenElem = document.getElementById('my-screen-share'); + +meeting.self.on( + 'screenShareUpdate', + async ({ screenShareEnabled, screenShareTracks }) => { + if (screenShareEnabled) { + const stream = new MediaStream(); + stream.addTrack(screenShareTracks.video); + screenElem.srcObject(stream); + await screenElem.play(); + } else { + await screenElem.stop(); + } + } +); +``` + +## Device update + +Subscribe to the `deviceUpdate` event to handle the changing video, audio and +speaker devices + +```ts +meeting.self.on('deviceUpdate', ({ device }) => { + // handle microphone device change + if (device.kind === 'audioinput') { + console.log('mic change', device); + } + // handle camera device change + if (device.kind === 'videoinput') { + console.log('camera change', device); + } + // handle speaker device change + if (device.kind === 'audiooutput') { + console.log('speaker change', device); + } +}); +``` + +## Network quality score + +Subscribe to the `mediaScoreUpdate` event to monitor network + +```ts +meeting.self.on('mediaScoreUpdate', ({ kind, isScreenshare, score }) => { + if (kind === 'video') { + console.log( + `Your ${isScreenshare ? 'screenshare' : 'video'} quality score is `, + score + ); + } + + if (kind === 'audio') { + console.log('Your audio quality score is ', score); + } + + if (score < 5) { + console.log('Your media quality is poor'); + } +}); +``` + +## Webinar Stage events + +In a `WEBINAR` setup, below events can be used to bring a user on to stage + +| **Event** | **Description** | +| -------------------------- | ---------------------------------------------------------------------------------------- | +| `waitlisted` | Emitted when the user has been added to the waitlist. | +| `joinStageRequestAccepted` | Emitted to all host users, when a host accepts a user's request to join webinar meeting. | +| `joinStageRequestRejected` | Emitted to all host users, when a host rejects a user's request to join webinar meeting. | +| `removedFromStage` | Emitted when the user has been kicked from the webinar meeting. | +| `stageJoined` | Emitted when the user has joined the webinar meeting. | +| `stageLeft` | Emitted when the user has left the webinar meeting. | +| `peerRequestToJoinStage` | Emitted when a user has requested to join the webinar meeting. | +| `peerRejectedToJoinStage` | Emitted when the user's request to join the meeting has been rejected. | +| `peerAcceptedToJoinStage` | Emitted when the user's request to join the meeting has been accepted | +| `peerStoppedPresenting` | Emitted when a participant stops presenting in the webinar meeting. | +| `peerStartedPresenting` | Emitted when a participant starts presenting in the webinar meeting. | + + + Web Core Events + + +## Permission Updates + +Triggered when permissions are updated dynamically by a privileged user + +Subscribe to `chatUpdate`, `pollsUpdate`, `pluginsUpdate` or `*` for any kind of permission updates +Example: + +```ts +meeting.self.permissions.on('chatUpdate', () => { + // Chat permissions are updated + // check meeting.self.permissions for updated permissions +}); +``` diff --git a/docs/ios-core-new/local-user/extras.mdx b/docs/ios-core-new/local-user/extras.mdx new file mode 100644 index 0000000000..f049449cf3 --- /dev/null +++ b/docs/ios-core-new/local-user/extras.mdx @@ -0,0 +1,97 @@ +--- +title: Other Methods +description: Methods to manage the local user. +sidebar_position: 5 +tags: + - web-core + - local-user + - self + - methods +--- + +## Update media resolution at runtime + +### Camera + +meeting.self.updateVideoConstraints(resolution) + +Example + +```ts +meeting.self.updateVideoConstraints({ + width: { ideal: 1920 }, + height: { ideal: 1080 }, +}); +``` + +### Screenshare + +meeting.self.updateScreenshareConstraints(resolution) + +Example + +```ts +meeting.self.updateScreenshareConstraints({ + width: { ideal: 1920 }, + height: { ideal: 1080 }, +}); +``` + +## Using Middlewares + +Middlewares are add-ons that you can use to add effects and filters to your +audio and video streams with ease. The `meeting.self` namespace exposes methods +to add and remove these middlewares. Read more about how to work with +middlewares [here](https://dyte.io/blog/streams-blog/). + +### Create a middleware + +```ts +function RetroTheme() { + return (canvas, ctx) => { + ctx.filter = 'grayscale(1)'; + ctx.shadowColor = '#000'; + ctx.shadowBlur = 20; + ctx.lineWidth = 50; + ctx.strokeStyle = '#000'; + ctx.strokeRect(0, 0, canvas.width, canvas.height); + }; +} +``` + +### Working with video middlewares + +```ts +// Add the video middleware +meeting.self.addVideoMiddleware(RetroTheme); + +// Remove the video middleware +meeting.self.removeVideoMiddleware(RetroTheme); +``` + +### Working with audio middlewares + +```ts +// Add the audio middleware +meeting.self.addAudioMiddleware(YourAudioMiddleware); + +// Remove the audio middleware +meeting.self.removeAudioMiddleware(YourAudioMiddleware); +``` + +## Pinning & unpinning + +You can pin or unpin yourself given you have the appropriate permissions. You +can check the pinned status of the local user using `meeting.isPinned`. + +```ts +meeting.self.pin(); +``` + +```ts +meeting.self.unpin(); +``` + + + Web Core Other Methods + diff --git a/docs/ios-core-new/local-user/introduction.mdx b/docs/ios-core-new/local-user/introduction.mdx new file mode 100644 index 0000000000..3fd7397a86 --- /dev/null +++ b/docs/ios-core-new/local-user/introduction.mdx @@ -0,0 +1,148 @@ +--- +title: Introduction +description: Local user setup guide. +sidebar_position: 1 +tags: + - web-core + - local-user + - self +--- + +# Introduction + +Accessible via `self` key within the `meeting` object, the local user object consists of all the information related to the current participant and methods to configure media and other states. + +## Properties + +Here is a list of properties that local user provides: + +**Metadata** + +- `userId`: User ID of the local user. +- `customParticipantId`: Identifier provided by the developer while adding the + participant. +- `organizationId`: The ID of the organization the meeting is created from. +- `name`: Contains Name of the local user. +- `picture`: Display picture URL for the local user. +- `permissions`: The permissions related to various capabilities for the local user defined by the preset + +**Media**: + +- `mediaPermissions`: The current audio and video permissions given by the local + user. +- `audioTrack`: The audio track for the local user. +- `videoTrack`: The video track for the local user. +- `screenShareTracks`: The screen share video and audio tracks for the local + user. +- `audioEnabled`: A boolean value indicating if the audio currently enabled. +- `videoEnabled`: A boolean value indicating if the video currently enabled. +- `screenShareEnabled`: A boolean value indicating if the screen share is + currently enabled. + +**States**: + +- `isPinned`: A boolean value indicating if the local user is pinned or not. +- `roomJoined`: A boolean value indicating if the local user is in the meeting +- `roomState`: Indicates the state of the user in the meeting. It + can take the following values: + + ```ts + "init" | "joined" | "waitlisted" | "rejected" | "kicked" | "left" | "ended" + ``` + +```mermaid +stateDiagram-v2 + direction LR + classDef END fill:#ef4444,color:#fff,stroke:#ef4444; + + [*] --> init + init --> joined + init --> waitlisted + waitlisted --> joined + waitlisted --> rejected + joined --> kicked + joined --> left + joined --> ended + + class kicked,left,ended,rejected END +``` + +
+ + + +## Change the name of the local user + +Change the user's name by calling `setName` method. The changed name will +reflect across all participants ONLY if the change happens before joining the +meeting. + +```ts +await meeting.self.setName('New Name'); +``` + +## Media + +### Mute/Unmute microphone + +```ts +// Mute Audio +await meeting.self.disableAudio(); + +// Unmute Audio +await meeting.self.enableAudio(); + +// Get current status +meeting.self.audioEnabled; +``` + +```mermaid +flowchart LR + classDef basic fill:white; + + eam("enableAudio()") --> success("Emits audioUpdate event on self") + eam -. possibly .-> indirect("Update mediaPermissions.audio with mediaPermissionUpdate event") + + class eam basic; +``` + +### Enable/Disable camera + +```ts +// Disable Video +await meeting.self.disableVideo(); + +// Enable Video +await meeting.self.enableVideo(); + +// Get current status +meeting.self.videoEnabled; +``` + +```mermaid +flowchart LR + classDef basic fill:white; + + eam("enableVideo()") --> success("Emits videoUpdate event on self") + eam -. possibly .-> indirect("Update mediaPermissions.video with mediaPermissionUpdate event") + + class eam basic; +``` + +### Enable / Disable Screen share + +```ts +// Enable Screenshare +await meeting.self.enableScreenShare(); + +// Disable Screenshare +await meeting.self.disableScreenShare(); + +// Get current status +meeting.self.screenShareEnabled; +``` + + + + Web Core Introduction + diff --git a/docs/ios-core-new/local-user/manage-media-devices.mdx b/docs/ios-core-new/local-user/manage-media-devices.mdx new file mode 100644 index 0000000000..9b29e380bb --- /dev/null +++ b/docs/ios-core-new/local-user/manage-media-devices.mdx @@ -0,0 +1,49 @@ +--- +title: Manage Media Devices +description: Local user media guide to manage media permissions. +sidebar_position: 3 +tags: + - web-core + - local-user + - self + - self events +--- + +# Manage Media Devices + +Media devices represents the hardware for the camera, microphone and speaker +devices. To get the list of media devices that are currently being used, you can +use the following methods: + +```js +// Get all media devices +const devices = meeting.self.getAllDevices(); + +// Get all audio devices +const audioDevices = meeting.self.getAudioDevices(); + +// Get all video devices +const videoDevices = meeting.self.getVideoDevices(); + +// Get all speakers +const speakerDevices = meeting.self.getSpeakerDevices(); + +// Get device by ID +const device = meeting.self.getDeviceById('12345', 'audio'); + +// Fetch current media devices being used +const currentDevices = meeting.self.getCurrentDevices(); +``` + +## Set device + +To set a device as an active device, you can call `setDevice` method. This takes +a `MediaDeviceInfo` object, and replaces the same `kind` device. + +```js +meeting.self.setDevice(device); +``` + + + Web Core Manage Media Devices + diff --git a/docs/ios-core-new/local-user/media-permission-errors.mdx b/docs/ios-core-new/local-user/media-permission-errors.mdx new file mode 100644 index 0000000000..542bdb9014 --- /dev/null +++ b/docs/ios-core-new/local-user/media-permission-errors.mdx @@ -0,0 +1,43 @@ +--- +title: Media Permission Errors +description: Local user media guide to local media permission errors. +sidebar_position: 4 +tags: + - web-core + - local-user + - self + - self events +--- + +# Media Permission Errors + +This event is triggered when Dyte fails to acquire the user's local media +(camera and/or microphone) or user revokes the permission for media devices. + +Your application can catch these errors like below: + +``` +meeting.self.on('mediaPermissionError', ({ + message, + kind +}) => { + console.log(`Failed to capture ${kind}: ${message}`); +}); +``` + +This event shares information that can be used to show appropriate message for +the user. + +Possible values for **message** are + + DENIED - Permission was denied by the user + + SYSTEM_DENIED - Permission was denied by the system + + COULD_NOT_START - Failed to capture media stream from the hardware + +Possible values for **kind** - `audio`, `video`, `screenshare` + + + Web Core Media Permission Errors + diff --git a/docs/ios-core-new/participants/_category_.json b/docs/ios-core-new/participants/_category_.json new file mode 100644 index 0000000000..1506bb147c --- /dev/null +++ b/docs/ios-core-new/participants/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 7, + "label": "Remote Participants", + "collapsible": true +} diff --git a/docs/ios-core-new/participants/events.mdx b/docs/ios-core-new/participants/events.mdx new file mode 100644 index 0000000000..5f47590cb6 --- /dev/null +++ b/docs/ios-core-new/participants/events.mdx @@ -0,0 +1,192 @@ +--- +title: Events +description: Event handling for participants. +sidebar_position: 3 +tags: + - web-core + - participants + - self +--- + +You can subscribe to events for all participants using +`meeting.participants.on()` method. Here are the supported events: + +### View mode change + +Triggered when the View mode changes + +```ts +meeting.participants.on( + 'viewModeChanged', + ({ viewMode, currentPage, pageCount }) => { + console.log('view mode changed', viewMode); + } +); +``` + +### Page change + +```ts +meeting.participants.on( + 'pageChanged', + ({ viewMode, currentPage, pageCount }) => { + console.log('page changed', currentPage); + } +); +``` + +### Active speaker + +This event is triggered when a participant becomes `active` when they starts to +speak. + +```ts +meeting.participants.on('activeSpeaker', (participant) => { + console.log(`${participant.id} is currently speaking`); +}); +``` + +## Events on all participants + +Instead of subscribing to individual participant events, you can subscribe to a +participant map, such as `joined` & `active` and get updated when any of the +participant emits an event. + +If you want to subscribe to participants when they become `active`, you can do +so by subscribing to `meetings.participants.active.on('participantJoined')` + +### Participant joined + +Trigger an event when any participant joins the meeting. + +```ts +meeting.participants.joined.on('participantJoined', (participant) => { + console.log(`A participant with id "${participant.id}" has joined`); +}); +``` + +### Participant left + +Trigger an event when any participant leaves the meeting. + +```ts +meeting.participants.joined.on('participantLeft', (participant) => { + console.log(`A participant with id "${participant.id}" has left the meeting`); +}); +``` + +### Participant pinned + +Trigger an event when a participant is pinned. + +```ts +meeting.participants.joined.on('pinned', (participant) => { + console.log(`Participant with id "${participant.id}" was pinned`); +}); +``` + +### Participant unpinned + +Trigger an event when a participant is unpinned. + +```ts +meeting.participants.joined.on('unpinned', (participant) => { + console.log(`Participant with id "${participant.id}" was unpinned`); +}); +``` + +### Video update + +Trigger an event when any participant starts / stops video. + +```ts +meeting.participants.joined.on('videoUpdate', (participant) => { + console.log( + `A participant with id "${participant.id}" updated their video track in the meeting` + ); + // Use the video track if it exists + if (participant.videoEnabled) { + // participant.videoTrack + } else { + // handle stop video + } +}); +``` + +### Audio update + +Trigger an event when any participant starts / stops audio. + +```ts +meeting.participants.joined.on('audioUpdate', (participant) => { + console.log( + `A participant with id "${participant.id}" updated their audio track in the meeting` + ); + // Use the audio track if it exists + if (participant.audioEnabled) { + // participant.audioTrack + } else { + // handle stop audio + } +}); +``` + +### Screen share update + +Trigger an event when any participant starts / stops screen share. + +```ts +meeting.participants.joined.on('screenShareUpdate', (participant) => { + console.log( + `A participant with id "${participant.id}" updated their screen share in the meeting` + ); + // Use the screen share track if it exists + if (participant.screenShareEnabled) { + // participant.screenShareTrack + } else { + // handle stop screen share + } +}); +``` + +## Network quality score + +Subscribe to the `mediaScoreUpdate` event to monitor network + +```ts +meeting.participants.joined.on( + 'mediaScoreUpdate', + ({ participantId, kind, isScreenshare, score }) => { + if (kind === 'video') { + console.log( + `Participant ${participantId}'s ${ + isScreenshare ? 'screenshare' : 'video' + } quality score is `, + score + ); + } + + if (kind === 'audio') { + console.log( + `Participant ${participantId}'s audio quality score is `, + score + ); + } + + if (score < 5) { + console.log(`Participant ${participantId}'s media quality is poor`); + } + } +); +``` + +## Events for specific participant + +If you want to subscribe to above events but for a specific participant only, +you can do so by binding event to `meeting.participants.joined.get(peerId).on()` +method. where the `peerId` is the id of the participant that you want to watch. + + + + Web Core Participant Events + diff --git a/docs/ios-core-new/participants/participant-object.mdx b/docs/ios-core-new/participants/participant-object.mdx new file mode 100644 index 0000000000..5850eb11e8 --- /dev/null +++ b/docs/ios-core-new/participants/participant-object.mdx @@ -0,0 +1,119 @@ +--- +title: Participant Object +description: The object corresponding to a particular participant. +sidebar_position: 2 +slug: /participants/participant-object +tags: + - web-core + - participants + - participant +--- + +# Participant Object + +The `participant` object consists of all the information related to a particular +participant. For instance, it contains a participants video/audio/screenshare +stream, and the participant's name. It also contains state variables that +indicate whether a participant's camera is on or off, and whether they are muted +or unmuted. Head over to [DyteParticipant](../reference/DyteParticipant.md) for +a detailed reference. + +The participant object has the following properties. + +**Media**: + +- `videoEnabled`: Set to true if the participant's camera is on. +- `audioEnabled`: Set to true if the participant is unmuted. +- `screenShareEnabled`: Set to true if the participant is sharing their screen. +- `videoTrack`: The video track of the participant. +- `audioTrack`: The audio track of the participant. +- `screenShareTracks`: The video and audio (if any) track of the participant's + screen share stream. + +**Metadata**: +- `id`: The `participantId` of the participant (aka `peerId`). +- `userId`: The `userId` of the participant. +- `name`: The participant's name. +- `picture`: The participant's picture (if any). +- `clientSpecificId`: An arbitrary ID that can be set to identify the + participant. +- `isPinned`: Set to true if the participant is pinned. +- `presetName`: Name of the preset associated with the participant. + +The participant object is an event emitter, so you can set listeners on this +object for events such as video and audio updates. For instance, to fire a +callback when a participant toggles their mic, you can subscribe to the +following events. + +```ts +meeting.participants.joined + .get(participantId) + .on('audioUpdate', ({ audioEnabled, audioTrack }) => { + // This will only be fired on mic toggles for the participant with ID `participantId` + console.log( + 'The participant with id', + participantId, + 'has toggled their mic to', + audioEnabled + ); + }); +``` + +The events emitted by all participant objects are also re-emitted by all the +maps in `meeting.participants`. Therefore, you can add a listener to +`meeting.participants.joined` for the `audioUpdate` event. For instance, the +same code above can be re-implemented as follows. + +```ts +meeting.participants.joined.on( + 'audioUpdate', + (participant, { audioEnabled, audioTrack }) => { + // This will be fired on mic toggles for all participants in the meeting + console.log( + 'The participant with id', + participant.id, + 'has toggled their mic to', + audioEnabled + ); + } +); +``` + +Read more about the participant events in the +[events](/web-core/participants/events) section in the API reference. + +## Host controls methods + +If you (the local user) have the relevant permissions in the meeting, you can +disable a participant's video/audio streams, or even remove them from the +meeting. + +```ts +const participant = meeting.participants.joined.get(participantId); + +// To disable a participant's video stream +participant.disableVideo(); + +// To disable a participant's audio stream +participant.disableAudio(); + +// To kick a participant from the meeting +participant.kick(); +``` + +You can also `pin` or `unpin` a participant in the meeting. All "pinned" +participants are added to the `meeting.participants.pinned` map. + +```ts +const participant = meeting.participants.joined.get(participantId); + +// Pin a participant to the meeting. +await participant.pin(); + +// Unpin a participant in the meeting. +await participant.unpin(); +``` + + + Web Core The participant object + diff --git a/docs/ios-core-new/participants/permissions.mdx b/docs/ios-core-new/participants/permissions.mdx new file mode 100644 index 0000000000..dec9f4db92 --- /dev/null +++ b/docs/ios-core-new/participants/permissions.mdx @@ -0,0 +1,52 @@ +# Permissions + +Permissions for a participant are defined by the preset. However they can updated in meeting by calling `updatePermissions` for remote participants + +## Find the target participants + +Permissions can be updated for either a single participant or multiple participant at once. Find the `id`s of the participant whose permissions need to be updated + +```ts +const participantIds = meeting.participants.joined + .toArray() + .filter((e) => { + return e.name.startsWith('John'); + }) + .map((p) => p.id); +``` + +## Update permissions + +```ts +// Allow file upload permissions in public chat +const newPermissions = { chat: { public: { files: true } } }; + +meeting.participants.updatePermissions(participantIds, newPermissions); +``` + +Allowed values for update permissions objects. Every field is optional + +```ts +interface UpdatedPermissions { + polls?: { + canCreate?: boolean; + canVote?: boolean; + }; + plugins?: { + canClose?: boolean; + canStart?: boolean; + }; + chat?: { + public?: { + canSend?: boolean; + text?: boolean; + files?: boolean; + }; + private?: { + canSend?: boolean; + text?: boolean; + files?: boolean; + };; + }; +} +``` diff --git a/docs/ios-core-new/participants/pip.mdx b/docs/ios-core-new/participants/pip.mdx new file mode 100644 index 0000000000..56d29a0dbb --- /dev/null +++ b/docs/ios-core-new/participants/pip.mdx @@ -0,0 +1,42 @@ +--- +title: Picture-in-Picture +description: 'Events, methods and data pertaining to browser picture in picture mode' +sidebar_position: 3 +tags: + - web-core + - participants + - participant +--- + +Picture-in-Picture API allows you to render `meeting.participants.active` participant's video as a floating tile outside of the current webpage's context. + +Supported in Chrome/Edge/Chromium based browsers + +## Methods + +### Check if supported + +Use the boolean value at `meeting.participants.pip.isSupported` to check if the browser supports PIP capabilities + +### Initialization + +Call `meeting.participant.pip.init()` to activate PIP mode. Optionally you can pass height and width the configure the size of the PIP tile + +```ts +meeting.participant.pip.init({ + width: 360, + height: 360, +}); +``` + +### Enable + +`meeting.participant.pip.enable()` to enable PIP mode if disabled + +### Disable + +`meeting.participant.pip.disable()` to enable PIP mode if enabled + + + Web Core Picture-in-Picture + diff --git a/docs/ios-core-new/participants/remote-participants.mdx b/docs/ios-core-new/participants/remote-participants.mdx new file mode 100644 index 0000000000..10ec193fac --- /dev/null +++ b/docs/ios-core-new/participants/remote-participants.mdx @@ -0,0 +1,117 @@ +--- +title: Participant Maps +description: 'Events, methods and data pertaining to meeting participants.' +sidebar_position: 1 +slug: /participants/ +tags: + - web-core + - participants + - participant +--- + +# Participant Maps + +The data regarding all meeting participants is stored under +`meeting.participants`. These **does not** include the local user. Use the +methods and events to consume the participants data. For example, to get all the +participants who joined the meeting: + +```ts +// get all joined participants +const joinedParticipants = meeting.participants.joined; +``` + +The `meeting.participants` object has the following **maps** of participants + +- **joined**: A map that contains all the participants who are currently in the meeting + except the local user +- **waitlisted**: A map that contains all the participants waiting to join the + meeting. +- **active**: A map that contains all the participants except the local user whose media is subscribed to i.e + participants are supposed to be on the screen at the moment except the local user +- **pinned**: A map that contains all the pinned participants of the meeting. + +Therefore if you were to make a video / audio grid of participants, you'd use the `active` +map, but to display the list of all participants in the meeting you'd use the `joined` map. + +Each participant in each of the `joined`, `waitlisted`, `active`, and `pinned` +maps is of type [`DyteParticipant`](../reference/DyteParticipant.md). Read more +about each individual `participant` object +[here](../participants/participant-object.mdx). + +Each of these maps are of type +[`DyteParticipantMap`](../reference/DyteParticipantMap.md), and therefore emit a +`participantJoined` event when a participant is added to the map, and a +`participantLeft` event when a participant leaves the map. For instance, to +listen for when a participant gets pinned in the meeting, you can use the +following snippet: + +```ts +meeting.participants.pinned.on('participantJoined', (participant) => { + console.log(`Participant ${participant.name} got pinned`); +}); +``` + +--- + +and these other properties + +- `count`: The number of participants who are joined in the meeting. +- `pageCount`: Number of pages available in paginated mode. +- `maxActiveParticipantsCount`: The maximum number of participants that can be + present in the active state. +- `lastActiveSpeaker `: This stores the `participantId` of the last participant + who spoke in the meeting. + +## Set participant view mode + +The view mode indicates whether the participants are populated in `ACTIVE_GRID` +mode or `PAGINATED` mode. In `ACTIVE_GRID` mode, the participants are +automatically replaced in `meeting.participants.active`, based on who is +speaking or who has their video turned on. + +In `PAGINATED` mode, the participants in `meeting.participants.active` will be +fixed. Only when you call the `meeting.participants.setPage(pageNumber)` method, +it will replace the `active` participants with a different set of participants. + +You can change the participant view between `ACTIVE_GRID` and `PAGINATED` mode +using the following method. This will trigger `viewModeChanged` event as a side +affect. + +```ts +// set the view mode to paginated +await meeting.participants.setViewMode('PAGINATED'); + +// set the view mode to active grid +await meeting.participants.setViewMode('ACTIVE_GRID'); +``` + +### Set page number in paginated mode + +The `setPage()` method allows you to switch between pages of participants +present in the meeting. + +```ts +// switch to second page +await meeting.participants.setPage(2); +``` + +## Waiting room methods + +The `acceptWaitingRoomRequest()` method accepts requests from waitlisted +participants if user has appropriate permissions. + +```ts +await meeting.participants.joined.acceptWaitingRoomRequest(participantId); +``` + +The `rejectWaitingRoomRequest()` method requests from waitlisted participants if +user has appropriate permissions. + +```ts +await meeting.participants.joined.rejectWaitingRoomRequest(participantId); +``` + + + Web Core Participants + diff --git a/docs/ios-core-new/plugins/_category_.json b/docs/ios-core-new/plugins/_category_.json new file mode 100644 index 0000000000..5772922e2f --- /dev/null +++ b/docs/ios-core-new/plugins/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 8, + "label": "Plugins", + "collapsible": true +} diff --git a/docs/ios-core-new/plugins/disable-plugin.mdx b/docs/ios-core-new/plugins/disable-plugin.mdx new file mode 100644 index 0000000000..38e250d212 --- /dev/null +++ b/docs/ios-core-new/plugins/disable-plugin.mdx @@ -0,0 +1,75 @@ +--- +title: Functions to disable plugins +description: Methods on a plugin in a meeting. +sidebar_position: 3 +tags: + - web-core + - plugins +--- + +# Functions to disable plugins + +Each plugin in `meeting.plugins` object is of type +[`DytePlugin`](./introduction) and exposes the following functions to disable +plugins. + +## Remove Plugin View + +This method is used for cleaning up event listeners attached to an iframe. It +must be used before the iframe is removed from the DOM. + +```ts +const plugins = meeting.plugins.all.toArray(); + +plugins.forEach(async (plugin: DytePlugin) => { + await plugin.removePluginView(); +}); +``` + +### Deactivate Plugins + +The `deactivate()` method deactivates the plugin for all users in the meeting. +When you deactivate a plugin, it gets removed from the active plugins map and +can only be accessed from `meeting.plugins.all`. + +The snippet below displays all active plugins and deactivate a plugin on click. + +```ts +const plugins = meeting.plugins.active.toArray(); + +plugins.forEach((plugin: DytePlugin) => { + const button = document.createElement('button'); + button.innerText = `Deactivate ${plugin.name}`; + button.onclick = async () => { + await plugin.deactivate(); + }; + document.body.appendChild(button); +}); +``` + +Here is another way you can deactivate a plugin. + +```ts +const plugins = meeting.plugins.active.toArray(); +const plugin = plugins.find((p) => p.name === 'YouTube'); + +await plugin?.deactivate(); +``` + +### ~~Disable Plugins~~ + +**_Deprecated_** + +The `disable()` method deactivates the plugin for the current user. This does +not affect other users in the meeting. + +```ts +const plugins = meeting.plugins.active.toArray(); +const plugin = plugins.find((p) => p.name === 'YouTube'); + +await plugin?.disable(); +``` + + + Web Core Functions to disable plugins + diff --git a/docs/ios-core-new/plugins/enable-plugin.mdx b/docs/ios-core-new/plugins/enable-plugin.mdx new file mode 100644 index 0000000000..56e0e35c17 --- /dev/null +++ b/docs/ios-core-new/plugins/enable-plugin.mdx @@ -0,0 +1,76 @@ +--- +title: Functions to enable plugins +description: Methods on a plugin in a meeting. +sidebar_position: 2 +tags: + - web-core + - plugins +--- + +# Functions to enable plugins + +Each plugin in `meeting.plugins` object is of type +[`DytePlugin`](./introduction) and exposes the following functions to enable +plugins. + +### Add Plugin View + +This method adds the communication layer between the plugin inside the iframe and +the core application (meeting object) in the main window. + +```ts +const plugins = meeting.plugins.all.toArray(); + +plugins.forEach(async (plugin: DytePlugin) => { + const iframe = document.createElement('iframe'); + await plugin.addPluginView(iframe); +}); +``` + +### Activate Plugins + +The `activate()` method activates a plugin for all users in the meeting. When +you activate a plugin, it moves into the active plugins map and can be accessed +from `meeting.plugins.active`. + +The snippet below displays all plugins and activates a plugin on click. + +```ts +const plugins = meeting.plugins.all.toArray(); + +plugins.forEach((plugin: DytePlugin) => { + const button = document.createElement('button'); + button.innerText = plugin.name; + button.onclick = async () => { + await plugin.activate(); + }; + document.body.appendChild(button); +}); +``` + +Here is another way you can activate a plugin. + +```ts +const plugins = meeting.plugins.all.toArray(); +const plugin = plugins.find((p) => p.name === 'YouTube'); + +await plugin?.activate(); +``` + +### ~~Enable Plugins~~ + +**_Deprecated_** + +The `enable()` method enables a plugin for the current user. This does not +affect other users in the meeting. + +```ts +const plugins = meeting.plugins.all.toArray(); +const plugin = plugins.find((p) => p.name === 'YouTube'); + +await plugin?.enable(); +``` + + + Web Core Functions to enable plugins + diff --git a/docs/ios-core-new/plugins/extra.mdx b/docs/ios-core-new/plugins/extra.mdx new file mode 100644 index 0000000000..2533499681 --- /dev/null +++ b/docs/ios-core-new/plugins/extra.mdx @@ -0,0 +1,47 @@ +--- +title: Other methods +description: Methods on a plugin in a meeting. +sidebar_position: 4 +tags: + - web-core + - plugins +--- + +## Subscribe to events from a plugin + +A plugin emits the following events: + +- `enabled` - Emitted when a plugin is enabled. +- `closed` - Emitted when a plugin is closed. +- `dyteStateUpdate` - Emitted when the state of the plugin has changed. +- `ready` - Emitted when the plugin is ready to exchange data with client SDK. +- `toggleViewMode` - Emitted when the control is toggled for users with + view-only permissions for a plugin. + +```ts +const pluginId = '...'; +const plugin = meeting.plugins.active.get(pluginId); +plugin.on('enabled', () => { + console.log('The plugin has been enabled'); +}); +``` + +## Send data to the plugin + +You can send data (type `any`) to a plugin using the `sendData()` method. This +method comes in handy when building your own plugin. + +```ts +const pluginId = '...'; +const plugin = meeting.plugins.active.get(pluginId); +plugin.on('ready', () => { + plugin.sendData({ + eventName: 'my-custom-event', + data: 'Hello world', + }); +}); +``` + + + Web Core Other methods + diff --git a/docs/ios-core-new/plugins/introduction.mdx b/docs/ios-core-new/plugins/introduction.mdx new file mode 100644 index 0000000000..4e2682c396 --- /dev/null +++ b/docs/ios-core-new/plugins/introduction.mdx @@ -0,0 +1,84 @@ +--- +title: Introduction +description: Manage plugins in a meeting. +sidebar_position: 1 +tags: + - web-core + - plugins +--- + +# Introduction + +Plugins are one-click add-ons that can make your meetings more immersive and +collaborative. Dyte provides a bunch of inbuilt plugins to choose from, you can +also build your own plugins using the Plugin SDK. + +The meeting plugins can be accessed from the `meeting.plugins` object, it +exposes the following. + +| Property | Type | Description | +| -------- | ---- | -------------------------------------- | +| active | Map | All plugins that are currently in use. | +| all | Map | All plugins the meeting has access to. | + +Each plugin in the map is of type `DytePlugin`. + +```ts +interface DytePlugin { + baseURL: string; + createdAt: string; + description: string; + id: string; + name: string; + config: PluginConfig | undefined; + organizationId: string; + picture: string; + private: boolean; + published: boolean; + staggered: boolean; + tags: string[]; + type: string; + updatedAt: string; +} +``` + +Once a plugin is activated, `plugin.config` get's populated. It is of type +`PluginConfig`. + +```ts +interface PluginConfig { + name: string; + pluginId: string; + version: string; + description: string; + author?: string; + repository?: string; + tags?: string[]; + picture?: string; + url?: string; + files: { + include: string[]; + exclude?: string[]; + }; + views?: { + [viewId: string]: { + url: string; + suggestedPosition: string; + }; + }; + contentScript?: string; + permissions?: { + [key: string]: { + default: boolean; + description: string; + }; + }; + config?: { + [key: string]: string; + }; +} +``` + + + Web Core Introduction + diff --git a/docs/ios-core-new/polls/_category_.json b/docs/ios-core-new/polls/_category_.json new file mode 100644 index 0000000000..fe2eed0b04 --- /dev/null +++ b/docs/ios-core-new/polls/_category_.json @@ -0,0 +1,5 @@ +{ + "position": 10, + "label": "Polls", + "collapsible": true +} diff --git a/docs/ios-core-new/polls/creating-a-poll.mdx b/docs/ios-core-new/polls/creating-a-poll.mdx new file mode 100644 index 0000000000..d333b245db --- /dev/null +++ b/docs/ios-core-new/polls/creating-a-poll.mdx @@ -0,0 +1,36 @@ +--- +title: Creating a poll +description: Create polls in a meeting. +sidebar_position: 2 +tags: + - web-core + - polls + - create +--- + +# Creating a poll + +A new poll can be created using the `create` method from the +[`meeting.polls`](./introduction) object. The `meeting.polls.create()` method +accepts the following params. + +| Param | Type | Default Value | Required | Description | +| --------- | -------- | ------------- | -------- | ------------------------------------------ | +| question | string | - | yes | The question that is to be voted for. | +| options | string[] | - | yes | The options of the poll. | +| anonymous | boolean | false | no | If true, the poll votes are anonymous. | +| hideVotes | boolean | false | no | If true, the votes on the poll are hidden. | + +The following snippet creates a poll where votes are anonymous. + +```ts +await meeting.poll.create( + 'Are you an early bird or a night owl?', + ['Early bird', 'Night owl'], + true +); +``` + + + Web Core Creating a poll + diff --git a/docs/ios-core-new/polls/introduction.mdx b/docs/ios-core-new/polls/introduction.mdx new file mode 100644 index 0000000000..b4c90d2c3f --- /dev/null +++ b/docs/ios-core-new/polls/introduction.mdx @@ -0,0 +1,44 @@ +--- +title: Introduction +description: 'Create, receive and interact with polls in a meeting.' +sidebar_position: 1 +tags: + - web-core + - polls +--- + +# Introduction + +The meetings polls object can be accessed using `meeting.polls`. It provides +methods to create polls, vote, and more. + +`meeting.polls.items` returns an array of all polls created in a meeting, where +each element is an object of type `Poll`. + +The type `Poll` is defined in the following manner. + +```ts +interface Poll { + id: string; + question: string; + options: PollOption[]; + anonymous: boolean; + hideVotes: boolean; + createdBy: string; + createdByUserId: string; + voted: string[]; // stores participant ID +} + +interface PollOption { + text: string; + votes: { + id: string; // stores participant ID + name: string; + }[]; + count: number; +} +``` + + + Web Core Introduction + diff --git a/docs/ios-core-new/polls/other-poll-functions.mdx b/docs/ios-core-new/polls/other-poll-functions.mdx new file mode 100644 index 0000000000..536af15ce2 --- /dev/null +++ b/docs/ios-core-new/polls/other-poll-functions.mdx @@ -0,0 +1,52 @@ +--- +title: Other poll functions +description: Other poll functions +sidebar_position: 4 +tags: + - web-core + - polls + - results + - updates +--- + +# Other poll functions + +## View poll results + +**The total votes on a poll can be accessed in the following manner.** + +```ts +const poll = meeting.polls.items[0]; +const votes = poll.voted; +``` + +`votes` is an array of participant ID's (`meeting.participant.id`). + +**The total votes on a poll option can be accessed in the following manner.** + +```ts +const poll = meeting.polls.items[0]; +const options = poll.options; +``` + +`options` returns an array of objects, where each object is of type +[`PollObject`](./introduction). + +## Get notified when a poll is created or updated + +An event is fired each time `meeting.polls.items` is updated or created. User +can listen for this to get the updated list of polls. the response object +contains the following properties. + +- `polls`: List of all polls. +- `newPoll`: A boolean variable which is true when a new poll has been created. + +```ts +meeting.polls.on('pollsUpdate', ({ polls, newPoll }) => { + console.log(polls, newPoll); +}); +``` + + + Web Core Other poll functions + diff --git a/docs/ios-core-new/polls/voting-on-a-poll.mdx b/docs/ios-core-new/polls/voting-on-a-poll.mdx new file mode 100644 index 0000000000..e99ef790eb --- /dev/null +++ b/docs/ios-core-new/polls/voting-on-a-poll.mdx @@ -0,0 +1,31 @@ +--- +title: Voting on a poll +description: Voting on polls in a meeting. +sidebar_position: 3 +tags: + - web-core + - polls + - votes +--- + +# Voting on a poll + +The `meeting.polls.vote()` method can be used to register a vote on a poll. It +accepts the following params. + +| Param | Type | Default Value | Required | Description | +| ----- | ------ | ------------- | -------- | ------------------------------------------ | +| id | string | - | yes | The ID of the poll that is to be voted on. | +| index | number | - | yes | The index of the option. | + +The following snippet votes for the 1st option on the 1st poll created in the +meeting. + +```ts +const poll = meeting.polls.items[0]; +await meeting.poll.vote(poll.id, 0); +``` + + + Web Core Voting on a poll + diff --git a/docs/ios-core-new/pre-call/1-media-preview.mdx b/docs/ios-core-new/pre-call/1-media-preview.mdx new file mode 100644 index 0000000000..ac1dc38bbd --- /dev/null +++ b/docs/ios-core-new/pre-call/1-media-preview.mdx @@ -0,0 +1,111 @@ +# Media Preview + +This section focuses on pre-call functionality, providing developers with the tools needed to prepare the media environment before joining the meeting. If you are using our UI Kits, this will be handled by `dyte-setup-screen` or could be built with `dyte-participant-tile`, `dyte-settings` components. + + +## Properties + +- `audioEnabled`: A boolean value indicating if the audio currently enabled. +- `videoEnabled`: A boolean value indicating if the video currently enabled. + +- `audioTrack`: The audio track for the local user. +- `videoTrack`: The video track for the local user. + +## Methods + +### Toggling Media + +The same methods used by post joining meeting are also used to control media-pre meeting. + +**1. Mute/Unmute microphone** + +```ts +// Mute Audio +await meeting.self.disableAudio(); + +// Unmute Audio +await meeting.self.enableAudio(); +``` + +```mermaid +flowchart LR + classDef basic fill:white; + + eam("enableAudio()") --> success("Emits audioUpdate event on self") + eam -. possibly .-> indirect("Update mediaPermissions.audio with mediaPermissionUpdate event") + + class eam basic; +``` + +
+ +Anytime there is an update in audio state you will get a `audioUpdate` event + +```ts + +meeting.self.on('audioUpdate', ({ audioEnabled, audioTrack })=> { + // if enabled show a visual(izer) preview of the audio to the user +}); + +``` + +**2. Enable/Disable camera** + +```ts +// Disable Video +await meeting.self.disableVideo(); + +// Enable Video +await meeting.self.enableVideo(); +``` + +```mermaid +flowchart LR + classDef basic fill:white; + + eam("enableVideo()") --> success("Emits videoUpdate event on self") + eam -. possibly .-> indirect("Update mediaPermissions.audio with mediaPermissionUpdate event") + + class eam basic; +``` +
+ +```ts +meeting.self.on('videoUpdate', ({ videoEnabled, videoTrack })=> { + // if videoEnabled play video here to a