@microsoft/omnichannel-chat-sdk 1.1.0 → 1.1.1-main.502460d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +517 -380
- package/package.json +1 -1
    
        package/README.md
    CHANGED
    
    | @@ -1,6 +1,7 @@ | |
| 1 1 | 
             
            # Omnichannel Chat SDK
         | 
| 2 2 |  | 
| 3 3 | 
             
            [](https://badge.fury.io/js/%40microsoft%2Fomnichannel-chat-sdk)
         | 
| 4 | 
            +
            [](https://packagephobia.com/result?p=@microsoft/omnichannel-chat-sdk)
         | 
| 4 5 | 
             
            
         | 
| 5 6 | 
             
            
         | 
| 6 7 |  | 
| @@ -12,12 +13,45 @@ Please make sure you have a chat widget configured before using this package or | |
| 12 13 | 
             
            - [Live Chat Widget vs. Chat SDK](#live-chat-widget-vs-chat-sdk)
         | 
| 13 14 | 
             
            - [Installation](#installation)
         | 
| 14 15 | 
             
            - [Installation on React Native](#installation-on-react-native)
         | 
| 15 | 
            -
            - [ | 
| 16 | 
            -
            - [ | 
| 17 | 
            -
            - [ | 
| 16 | 
            +
            - [SDK Methods](#sdk-methods)
         | 
| 17 | 
            +
                - [Initialization](#initialization)
         | 
| 18 | 
            +
                - [Start Chat](#start-chat)
         | 
| 19 | 
            +
                - [End Chat](#end-chat)
         | 
| 20 | 
            +
                - [Get Pre-Chat Survey](#get-pre-chat-survey)
         | 
| 21 | 
            +
                - [Get Live Chat Config](#get-live-chat-config)
         | 
| 22 | 
            +
                - [Get Current Live Chat Context](#get-current-live-chat-context)
         | 
| 23 | 
            +
                - [Get Data Masking Rules](#get-data-masking-rules)
         | 
| 24 | 
            +
                - [Get Chat Reconnect Context](#get-chat-reconnect-context)
         | 
| 25 | 
            +
                - [Get Conversation Details](#get-conversation-details)
         | 
| 26 | 
            +
                - [Get Chat Token](#get-chat-token)
         | 
| 27 | 
            +
                - [Get Calling Token](#get-calling-token)
         | 
| 28 | 
            +
                - [Get Messages](#get-messages)
         | 
| 29 | 
            +
                - [Send Messages](#send-messages)
         | 
| 30 | 
            +
                - [On New Message](#on-new-message)
         | 
| 31 | 
            +
                - [On Typing Event](#on-typing-event)
         | 
| 32 | 
            +
                - [On Agent End Session](#on-agent-end-session)
         | 
| 33 | 
            +
                - [Send Typing Event](#send-typing-event)
         | 
| 34 | 
            +
                - [Email Live Chat Transcript](#email-live-chat-transcript)
         | 
| 35 | 
            +
                - [Get Live Chat Transcript](#get-live-chat-transcript)
         | 
| 36 | 
            +
                - [Upload File Attachment](#upload-file-attachment)
         | 
| 37 | 
            +
                - [Download File Attachment](#download-file-attachment)
         | 
| 38 | 
            +
                - [Create Chat Adapter](#create-chat-adapter)
         | 
| 39 | 
            +
                - [Get Voice & Video Calling](#get-voice--video-calling)
         | 
| 40 | 
            +
                - [Get Post Chat Survey Context](#get-post-chat-survey-context)
         | 
| 18 41 | 
             
            - [Common Scenarios](#common-scenarios)
         | 
| 42 | 
            +
                - [Using BotFramework-WebChat](#using-botframework-webchat)
         | 
| 43 | 
            +
                - [Pre-Chat Survey](#pre-chat-survey)
         | 
| 44 | 
            +
                - [Post-Chat Survey](#post-chat-survey)
         | 
| 45 | 
            +
                - [Reconnect to existing Chat](#reconnect-to-existing-chat)
         | 
| 46 | 
            +
                - [Authenticated Chat](#authenticated-chat)
         | 
| 47 | 
            +
                - [Persistent Chat](#persistent-chat)
         | 
| 48 | 
            +
                - [Chat Reconnect with Authenticated User](#chat-reconnect-with-authenticated-user)
         | 
| 49 | 
            +
                - [Chat Reconnect with Unauthenticated User](#chat-reconnect-with-unauthenticated-user)
         | 
| 50 | 
            +
                - [Operating Hours](#operating-hours)
         | 
| 51 | 
            +
            - [Sample Apps](https://github.com/microsoft/omnichannel-chat-sdk-samples)
         | 
| 19 52 | 
             
            - [Feature Comparisons](#feature-comparisons)
         | 
| 20 53 | 
             
            - [Telemetry](#telemetry)
         | 
| 54 | 
            +
            - [Development Guide](docs/DEVELOPMENT_GUIDE.md)
         | 
| 21 55 | 
             
            - [Troubleshooting Guide](docs/TROUBLESHOOTING_GUIDE.md)
         | 
| 22 56 |  | 
| 23 57 | 
             
            ## Live Chat Widget vs. Chat SDK
         | 
| @@ -58,7 +92,7 @@ Omnichannel offers an live chat widget (LCW) by default. You can use the Chat SD | |
| 58 92 | 
             
            ## Installation
         | 
| 59 93 |  | 
| 60 94 | 
             
            ```
         | 
| 61 | 
            -
             | 
| 95 | 
            +
            npm install @microsoft/omnichannel-chat-sdk --save
         | 
| 62 96 | 
             
            ```
         | 
| 63 97 |  | 
| 64 98 | 
             
            ## Installation on React Native
         | 
| @@ -106,243 +140,301 @@ The following steps will be required to run Omnichannel Chat SDK on React Native | |
| 106 140 | 
             
                import 'react-native-url-polyfill';
         | 
| 107 141 | 
             
                ```
         | 
| 108 142 |  | 
| 109 | 
            -
            ##  | 
| 110 | 
            -
             | 
| 111 | 
            -
            | Method | Description | Notes |
         | 
| 112 | 
            -
            | ------ | ----------- | ----- |
         | 
| 113 | 
            -
            | OmnichannelChatSDK.initialize() | Initializes ChatSDK internal data | |
         | 
| 114 | 
            -
            | OmnichannelChatSDK.startChat() | Starts OC chat, handles prechat response | |
         | 
| 115 | 
            -
            | OmnichannelChatSDK.endChat() | Ends OC chat | |
         | 
| 116 | 
            -
            | OmnichannelChatSDK.getPreChatSurvey() | Adaptive card data of PreChat survey | |
         | 
| 117 | 
            -
            | OmnichannelChatSDK.getLiveChatConfig() | Get live chat config | |
         | 
| 118 | 
            -
            | OmnichannelChatSDK.getDataMaskingRules() | Get active data masking rules | |
         | 
| 119 | 
            -
            | OmnichannelChatSDK.getCurrentLiveChatContext() | Get current live chat context information to reconnect to the same chat | |
         | 
| 120 | 
            -
            | OmnichannelChatSDK.getChatReconnectContext() | Get current reconnectable chat context information to reconnect to a previous existing chat session | |
         | 
| 121 | 
            -
            | OmnichannelChatSDK.getConversationDetails() | Get details of the current conversation such as its state & when the agent joined the conversation | |
         | 
| 122 | 
            -
            | OmnichannelChatSDK.getChatToken() | Get chat token | |
         | 
| 123 | 
            -
            | OmnichannelChatSDK.getCallingToken() | Get calling token | |
         | 
| 124 | 
            -
            | OmnichannelChatSDK.getMessages() | Get all messages | |
         | 
| 125 | 
            -
            | OmnichannelChatSDK.sendMessage() | Send message | |
         | 
| 126 | 
            -
            | OmnichannelChatSDK.onNewMessage() | Handles system message, client/agent messages, adaptive cards, attachments to download | |
         | 
| 127 | 
            -
            | OmnichannelChatSDK.onTypingEvent() | Handles agent typing event | |
         | 
| 128 | 
            -
            | OmnichannelChatSDK.onAgentEndSession() | Handler when agent ends session | |
         | 
| 129 | 
            -
            | OmnichannelChatSDK.sendTypingEvent() | Sends customer typing event | |
         | 
| 130 | 
            -
            | OmnichannelChatSDK.emailLiveChatTranscript() | Email transcript | |
         | 
| 131 | 
            -
            | OmnichannelChatSDK.getLiveChatTranscript() | Get transcript data (JSON) | |
         | 
| 132 | 
            -
            | OmnichannelChatSDK.uploadFileAttachment() | Send file attachment | |
         | 
| 133 | 
            -
            | OmnichannelChatSDK.downloadFileAttachment() | Download file attachment | |
         | 
| 134 | 
            -
            | OmnichannelChatSDK.createChatAdapter() | Get Chat Adapter | **Web only** |
         | 
| 135 | 
            -
            | OmnichannelChatSDK.getVoiceVideoCalling() | Get VoiceVideoCall SDK for Escalation to Voice & Video | **Web only** |
         | 
| 136 | 
            -
            | OmnichannelChatSDK.getPostChatSurveyContext() | Get post chat survey link, survey locale, and whether an agent has joined the survey | |
         | 
| 137 | 
            -
             | 
| 138 | 
            -
            ## API examples
         | 
| 139 | 
            -
             | 
| 140 | 
            -
            ### Import
         | 
| 141 | 
            -
            ```ts
         | 
| 142 | 
            -
                import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
         | 
| 143 | 
            -
            ```
         | 
| 143 | 
            +
            ## SDK Methods
         | 
| 144 144 |  | 
| 145 145 | 
             
            ### Initialization
         | 
| 146 | 
            +
             | 
| 147 | 
            +
            It handles the initialization of ChatSDK internal data.
         | 
| 148 | 
            +
             | 
| 146 149 | 
             
            ```ts
         | 
| 147 | 
            -
             | 
| 148 | 
            -
                    orgUrl: "",
         | 
| 149 | 
            -
                    orgId: "",
         | 
| 150 | 
            -
                    widgetId: ""
         | 
| 151 | 
            -
                };
         | 
| 150 | 
            +
            import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
         | 
| 152 151 |  | 
| 153 | 
            -
             | 
| 154 | 
            -
             | 
| 155 | 
            -
             | 
| 156 | 
            -
             | 
| 157 | 
            -
             | 
| 158 | 
            -
                };
         | 
| 152 | 
            +
            const omnichannelConfig = {
         | 
| 153 | 
            +
                orgUrl: "",
         | 
| 154 | 
            +
                orgId: "",
         | 
| 155 | 
            +
                widgetId: ""
         | 
| 156 | 
            +
            };
         | 
| 159 157 |  | 
| 160 | 
            -
             | 
| 161 | 
            -
                 | 
| 162 | 
            -
             | 
| 158 | 
            +
            const chatSDKConfig = { // Optional
         | 
| 159 | 
            +
                dataMasking: {
         | 
| 160 | 
            +
                    disable: false,
         | 
| 161 | 
            +
                    maskingCharacter: '#'
         | 
| 162 | 
            +
                }
         | 
| 163 | 
            +
            };
         | 
| 163 164 |  | 
| 164 | 
            -
             | 
| 165 | 
            -
             | 
| 166 | 
            -
                const liveChatContext = await chatSDK.getCurrentLiveChatContext();
         | 
| 165 | 
            +
            const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
         | 
| 166 | 
            +
            await chatSDK.initialize();
         | 
| 167 167 | 
             
            ```
         | 
| 168 168 |  | 
| 169 | 
            -
            ###  | 
| 169 | 
            +
            ### Start Chat
         | 
| 170 | 
            +
             | 
| 171 | 
            +
            It starts an Omnichannel conversation.
         | 
| 172 | 
            +
             | 
| 170 173 | 
             
            ```ts
         | 
| 171 | 
            -
             | 
| 172 | 
            -
             | 
| 173 | 
            -
                } | 
| 174 | 
            +
            const customContext = {
         | 
| 175 | 
            +
                'contextKey1': {'value': 'contextValue1', 'isDisplayable': true},
         | 
| 176 | 
            +
                'contextKey2': {'value': 12.34, 'isDisplayable': false},
         | 
| 177 | 
            +
                'contextKey3': {'value': true}
         | 
| 178 | 
            +
            };
         | 
| 179 | 
            +
             | 
| 180 | 
            +
            const optionalParams = {
         | 
| 181 | 
            +
                preChatResponse: '', // PreChatSurvey response
         | 
| 182 | 
            +
                liveChatContext: {}, // EXISTING chat context data
         | 
| 183 | 
            +
                customContext // Custom Context
         | 
| 184 | 
            +
            };
         | 
| 174 185 |  | 
| 175 | 
            -
             | 
| 186 | 
            +
            await chatSDK.startChat(optionalParams);
         | 
| 176 187 | 
             
            ```
         | 
| 177 188 |  | 
| 178 | 
            -
            ###  | 
| 189 | 
            +
            ### End Chat
         | 
| 190 | 
            +
             | 
| 191 | 
            +
            It ends the current Omnichannel conversation.
         | 
| 192 | 
            +
             | 
| 179 193 | 
             
            ```ts
         | 
| 180 | 
            -
             | 
| 194 | 
            +
            await chatSDK.endChat();
         | 
| 181 195 | 
             
            ```
         | 
| 182 196 |  | 
| 183 | 
            -
            ### Get Chat  | 
| 197 | 
            +
            ### Get Pre-Chat Survey
         | 
| 198 | 
            +
             | 
| 199 | 
            +
            It gets the Pre-Chat Survey from Live Chat Config. Pre-Chat Survey is in Adaptive Card format.
         | 
| 200 | 
            +
             | 
| 201 | 
            +
            `Option 1`
         | 
| 184 202 | 
             
            ```ts
         | 
| 185 | 
            -
             | 
| 203 | 
            +
            const preChatSurvey = await getPreChatSurvey(); // Adaptive Cards JSON payload data
         | 
| 186 204 | 
             
            ```
         | 
| 187 | 
            -
             | 
| 188 | 
            -
            ### Get Calling Token
         | 
| 205 | 
            +
            `Option 2`
         | 
| 189 206 | 
             
            ```ts
         | 
| 190 | 
            -
             | 
| 207 | 
            +
            const parseToJSON = false;
         | 
| 208 | 
            +
            const preChatSurvey = await getPreChatSurvey(parseToJSON); // Adaptive Cards payload data as string
         | 
| 191 209 | 
             
            ```
         | 
| 192 210 |  | 
| 193 211 | 
             
            ### Get Live Chat Config
         | 
| 212 | 
            +
             | 
| 213 | 
            +
            It fetches the Live Chat Config.
         | 
| 214 | 
            +
             | 
| 194 215 | 
             
            ```ts
         | 
| 195 | 
            -
             | 
| 216 | 
            +
            const liveChatConfig = await chatSDK.getLiveChatConfig();
         | 
| 196 217 | 
             
            ```
         | 
| 197 218 |  | 
| 198 | 
            -
            ### Get  | 
| 219 | 
            +
            ### Get Current Live Chat Context
         | 
| 220 | 
            +
             | 
| 221 | 
            +
            It gets the current live chat context information to be used to reconnect to the same conversation.
         | 
| 222 | 
            +
             | 
| 199 223 | 
             
            ```ts
         | 
| 200 | 
            -
             | 
| 224 | 
            +
            const liveChatContext = await chatSDK.getCurrentLiveChatContext();
         | 
| 201 225 | 
             
            ```
         | 
| 202 226 |  | 
| 203 | 
            -
            ### Get  | 
| 204 | 
            -
             | 
| 227 | 
            +
            ### Get Data Masking Rules
         | 
| 228 | 
            +
             | 
| 229 | 
            +
            It gets the active data masking rules from Live Chat Config.
         | 
| 230 | 
            +
             | 
| 205 231 | 
             
            ```ts
         | 
| 206 | 
            -
             | 
| 232 | 
            +
            const dataMaskingRules = await chatSDK.getDataMaskingRules();
         | 
| 207 233 | 
             
            ```
         | 
| 208 | 
            -
             | 
| 234 | 
            +
             | 
| 235 | 
            +
            ### Get Chat Reconnect Context
         | 
| 236 | 
            +
             | 
| 237 | 
            +
            It gets the current reconnectable chat context information to connect to a previous existing chat session.
         | 
| 238 | 
            +
             | 
| 239 | 
            +
            `Reconnection options` is required. See [documentation](https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session)
         | 
| 240 | 
            +
             | 
| 209 241 | 
             
            ```ts
         | 
| 210 | 
            -
             | 
| 211 | 
            -
                 | 
| 242 | 
            +
            const optionalParams = {
         | 
| 243 | 
            +
                reconnectId: '', // reconnect Id
         | 
| 244 | 
            +
            };
         | 
| 245 | 
            +
             | 
| 246 | 
            +
            const chatReconnectContext = await chatSDK.getChatReconnectContext(optionalParams);
         | 
| 212 247 | 
             
            ```
         | 
| 213 248 |  | 
| 214 | 
            -
            ### Get  | 
| 249 | 
            +
            ### Get Conversation Details
         | 
| 250 | 
            +
             | 
| 251 | 
            +
            It gets the details of the current conversation such as its state & when the agent joined the conversation.
         | 
| 252 | 
            +
             | 
| 215 253 | 
             
            ```ts
         | 
| 216 | 
            -
             | 
| 217 | 
            -
                    const context = await chatSDK.getPostChatSurveyContext();
         | 
| 218 | 
            -
                    if (context.participantJoined) { // participantJoined will be true if an agent has joined the conversation, or a bot has joined the conversation and the bot survey flag has been turned on on the admin side.
         | 
| 219 | 
            -
                        // formsProLocale is the default language you have set on the CustomerVoice portal. You can override this url parameter with any locale that CustomerVoice supports.
         | 
| 220 | 
            -
                        // If "&lang=" is not set on the url, the locale will be English.
         | 
| 221 | 
            -
                        const linkToSend = context.surveyInviteLink + "&lang=" + context.formsProLocale;
         | 
| 222 | 
            -
                        // This link is accessible and will redirect to the survey page. Use it as you see fit.
         | 
| 223 | 
            -
                    }
         | 
| 224 | 
            -
                } catch (ex) {
         | 
| 225 | 
            -
                    // If the post chat should not be shown by any reason (e.g. post chat is not enabled), promise will be rejected.
         | 
| 226 | 
            -
                }
         | 
| 254 | 
            +
            const conversationDetails = await chatSDK.getConversationDetails();
         | 
| 227 255 | 
             
            ```
         | 
| 228 256 |  | 
| 229 | 
            -
            ###  | 
| 257 | 
            +
            ### Get chat Token
         | 
| 258 | 
            +
             | 
| 259 | 
            +
            It gets the chat token used to initiates a chat with Omnichannel messaging client.
         | 
| 260 | 
            +
             | 
| 230 261 | 
             
            ```ts
         | 
| 231 | 
            -
             | 
| 232 | 
            -
             | 
| 233 | 
            -
                    'contextKey2': {'value': 12.34, 'isDisplayable': false},
         | 
| 234 | 
            -
                    'contextKey3': {'value': true}
         | 
| 235 | 
            -
                };
         | 
| 262 | 
            +
            const chatToken = await chatSDK.getChatToken();
         | 
| 263 | 
            +
            ```
         | 
| 236 264 |  | 
| 237 | 
            -
             | 
| 238 | 
            -
             | 
| 239 | 
            -
             | 
| 240 | 
            -
             | 
| 241 | 
            -
             | 
| 242 | 
            -
             | 
| 265 | 
            +
            ### Get Calling Token
         | 
| 266 | 
            +
             | 
| 267 | 
            +
            It gets the calling token used to initiates a Voice & Video Call.
         | 
| 268 | 
            +
             | 
| 269 | 
            +
            ```ts
         | 
| 270 | 
            +
            const callingToken = await chatSDK.getCallingToken();
         | 
| 243 271 | 
             
            ```
         | 
| 244 272 |  | 
| 245 | 
            -
            ###  | 
| 273 | 
            +
            ### Get Messages
         | 
| 274 | 
            +
             | 
| 275 | 
            +
            It gets all the messages of the current conversation.
         | 
| 276 | 
            +
             | 
| 246 277 | 
             
            ```ts
         | 
| 247 | 
            -
             | 
| 278 | 
            +
            const messages = await chatSDK.getMessages();
         | 
| 248 279 | 
             
            ```
         | 
| 249 280 |  | 
| 250 | 
            -
            ###  | 
| 281 | 
            +
            ### Send Messages
         | 
| 282 | 
            +
             | 
| 283 | 
            +
            It sends a message to Omnichannel.
         | 
| 284 | 
            +
             | 
| 251 285 | 
             
            ```ts
         | 
| 252 | 
            -
             | 
| 253 | 
            -
                    rehydrate: true, // Rehydrate all previous messages of existing conversation (false by default)
         | 
| 254 | 
            -
                }
         | 
| 286 | 
            +
            import {DeliveryMode, MessageContentType, MessageType, PersonType} from '@microsoft/omnichannel-chat-sdk';
         | 
| 255 287 |  | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 258 | 
            -
             | 
| 259 | 
            -
             | 
| 288 | 
            +
            ...
         | 
| 289 | 
            +
             | 
| 290 | 
            +
            const displayName = "Contoso"
         | 
| 291 | 
            +
            const message = "Sample message from customer";
         | 
| 292 | 
            +
            const messageToSend = {
         | 
| 293 | 
            +
                content: message
         | 
| 294 | 
            +
            };
         | 
| 295 | 
            +
             | 
| 296 | 
            +
            await chatSDK.sendMessage(messageToSend);
         | 
| 260 297 | 
             
            ```
         | 
| 261 298 |  | 
| 262 | 
            -
            ### On  | 
| 299 | 
            +
            ### On New Message
         | 
| 300 | 
            +
             | 
| 301 | 
            +
            It subscribes to new incoming messages of the current conversation such as system messages, client messages, agent messages, adaptive cards and attachments.
         | 
| 302 | 
            +
             | 
| 263 303 | 
             
            ```ts
         | 
| 264 | 
            -
             | 
| 265 | 
            -
             | 
| 266 | 
            -
             | 
| 267 | 
            -
            ```
         | 
| 304 | 
            +
            const optionalParams = {
         | 
| 305 | 
            +
                rehydrate: true, // Rehydrate all previous messages of existing conversation (false by default)
         | 
| 306 | 
            +
            }
         | 
| 268 307 |  | 
| 308 | 
            +
            chatSDK.onNewMessage((message) => {
         | 
| 309 | 
            +
                console.log(`[NewMessage] ${message.content}`);
         | 
| 310 | 
            +
                console.log(message);
         | 
| 311 | 
            +
            }, optionalParams);
         | 
| 312 | 
            +
            ```
         | 
| 269 313 | 
             
            ### On Typing Event
         | 
| 314 | 
            +
             | 
| 315 | 
            +
            It subscribes to agent typing event.
         | 
| 316 | 
            +
             | 
| 270 317 | 
             
            ```ts
         | 
| 271 | 
            -
             | 
| 272 | 
            -
             | 
| 273 | 
            -
             | 
| 318 | 
            +
            chatSDK.onTypingEvent(() => {
         | 
| 319 | 
            +
                console.log("Agent is typing...");
         | 
| 320 | 
            +
            })
         | 
| 274 321 | 
             
            ```
         | 
| 275 322 |  | 
| 276 | 
            -
            ###  | 
| 323 | 
            +
            ### On Agent End Session
         | 
| 324 | 
            +
             | 
| 325 | 
            +
            It subscribes to agent ending the session of the conversation.
         | 
| 326 | 
            +
             | 
| 277 327 | 
             
            ```ts
         | 
| 278 | 
            -
             | 
| 328 | 
            +
            chatSDK.onAgentEndSession(() => {
         | 
| 329 | 
            +
                console.log("Session ended!");
         | 
| 330 | 
            +
            });
         | 
| 279 331 | 
             
            ```
         | 
| 280 332 |  | 
| 281 | 
            -
            ### Send  | 
| 333 | 
            +
            ### Send Typing Event
         | 
| 334 | 
            +
             | 
| 335 | 
            +
            It sends a customer typing event.
         | 
| 336 | 
            +
             | 
| 282 337 | 
             
            ```ts
         | 
| 283 | 
            -
             | 
| 338 | 
            +
            await chatSDK.sendTypingEvent();
         | 
| 339 | 
            +
            ```
         | 
| 284 340 |  | 
| 285 | 
            -
             | 
| 341 | 
            +
            ### Email Live Chat Transcript
         | 
| 286 342 |  | 
| 287 | 
            -
             | 
| 288 | 
            -
                const message = "Sample message from customer";
         | 
| 289 | 
            -
                const messageToSend = {
         | 
| 290 | 
            -
                  content: message
         | 
| 291 | 
            -
                };
         | 
| 343 | 
            +
            It sends an email of the live chat transcript.
         | 
| 292 344 |  | 
| 293 | 
            -
             | 
| 345 | 
            +
            ```ts
         | 
| 346 | 
            +
            const body = {
         | 
| 347 | 
            +
                emailAddress: 'contoso@microsoft.com',
         | 
| 348 | 
            +
                attachmentMessage: 'Attachment Message'
         | 
| 349 | 
            +
            };
         | 
| 350 | 
            +
            await chatSDK.emailLiveChatTranscript(body);
         | 
| 294 351 | 
             
            ```
         | 
| 295 352 |  | 
| 296 | 
            -
            ###  | 
| 353 | 
            +
            ### Get Live Chat Transcript
         | 
| 354 | 
            +
             | 
| 355 | 
            +
            It fetches the current conversation transcript data in JSON.
         | 
| 356 | 
            +
             | 
| 297 357 | 
             
            ```ts
         | 
| 298 | 
            -
             | 
| 358 | 
            +
            await chatSDK.getLiveChatTranscript();
         | 
| 299 359 | 
             
            ```
         | 
| 300 360 |  | 
| 301 | 
            -
            ### Upload Attachment
         | 
| 361 | 
            +
            ### Upload File Attachment
         | 
| 362 | 
            +
             | 
| 363 | 
            +
            It sends a file attachment to the current conversation.
         | 
| 364 | 
            +
             | 
| 302 365 | 
             
            ```ts
         | 
| 303 | 
            -
             | 
| 304 | 
            -
             | 
| 305 | 
            -
             | 
| 306 | 
            -
             | 
| 307 | 
            -
             | 
| 308 | 
            -
             | 
| 309 | 
            -
             | 
| 366 | 
            +
            const fileInfo = {
         | 
| 367 | 
            +
                name: '',
         | 
| 368 | 
            +
                type: '',
         | 
| 369 | 
            +
                size: '',
         | 
| 370 | 
            +
                data: ''
         | 
| 371 | 
            +
            };
         | 
| 372 | 
            +
            await chatSDK.uploadFileAttachment(fileInfo);
         | 
| 310 373 | 
             
            ```
         | 
| 311 374 |  | 
| 312 | 
            -
            ### Download Attachment
         | 
| 375 | 
            +
            ### Download File Attachment
         | 
| 376 | 
            +
             | 
| 377 | 
            +
            It downloads the file attachment of the incoming message as a Blob response.
         | 
| 378 | 
            +
             | 
| 313 379 | 
             
            ```ts
         | 
| 314 | 
            -
             | 
| 380 | 
            +
            const blobResponse = await chatsdk.downloadFileAttachment(message.fileMetadata);
         | 
| 315 381 |  | 
| 316 | 
            -
             | 
| 382 | 
            +
            ...
         | 
| 317 383 |  | 
| 318 | 
            -
             | 
| 319 | 
            -
             | 
| 320 | 
            -
             | 
| 321 | 
            -
             | 
| 322 | 
            -
             | 
| 323 | 
            -
             | 
| 324 | 
            -
             | 
| 384 | 
            +
            // React Native implementation
         | 
| 385 | 
            +
            const fileReaderInstance = new FileReader();
         | 
| 386 | 
            +
            fileReaderInstance.readAsDataURL(blobResponse);
         | 
| 387 | 
            +
            fileReaderInstance.onload = () => {
         | 
| 388 | 
            +
                const base64data = fileReaderInstance.result;
         | 
| 389 | 
            +
                return <Image source={{uri: base64data}}/>
         | 
| 390 | 
            +
            }
         | 
| 325 391 | 
             
            ```
         | 
| 326 392 |  | 
| 327 | 
            -
            ###  | 
| 393 | 
            +
            ### Create Chat Adapter
         | 
| 394 | 
            +
             | 
| 395 | 
            +
            > :warning: Currently supported on web only
         | 
| 396 | 
            +
             | 
| 397 | 
            +
            It creates a chat adapter to use with [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat).
         | 
| 328 398 |  | 
| 329 399 | 
             
            ```ts
         | 
| 330 | 
            -
             | 
| 400 | 
            +
            const chatAdapter = await chatSDK.createChatAdapter();
         | 
| 331 401 | 
             
            ```
         | 
| 332 402 |  | 
| 333 | 
            -
            ###  | 
| 403 | 
            +
            ### Get Voice & Video Calling
         | 
| 404 | 
            +
             | 
| 405 | 
            +
            > :warning: Currently supported on web only
         | 
| 406 | 
            +
             | 
| 407 | 
            +
            It fetches the SDK for Escalation to Voice & Video.
         | 
| 334 408 |  | 
| 335 409 | 
             
            ```ts
         | 
| 336 | 
            -
             | 
| 337 | 
            -
             | 
| 338 | 
            -
             | 
| 339 | 
            -
             | 
| 340 | 
            -
                 | 
| 410 | 
            +
            try {
         | 
| 411 | 
            +
                const VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
         | 
| 412 | 
            +
                console.log("VoiceVideoCalling loaded");
         | 
| 413 | 
            +
            } catch (e) {
         | 
| 414 | 
            +
                console.log(`Failed to load VoiceVideoCalling: ${e}`);
         | 
| 415 | 
            +
             | 
| 416 | 
            +
                if (e.message === 'UnsupportedPlatform') {
         | 
| 417 | 
            +
                    // Voice Video Calling feature is not supported on this platform
         | 
| 418 | 
            +
                }
         | 
| 419 | 
            +
             | 
| 420 | 
            +
                if (e.message === 'FeatureDisabled') {
         | 
| 421 | 
            +
                    // Voice Video Calling feature is disabled on admin side
         | 
| 422 | 
            +
                }
         | 
| 423 | 
            +
            }
         | 
| 424 | 
            +
            ```
         | 
| 425 | 
            +
            ### Get Post Chat Survey Context
         | 
| 426 | 
            +
             | 
| 427 | 
            +
            It gets post chat survey link, survey locale, and whether an agent has joined the survey.
         | 
| 428 | 
            +
             | 
| 429 | 
            +
            ```ts
         | 
| 430 | 
            +
            const context = await chatSDK.getPostChatSurveyContext();
         | 
| 341 431 | 
             
            ```
         | 
| 342 432 |  | 
| 343 433 | 
             
            ## Common Scenarios
         | 
| 344 434 |  | 
| 345 | 
            -
            ###  | 
| 435 | 
            +
            ### Pre-Chat Survey
         | 
| 436 | 
            +
             | 
| 437 | 
            +
            > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-pre-chat-survey?tabs=customerserviceadmincenter on how to set up pre-conversation surveys
         | 
| 346 438 |  | 
| 347 439 | 
             
            ```ts
         | 
| 348 440 | 
             
                import * as AdaptiveCards, { Action } from "adaptivecards";
         | 
| @@ -375,314 +467,359 @@ The following steps will be required to run Omnichannel Chat SDK on React Native | |
| 375 467 |  | 
| 376 468 | 
             
            ```
         | 
| 377 469 |  | 
| 470 | 
            +
            ### Post-Chat Survey
         | 
| 471 | 
            +
             | 
| 472 | 
            +
            > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-post-conversation-survey?tabs=customerserviceadmincenter on how to set up post-conversation surveys
         | 
| 473 | 
            +
             | 
| 474 | 
            +
            > ❗ `chatSDK.getPostChatSurveyContext()` needs to be called before `chatSDK.endChat()` is called
         | 
| 475 | 
            +
             | 
| 476 | 
            +
            ```ts
         | 
| 477 | 
            +
            // 1. Start chat
         | 
| 478 | 
            +
            await chatSDK.startChat();
         | 
| 479 | 
            +
             | 
| 480 | 
            +
            // 2. Save post chat survey context before ending chat
         | 
| 481 | 
            +
            try {
         | 
| 482 | 
            +
                const context = await chatSDK.getPostChatSurveyContext();
         | 
| 483 | 
            +
                if (context.participantJoined) { // participantJoined will be true if an agent has joined the conversation, or a bot has joined the conversation and the bot survey flag has been turned on on the admin side.
         | 
| 484 | 
            +
                    // formsProLocale is the default language you have set on the CustomerVoice portal. You can override this url parameter with any locale that CustomerVoice supports.
         | 
| 485 | 
            +
                    // If "&lang=" is not set on the url, the locale will be English.
         | 
| 486 | 
            +
                    const linkToSend = context.surveyInviteLink + "&lang=" + context.formsProLocale;
         | 
| 487 | 
            +
                    // This link is accessible and will redirect to the survey page. Use it as you see fit.
         | 
| 488 | 
            +
                }
         | 
| 489 | 
            +
            } catch (ex) {
         | 
| 490 | 
            +
                // If the post chat should not be shown by any reason (e.g. post chat is not enabled), promise will be rejected.
         | 
| 491 | 
            +
            }
         | 
| 492 | 
            +
             | 
| 493 | 
            +
            // 3. End chat
         | 
| 494 | 
            +
            await chatSDK.endChat();
         | 
| 495 | 
            +
             | 
| 496 | 
            +
            // 4. Display Post Chat
         | 
| 497 | 
            +
            ```
         | 
| 498 | 
            +
             | 
| 378 499 | 
             
            ### Reconnect to existing Chat
         | 
| 379 500 |  | 
| 380 501 | 
             
            ```ts
         | 
| 381 | 
            -
             | 
| 502 | 
            +
            await chatSDK.startChat(); // Starts NEW chat
         | 
| 382 503 |  | 
| 383 | 
            -
             | 
| 504 | 
            +
            const liveChatContext = await chatSDK.getCurrentLiveChatContext(); // Gets chat context
         | 
| 384 505 |  | 
| 385 | 
            -
             | 
| 506 | 
            +
            cache.saveChatContext(liveChatContext); // Custom logic to save chat context to cache
         | 
| 386 507 |  | 
| 387 | 
            -
             | 
| 508 | 
            +
            ...
         | 
| 388 509 |  | 
| 389 | 
            -
             | 
| 510 | 
            +
            // Page/component reloads, ALL previous states are GONE
         | 
| 390 511 |  | 
| 391 | 
            -
             | 
| 512 | 
            +
            ...
         | 
| 392 513 |  | 
| 393 | 
            -
             | 
| 514 | 
            +
            const liveChatContext = cache.loadChatContext() // Custom logic to load chat context from cache
         | 
| 394 515 |  | 
| 395 | 
            -
             | 
| 396 | 
            -
             | 
| 516 | 
            +
            const optionalParams = {};
         | 
| 517 | 
            +
            optionalParams.liveChatContext = liveChatContext;
         | 
| 397 518 |  | 
| 398 | 
            -
             | 
| 519 | 
            +
            await chatSDK.startChat(optionalParams); // Reconnects to EXISTING chat
         | 
| 399 520 |  | 
| 400 | 
            -
             | 
| 521 | 
            +
            ...
         | 
| 401 522 |  | 
| 402 | 
            -
             | 
| 403 | 
            -
             | 
| 523 | 
            +
            const messages = await chatSDK.getMessages(); // Gets all messages from EXISTING chat
         | 
| 524 | 
            +
            messages.reverse().forEach((message: any) => renderMessage(message)); // Logic to render all messages to UI
         | 
| 404 525 | 
             
            ```
         | 
| 405 526 |  | 
| 406 527 | 
             
            ### Authenticated Chat
         | 
| 407 528 |  | 
| 408 | 
            -
             | 
| 409 | 
            -
                // add if using against an authenticated chat endpoint
         | 
| 410 | 
            -
                // see https://docs.microsoft.com/en-us/dynamics365/omnichannel/administrator/create-chat-auth-settings on how to set up an authenticated chat widget
         | 
| 529 | 
            +
            > See https://docs.microsoft.com/en-us/dynamics365/customer-service/create-chat-auth-settings?tabs=customerserviceadmincenter#create-a-chat-authentication-setting-record on how to set up an authenticated chat
         | 
| 411 530 |  | 
| 412 | 
            -
             | 
| 413 | 
            -
             | 
| 414 | 
            -
             | 
| 415 | 
            -
             | 
| 416 | 
            -
             | 
| 417 | 
            -
                         | 
| 418 | 
            -
             | 
| 419 | 
            -
             | 
| 420 | 
            -
                         | 
| 531 | 
            +
            ```ts
         | 
| 532 | 
            +
            const chatSDKConfig = {
         | 
| 533 | 
            +
                getAuthToken: async () => {
         | 
| 534 | 
            +
                    const response = await fetch("http://contosohelp.com/token");
         | 
| 535 | 
            +
                    if (response.ok) {
         | 
| 536 | 
            +
                        return await response.text();
         | 
| 537 | 
            +
                    }
         | 
| 538 | 
            +
                    else {
         | 
| 539 | 
            +
                        return null
         | 
| 421 540 | 
             
                    }
         | 
| 422 541 | 
             
                }
         | 
| 542 | 
            +
            }
         | 
| 423 543 |  | 
| 424 | 
            -
             | 
| 425 | 
            -
             | 
| 544 | 
            +
            const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
         | 
| 545 | 
            +
            await chatSDK.initialize();
         | 
| 426 546 |  | 
| 427 | 
            -
             | 
| 547 | 
            +
            // from this point, this acts like a regular chat widget
         | 
| 428 548 | 
             
            ```
         | 
| 429 549 |  | 
| 430 550 | 
             
            ### Persistent Chat
         | 
| 431 551 |  | 
| 552 | 
            +
            > See https://docs.microsoft.com/en-us/dynamics365/customer-service/persistent-chat on how to set up persistent chat
         | 
| 553 | 
            +
             | 
| 432 554 | 
             
            ```ts
         | 
| 433 | 
            -
             | 
| 434 | 
            -
             | 
| 435 | 
            -
             | 
| 436 | 
            -
             | 
| 437 | 
            -
             | 
| 438 | 
            -
             | 
| 439 | 
            -
             | 
| 440 | 
            -
             | 
| 441 | 
            -
             | 
| 442 | 
            -
             | 
| 443 | 
            -
             | 
| 444 | 
            -
             | 
| 445 | 
            -
                        }
         | 
| 555 | 
            +
            const chatSDKConfig = {
         | 
| 556 | 
            +
                persistentChat: {
         | 
| 557 | 
            +
                    disable: false,
         | 
| 558 | 
            +
                    tokenUpdateTime: 21600000
         | 
| 559 | 
            +
                },
         | 
| 560 | 
            +
                getAuthToken: async () => {
         | 
| 561 | 
            +
                    const response = await fetch("http://contosohelp.com/token");
         | 
| 562 | 
            +
                    if (response.ok) {
         | 
| 563 | 
            +
                        return await response.text();
         | 
| 564 | 
            +
                    }
         | 
| 565 | 
            +
                    else {
         | 
| 566 | 
            +
                        return null
         | 
| 446 567 | 
             
                    }
         | 
| 447 568 | 
             
                }
         | 
| 569 | 
            +
            }
         | 
| 448 570 |  | 
| 449 | 
            -
             | 
| 450 | 
            -
             | 
| 571 | 
            +
            const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
         | 
| 572 | 
            +
            await chatSDK.initialize();
         | 
| 451 573 |  | 
| 452 | 
            -
             | 
| 574 | 
            +
            // from this point, this acts like a persistent chat
         | 
| 453 575 | 
             
            ```
         | 
| 454 576 | 
             
            ### Chat Reconnect with Authenticated User
         | 
| 455 577 |  | 
| 578 | 
            +
            > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session on how to set up chat reconnect
         | 
| 579 | 
            +
             | 
| 456 580 | 
             
            ```ts
         | 
| 457 | 
            -
             | 
| 458 | 
            -
             | 
| 459 | 
            -
             | 
| 460 | 
            -
             | 
| 461 | 
            -
             | 
| 462 | 
            -
             | 
| 463 | 
            -
             | 
| 464 | 
            -
             | 
| 465 | 
            -
             | 
| 466 | 
            -
             | 
| 467 | 
            -
             | 
| 468 | 
            -
                        }
         | 
| 581 | 
            +
            const chatSDKConfig = {
         | 
| 582 | 
            +
                chatReconnect: {
         | 
| 583 | 
            +
                    disable: false,
         | 
| 584 | 
            +
                },
         | 
| 585 | 
            +
                getAuthToken: async () => {
         | 
| 586 | 
            +
                    const response = await fetch("http://contosohelp.com/token");
         | 
| 587 | 
            +
                    if (response.ok) {
         | 
| 588 | 
            +
                        return await response.text();
         | 
| 589 | 
            +
                    }
         | 
| 590 | 
            +
                    else {
         | 
| 591 | 
            +
                        return null
         | 
| 469 592 | 
             
                    }
         | 
| 470 593 | 
             
                }
         | 
| 594 | 
            +
            }
         | 
| 471 595 |  | 
| 472 | 
            -
             | 
| 473 | 
            -
             | 
| 596 | 
            +
            const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
         | 
| 597 | 
            +
            await chatSDK.initialize();
         | 
| 474 598 |  | 
| 475 | 
            -
             | 
| 599 | 
            +
            ...
         | 
| 476 600 |  | 
| 477 | 
            -
             | 
| 601 | 
            +
            const chatReconnectContext = await chatSDK.getChatReconnectContext();
         | 
| 478 602 |  | 
| 479 | 
            -
             | 
| 480 | 
            -
             | 
| 481 | 
            -
             | 
| 603 | 
            +
            if (chatReconnectContext.reconnectId) {
         | 
| 604 | 
            +
                // Add UX with options to reconnect to previous existing chat or start new chat
         | 
| 605 | 
            +
            }
         | 
| 482 606 |  | 
| 483 | 
            -
             | 
| 484 | 
            -
             | 
| 485 | 
            -
             | 
| 486 | 
            -
             | 
| 607 | 
            +
            // Reconnect chat option
         | 
| 608 | 
            +
            const optionalParams = {};
         | 
| 609 | 
            +
            optionalParams.reconnectId = chatReconnectContext.reconnectId;
         | 
| 610 | 
            +
            chatSDK.startChat(optionalParams);
         | 
| 487 611 |  | 
| 488 | 
            -
             | 
| 489 | 
            -
             | 
| 612 | 
            +
            // Start new chat option
         | 
| 613 | 
            +
            chatSDK.startChat();
         | 
| 490 614 | 
             
            ```
         | 
| 491 615 |  | 
| 492 616 | 
             
            ### Chat Reconnect with Unauthenticated User
         | 
| 493 617 |  | 
| 618 | 
            +
            > See https://docs.microsoft.com/en-us/dynamics365/customer-service/configure-reconnect-chat?tabs=customerserviceadmincenter#enable-reconnection-to-a-previous-chat-session on how to set up chat reconnect
         | 
| 619 | 
            +
             | 
| 494 620 | 
             
            ```ts
         | 
| 495 | 
            -
             | 
| 496 | 
            -
             | 
| 497 | 
            -
             | 
| 498 | 
            -
             | 
| 499 | 
            -
             | 
| 621 | 
            +
            const chatSDKConfig = {
         | 
| 622 | 
            +
                chatReconnect: {
         | 
| 623 | 
            +
                    disable: false,
         | 
| 624 | 
            +
                },
         | 
| 625 | 
            +
            }
         | 
| 500 626 |  | 
| 501 | 
            -
             | 
| 502 | 
            -
             | 
| 627 | 
            +
            const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
         | 
| 628 | 
            +
            await chatSDK.initialize();
         | 
| 503 629 |  | 
| 504 | 
            -
             | 
| 630 | 
            +
            ....
         | 
| 505 631 |  | 
| 506 | 
            -
             | 
| 632 | 
            +
            const optionalParams: any = {};
         | 
| 507 633 |  | 
| 508 | 
            -
             | 
| 509 | 
            -
             | 
| 510 | 
            -
             | 
| 634 | 
            +
            // Retrieve reconnect id from the URL
         | 
| 635 | 
            +
            const urlParams = new URLSearchParams(window.location.search);
         | 
| 636 | 
            +
            const reconnectId = urlParams.get('oc.reconnectid');
         | 
| 511 637 |  | 
| 512 | 
            -
             | 
| 513 | 
            -
             | 
| 514 | 
            -
             | 
| 638 | 
            +
            const params = {
         | 
| 639 | 
            +
                reconnectId
         | 
| 640 | 
            +
            };
         | 
| 515 641 |  | 
| 516 | 
            -
             | 
| 517 | 
            -
             | 
| 642 | 
            +
            // Validate reconnect id
         | 
| 643 | 
            +
            const chatReconnectContext = await chatSDK.getChatReconnectContext(params);
         | 
| 518 644 |  | 
| 519 | 
            -
             | 
| 520 | 
            -
             | 
| 521 | 
            -
             | 
| 522 | 
            -
             | 
| 645 | 
            +
            // If the reconnect id is invalid or expired, redirect URL if there is any URL set in the configuration
         | 
| 646 | 
            +
            if (chatReconnectContext.redirectURL) {
         | 
| 647 | 
            +
                window.location.replace(chatReconnectContext.redirectURL);
         | 
| 648 | 
            +
            }
         | 
| 523 649 |  | 
| 524 | 
            -
             | 
| 525 | 
            -
             | 
| 526 | 
            -
             | 
| 527 | 
            -
             | 
| 528 | 
            -
             | 
| 529 | 
            -
             | 
| 530 | 
            -
             | 
| 531 | 
            -
             | 
| 650 | 
            +
            // Valid reconnect id, reconnect to previous chat
         | 
| 651 | 
            +
            if (chatReconnectContext.reconnectId) {
         | 
| 652 | 
            +
                await chatSDK.startChat({
         | 
| 653 | 
            +
                    reconnectId: chatReconnectContext.reconnectId
         | 
| 654 | 
            +
                });
         | 
| 655 | 
            +
            } else {  // Reconnect id from URL is not valid, start new chat session
         | 
| 656 | 
            +
                await chatSDK.startChat();
         | 
| 657 | 
            +
            }
         | 
| 532 658 | 
             
            ```
         | 
| 533 659 |  | 
| 534 660 | 
             
            ### Operating Hours
         | 
| 535 661 |  | 
| 662 | 
            +
            > See https://docs.microsoft.com/en-us/dynamics365/customer-service/create-operating-hours?tabs=customerserviceadmincenter on how to set up operating hours
         | 
| 663 | 
            +
             | 
| 536 664 | 
             
            ```ts
         | 
| 537 | 
            -
             | 
| 538 | 
            -
             | 
| 539 | 
            -
             | 
| 665 | 
            +
            const chatConfig = await chatSDK.getLiveChatConfig();
         | 
| 666 | 
            +
            const {LiveWSAndLiveChatEngJoin: liveWSAndLiveChatEngJoin} = liveChatConfig;
         | 
| 667 | 
            +
            const {OutOfOperatingHours: outOfOperatingHours} = liveWSAndLiveChatEngJoin;
         | 
| 540 668 |  | 
| 541 | 
            -
             | 
| 542 | 
            -
             | 
| 543 | 
            -
             | 
| 544 | 
            -
             | 
| 545 | 
            -
             | 
| 546 | 
            -
             | 
| 669 | 
            +
            if (outOfOperatingHours === "True") {
         | 
| 670 | 
            +
                // Handles UX on Out of Operating Hours
         | 
| 671 | 
            +
            } else {
         | 
| 672 | 
            +
                await chatSDK.startChat();
         | 
| 673 | 
            +
                // Renders Custom Chat Widget
         | 
| 674 | 
            +
            }
         | 
| 547 675 | 
             
            ```
         | 
| 548 676 |  | 
| 549 | 
            -
            ###  | 
| 677 | 
            +
            ### Using [BotFramework-WebChat](https://github.com/microsoft/BotFramework-WebChat)
         | 
| 678 | 
            +
            > :warning: Currently supported on web only
         | 
| 550 679 |  | 
| 551 | 
            -
             | 
| 552 | 
            -
             | 
| 553 | 
            -
             | 
| 554 | 
            -
             | 
| 555 | 
            -
             | 
| 556 | 
            -
                 | 
| 680 | 
            +
            Minimum Requirement Checklist
         | 
| 681 | 
            +
            1. [ ] Initialize ChatSDK
         | 
| 682 | 
            +
            1. [ ] Start new conversation
         | 
| 683 | 
            +
            1. [ ] Create Chat Adapter
         | 
| 684 | 
            +
            1. [ ] Create WebChat store with default middlewares
         | 
| 685 | 
            +
                1. [ ] Send Default Channel Message Tags using Store Middleware (See [here](/docs//DEVELOPMENT_GUIDE.md#send-default-channel-message-tags-using-store-middleware)) ❗ Required
         | 
| 686 | 
            +
            1. [ ] Render WebChat
         | 
| 557 687 |  | 
| 558 | 
            -
             | 
| 559 | 
            -
             | 
| 688 | 
            +
            ```ts
         | 
| 689 | 
            +
            import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
         | 
| 690 | 
            +
            import ReactWebChat, {createStore} from 'botframework-webchat';
         | 
| 560 691 |  | 
| 561 | 
            -
             | 
| 562 | 
            -
             | 
| 563 | 
            -
             | 
| 692 | 
            +
            // 1. ChatSDK Initialization
         | 
| 693 | 
            +
            const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig);
         | 
| 694 | 
            +
            await chatSDK.initialize();
         | 
| 564 695 |  | 
| 565 | 
            -
             | 
| 566 | 
            -
             | 
| 696 | 
            +
            // 2. Start new conversation
         | 
| 697 | 
            +
            await chatSDK.startChat();
         | 
| 567 698 |  | 
| 568 | 
            -
             | 
| 569 | 
            -
             | 
| 570 | 
            -
                  console.log(`[NewMessage] ${message.content}`); // IC3 protocol message data
         | 
| 571 | 
            -
                  console.log(message);
         | 
| 572 | 
            -
                });
         | 
| 699 | 
            +
            // 3. Create chat adapter
         | 
| 700 | 
            +
            const chatAdapter = await chatSDK.createChatAdapter();
         | 
| 573 701 |  | 
| 574 | 
            -
             | 
| 702 | 
            +
            // 4. Create WebChat store with middlewares
         | 
| 703 | 
            +
            const store = createStore(
         | 
| 704 | 
            +
                {}, // initial state
         | 
| 705 | 
            +
                sendDefaultMessagingTagsMiddleware // ❗ Required
         | 
| 706 | 
            +
            );
         | 
| 575 707 |  | 
| 576 | 
            -
             | 
| 577 | 
            -
             | 
| 578 | 
            -
             | 
| 579 | 
            -
             | 
| 580 | 
            -
                 | 
| 708 | 
            +
            // 5. Render WebChat
         | 
| 709 | 
            +
            <ReactWebChat
         | 
| 710 | 
            +
                store={store}
         | 
| 711 | 
            +
                userID="teamsvisitor"
         | 
| 712 | 
            +
                directLine={chatAdapter}
         | 
| 713 | 
            +
                sendTypingIndicator={true}
         | 
| 714 | 
            +
            />
         | 
| 581 715 | 
             
            ```
         | 
| 582 716 |  | 
| 583 717 | 
             
            ### Escalation to Voice & Video
         | 
| 584 | 
            -
             | 
| 718 | 
            +
            > :warning: Currently supported on web only
         | 
| 719 | 
            +
             | 
| 720 | 
            +
            > See https://docs.microsoft.com/en-us/dynamics365/customer-service/call-options-visual-engagement on how to set up calling options
         | 
| 721 | 
            +
             | 
| 585 722 | 
             
            ```ts
         | 
| 586 | 
            -
             | 
| 723 | 
            +
            import OmnichannelChatSDK from '@microsoft/omnichannel-chat-sdk';
         | 
| 587 724 |  | 
| 588 | 
            -
             | 
| 725 | 
            +
            ...
         | 
| 589 726 |  | 
| 590 | 
            -
             | 
| 591 | 
            -
             | 
| 727 | 
            +
            const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
         | 
| 728 | 
            +
            await chatSDK.initialize();
         | 
| 592 729 |  | 
| 593 | 
            -
             | 
| 594 | 
            -
             | 
| 595 | 
            -
             | 
| 596 | 
            -
             | 
| 597 | 
            -
             | 
| 598 | 
            -
             | 
| 730 | 
            +
            let VoiceVideoCallingSDK;
         | 
| 731 | 
            +
            try {
         | 
| 732 | 
            +
                VoiceVideoCallingSDK = await chatSDK.getVoiceVideoCalling();
         | 
| 733 | 
            +
                console.log("VoiceVideoCalling loaded");
         | 
| 734 | 
            +
            } catch (e) {
         | 
| 735 | 
            +
                console.log(`Failed to load VoiceVideoCalling: ${e}`);
         | 
| 599 736 |  | 
| 600 | 
            -
             | 
| 601 | 
            -
             | 
| 602 | 
            -
             | 
| 737 | 
            +
                if (e.message === 'UnsupportedPlatform') {
         | 
| 738 | 
            +
                    // Voice Video Calling feature is not supported on this platform
         | 
| 739 | 
            +
                }
         | 
| 603 740 |  | 
| 604 | 
            -
             | 
| 605 | 
            -
             | 
| 606 | 
            -
                    }
         | 
| 741 | 
            +
                if (e.message === 'FeatureDisabled') {
         | 
| 742 | 
            +
                    // Voice Video Calling feature is disabled on admin side
         | 
| 607 743 | 
             
                }
         | 
| 744 | 
            +
            }
         | 
| 608 745 |  | 
| 609 | 
            -
             | 
| 746 | 
            +
            await chatSDK.startChat();
         | 
| 610 747 |  | 
| 611 | 
            -
             | 
| 612 | 
            -
             | 
| 613 | 
            -
                // Initialize only if VoiceVideoCallingSDK is defined
         | 
| 614 | 
            -
                if (VoiceVideoCallingSDK) {
         | 
| 615 | 
            -
                    try {
         | 
| 616 | 
            -
                        await VoiceVideoCallingSDK.initialize({
         | 
| 617 | 
            -
                            chatToken,
         | 
| 618 | 
            -
                            selfVideoHTMLElementId: 'selfVideo', // HTML element id where video stream of the agent will be rendered
         | 
| 619 | 
            -
                            remoteVideoHTMLElementId: 'remoteVideo', // HTML element id where video stream of the customer will be rendered
         | 
| 620 | 
            -
                            OCClient: chatSDK.OCClient
         | 
| 621 | 
            -
                        });
         | 
| 622 | 
            -
                    } catch (e) {
         | 
| 623 | 
            -
                        console.error("Failed to initialize VoiceVideoCalling!");
         | 
| 624 | 
            -
                    }
         | 
| 748 | 
            +
            const chatToken: any = await chatSDK.getChatToken();
         | 
| 625 749 |  | 
| 626 | 
            -
             | 
| 627 | 
            -
             | 
| 628 | 
            -
             | 
| 750 | 
            +
            // Initialize only if VoiceVideoCallingSDK is defined
         | 
| 751 | 
            +
            if (VoiceVideoCallingSDK) {
         | 
| 752 | 
            +
                try {
         | 
| 753 | 
            +
                    await VoiceVideoCallingSDK.initialize({
         | 
| 754 | 
            +
                        chatToken,
         | 
| 755 | 
            +
                        selfVideoHTMLElementId: 'selfVideo', // HTML element id where video stream of the agent will be rendered
         | 
| 756 | 
            +
                        remoteVideoHTMLElementId: 'remoteVideo', // HTML element id where video stream of the customer will be rendered
         | 
| 757 | 
            +
                        OCClient: chatSDK.OCClient
         | 
| 629 758 | 
             
                    });
         | 
| 759 | 
            +
                } catch (e) {
         | 
| 760 | 
            +
                    console.error("Failed to initialize VoiceVideoCalling!");
         | 
| 761 | 
            +
                }
         | 
| 630 762 |  | 
| 631 | 
            -
             | 
| 632 | 
            -
             | 
| 633 | 
            -
             | 
| 634 | 
            -
             | 
| 763 | 
            +
                // Triggered when there's an incoming call
         | 
| 764 | 
            +
                VoiceVideoCallingSDK.onCallAdded(() => {
         | 
| 765 | 
            +
                    ...
         | 
| 766 | 
            +
                });
         | 
| 635 767 |  | 
| 636 | 
            -
             | 
| 637 | 
            -
             | 
| 638 | 
            -
             | 
| 639 | 
            -
             | 
| 768 | 
            +
                // Triggered when local video stream is available (e.g.: Local video added succesfully in selfVideoHTMLElement)
         | 
| 769 | 
            +
                VoiceVideoCallingSDK.onLocalVideoStreamAdded(() => {
         | 
| 770 | 
            +
                    ...
         | 
| 771 | 
            +
                });
         | 
| 640 772 |  | 
| 641 | 
            -
             | 
| 642 | 
            -
             | 
| 643 | 
            -
             | 
| 644 | 
            -
             | 
| 773 | 
            +
                // Triggered when local video stream is unavailable (e.g.: Customer turning off local video)
         | 
| 774 | 
            +
                VoiceVideoCallingSDK.onLocalVideoStreamRemoved(() => {
         | 
| 775 | 
            +
                    ...
         | 
| 776 | 
            +
                });
         | 
| 645 777 |  | 
| 646 | 
            -
             | 
| 647 | 
            -
             | 
| 648 | 
            -
             | 
| 649 | 
            -
             | 
| 778 | 
            +
                // Triggered when remote video stream is available (e.g.: Remote video added succesfully in remoteVideoHTMLElement)
         | 
| 779 | 
            +
                VoiceVideoCallingSDK.onRemoteVideoStreamAdded(() => {
         | 
| 780 | 
            +
                    ...
         | 
| 781 | 
            +
                });
         | 
| 650 782 |  | 
| 651 | 
            -
             | 
| 652 | 
            -
             | 
| 653 | 
            -
             | 
| 654 | 
            -
             | 
| 783 | 
            +
                // Triggered when remote video stream is unavailable (e.g.: Agent turning off remote video)
         | 
| 784 | 
            +
                VoiceVideoCallingSDK.onRemoteVideoStreamRemoved(() => {
         | 
| 785 | 
            +
                    ...
         | 
| 786 | 
            +
                });
         | 
| 655 787 |  | 
| 656 | 
            -
             | 
| 657 | 
            -
             | 
| 788 | 
            +
                // Triggered when current call has ended or disconnected regardless the party
         | 
| 789 | 
            +
                VoiceVideoCalling.onCallDisconnected(() => {
         | 
| 790 | 
            +
                    ...
         | 
| 791 | 
            +
                });
         | 
| 658 792 |  | 
| 659 | 
            -
             | 
| 660 | 
            -
             | 
| 793 | 
            +
                // Check if microphone is muted
         | 
| 794 | 
            +
                const isMicrophoneMuted = VoiceVideoCallingSDK.isMicrophoneMuted();
         | 
| 661 795 |  | 
| 662 | 
            -
             | 
| 663 | 
            -
             | 
| 796 | 
            +
                // Check if remote video is available
         | 
| 797 | 
            +
                const isRemoteVideoEnabled = VoiceVideoCallingSDK.isRemoteVideoEnabled();
         | 
| 664 798 |  | 
| 665 | 
            -
             | 
| 666 | 
            -
             | 
| 667 | 
            -
                        withVideo: true // Accept call with/without video stream
         | 
| 668 | 
            -
                    };
         | 
| 669 | 
            -
                    await VoiceVideoCallingSDK.acceptCall(acceptCallConfig);
         | 
| 799 | 
            +
                // Check if local video is available
         | 
| 800 | 
            +
                const isLocalVideoEnabled = VoiceVideoCallingSDK.isLocalVideoEnabled();
         | 
| 670 801 |  | 
| 671 | 
            -
             | 
| 672 | 
            -
             | 
| 802 | 
            +
                // Accepts incoming call
         | 
| 803 | 
            +
                const acceptCallConfig = {
         | 
| 804 | 
            +
                    withVideo: true // Accept call with/without video stream
         | 
| 805 | 
            +
                };
         | 
| 806 | 
            +
                await VoiceVideoCallingSDK.acceptCall(acceptCallConfig);
         | 
| 673 807 |  | 
| 674 | 
            -
             | 
| 675 | 
            -
             | 
| 808 | 
            +
                // Rejects incoming call
         | 
| 809 | 
            +
                await VoiceVideoCallingSDK.rejectCall();
         | 
| 676 810 |  | 
| 677 | 
            -
             | 
| 678 | 
            -
             | 
| 811 | 
            +
                // Ends/Stops current call
         | 
| 812 | 
            +
                await VoiceVideoCallingSDK.stopCall();
         | 
| 679 813 |  | 
| 680 | 
            -
             | 
| 681 | 
            -
             | 
| 814 | 
            +
                // Mute/Unmute current call
         | 
| 815 | 
            +
                await VoiceVideoCallingSDK.toggleMute()
         | 
| 682 816 |  | 
| 683 | 
            -
             | 
| 684 | 
            -
             | 
| 685 | 
            -
             | 
| 817 | 
            +
                // Display/Hide local video of current call
         | 
| 818 | 
            +
                await VoiceVideoCallingSDK.toggleLocalVideo()
         | 
| 819 | 
            +
             | 
| 820 | 
            +
                // Clean up VoiceVideoCallingSDK (e.g.: Usually called when customer ends chat session)
         | 
| 821 | 
            +
                VoiceVideoCallingSDK.close();
         | 
| 822 | 
            +
            }
         | 
| 686 823 | 
             
            ```
         | 
| 687 824 |  | 
| 688 825 | 
             
            ## Feature Comparisons
         | 
| @@ -727,20 +864,20 @@ Some of the data being collected are the following: | |
| 727 864 | 
             
            If your organization is concerned about the data collected by the Chat SDK, you have the option to turn off automatic data collection by adding a flag in the `ChatSDKConfig`.
         | 
| 728 865 |  | 
| 729 866 | 
             
            ```ts
         | 
| 730 | 
            -
             | 
| 731 | 
            -
             | 
| 732 | 
            -
             | 
| 733 | 
            -
             | 
| 734 | 
            -
             | 
| 867 | 
            +
            const omnichannelConfig = {
         | 
| 868 | 
            +
                orgUrl: "",
         | 
| 869 | 
            +
                orgId: "",
         | 
| 870 | 
            +
                widgetId: ""
         | 
| 871 | 
            +
            };
         | 
| 735 872 |  | 
| 736 | 
            -
             | 
| 737 | 
            -
             | 
| 738 | 
            -
             | 
| 739 | 
            -
             | 
| 740 | 
            -
             | 
| 873 | 
            +
            const chatSDKConfig = {
         | 
| 874 | 
            +
                telemetry: {
         | 
| 875 | 
            +
                    disable: true // Disable telemetry
         | 
| 876 | 
            +
                }
         | 
| 877 | 
            +
            };
         | 
| 741 878 |  | 
| 742 | 
            -
             | 
| 743 | 
            -
             | 
| 879 | 
            +
            const chatSDK = new OmnichannelChatSDK.OmnichannelChatSDK(omnichannelConfig, chatSDKConfig);
         | 
| 880 | 
            +
            await chatSDK.initialize();
         | 
| 744 881 | 
             
            ```
         | 
| 745 882 |  | 
| 746 883 | 
             
            # Contributing
         |