Search code examples
botframeworkdirect-line-botframework

Loader icon in Bot Framework Webchat


I am using Bot Framework Webchat. There are few user related data which I am posting using back channel post activity through the store option to greet the user.

<ReactWebChat
  activityMiddleware={ activityMiddleware }
  directLine={ window.WebChat.createDirectLine( this.state.token ) }
  store = {this.handleGetStore()}
  styleOptions={styleOptions}
/>

handleGetStore returns the store data:

handleGetStore(){
    const store = window.WebChat.createStore({}, ({ dispatch }) => next => action => {
        if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
            dispatch({
                type: 'WEB_CHAT/SEND_EVENT',
                payload: {
                    name: 'userDetail',
                    value: this.state.userDetail
                }
            });
        }
        return next(action);
    });
    return store;
}

When the connection initiates the loader appears.

enter image description here

After that there is delay of about 3-5 seconds before the welcome message appears and in the meantime the Webchat seems ready for the user.

enter image description here

A slight delay of 3 seconds is acceptable but quite often the delay is upto 10 seconds or more. I understand that this can be slightly improved by using the Always On feature of the App Service and scaling up the plan. Is there a way I can wait for the back channel welcome message to appear and show the loader until then?

Reference: https://github.com/microsoft/BotFramework-WebChat/pull/1866


Solution

  • Unfortunately, the connection status display relies on events received from DirectLineJs and Web Chat does not support customizing its behavior at the moment. That being said, there is a hacky way to accomplish what you're trying to do by dispatching pseudo DirectLine events.

    Here are the steps below:

    • Create a flag that will indicate whether or not the bot has sent a welcome message - received_welcome_message.

    • When Web Chat dispatches a connection fulfilled event, check the flag to ensure a welcome message has been received. If the bot has not sent a welcome message, dispatch the welcome event to the bot and reset the connection status to fulfilling.

    • When Web Chat receives an activity from the bot, check if it is a welcome message. I would recommend adding a name attribute to message on the bot side to check - await context.sendActivity({ text: 'Welcome', name: 'welcome'}). If the activity is a welcome message, dispatch a connection fulfilled event and set the flag to true.

    For more details take a look at the code snippets below.

    let received_welcome_message = false;
    const store = createStore(
      {},
      ({ dispatch}) => next => action => {
    
        if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
    
          if (!received_welcome_message) {
            dispatch({
              type: 'DIRECT_LINE/CONNECT_FULFILLING'
            });
            dispatch({
              type: 'WEB_CHAT/SEND_EVENT',
              payload: { name: 'webchat/join' }
            });
    
            return
          }
    
        } else if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY' && action.payload.activity.name === 'welcome') {
          received_welcome_message = true;
          dispatch({
            type: 'DIRECT_LINE/CONNECT_FULFILLED',
          });
        }
        return next(action);
      }
    );
    

    Edit

    A less hacky approach is to dispatch a post activity pending event when the connection to the bot is fulfilled to mimic the bot sending a welcome message. Note, that the bot is unaware of the mimicked activity. See the code snippet below.

    const store = createStore(
      {},
      ({ dispatch}) => next => action => {
        console.log(action)
        if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
          dispatch({
            type: 'DIRECT_LINE/POST_ACTIVITY_PENDING',
            meta: { method: 'keyboard' },
            payload: {
              activity: {
                from: { role: "bot" },
                text: "Welcome Message",
                textFormat: "plain",
                timestamp: new Date().toString(),
                type: "message"
              }
            }
          })
        }
        return next(action);
      }
    

    Hope this helps!