tjtanjin / react-chatbotify

A modern React library for creating a flexible and extensible chatbot.
https://react-chatbotify.com
MIT License
135 stars 65 forks source link

[Help] How to keep bot typing status while Backend call is being made #12

Closed ahetawal-p closed 6 months ago

ahetawal-p commented 6 months ago

Bug Description I am follow this example to make an api call based on the user option selection. https://react-chatbotify.tjtanjin.com/docs/examples/smart_conversation

The api call might take a while to return, is there a way to persist the Both typing indicator, so the user knows that something is happing. Currently the bot typing indicator shows up for a brief moment, and then disappears, and the api call has still not returned. So the user is unsure whether they need to take some action or its still processing.

Either a way to show a loading indicator or bot typing indicator while the call is in flight, would be super helpful from UX perspective.

tjtanjin commented 6 months ago

Hey @ahetawal-p, the bot typing indicator should actually persist until a reply is provided by the bot. Do you have a code snippet I could use to reproduce and investigate the behavior you are seeing?

If you're not comfortable sharing it publicly, feel free to reach out in private on discord. Thanks!

ahetawal-p commented 6 months ago

Hi @tjtanjin Here is a sample bot I have been playing with :

const sleep = ms => new Promise(r => setTimeout(r, ms))
const helpOptions = ['A', 'B', 'C']

export const Chatbot = () => {
  const flow = {
    start: {
      message: 'Hey! Want to know insights. Try these options below',
      options: helpOptions,
      path: 'process_options',
    },
    prompt_again: {
      message: 'Do you need any other help?',
      options: helpOptions,
      path: 'process_options',
    },
    repeat: {
      transition: { duration: 1000 },
      path: 'prompt_again',
    },
    A: {
      message: async (_params: Params) => {
        const result = await sleep(7000)
        return 'ADetails'
      },
      path: 'repeat',
    },

    B: {
      message: async (_params: Params) => {
        const result = await sleep(7000)
        return 'bDetails'
      },
      path: 'repeat',
    },
    C: {
      message: async (_params: Params) => {
        const result = await sleep(7000)
        return 'CDetails'
      },
      path: 'repeat',
    },
    process_options: {
      transition: { duration: 0 },
      path: params => {
        switch (params.userInput) {
          case 'A':
            return 'A'
          case 'B':
            return 'A'
          case 'C':
            return 'C'
        }
        return 'repeat'
      },
    },
  }

  return (
      <ChatBot
        options={{
          theme: { embedded: true, showInputRow: false },
          fileAttachment: {
            disabled: true,
          },
          emoji: {
            disabled: true,
          },
       }
        flow={flow}
      />
  )
}

When I select "A" option, the api call is waiting for 7 secs, but the typing indicator goes away very soon.

tjtanjin commented 6 months ago

Hey @ahetawal-p, the reason why the bot typing indicator is disappearing for you is because of the process_options block. The logic for the bot typing indicator is as such:

1) On bot startup, preprocessing is done on start block 2) When user sends input, postprocessing is done on start block and preprocessing is done on the next block (in your case process_options) 3) The bot will continue to show typing indicator until step 2 is done 4) Bot waits for next user input

So why is process_options block a problem? Essentially, your typing indicator disappears because step 2 is completed and transitions to a third block (e.g. A). However, since the transition is done automatically, there is no typing indicator.

There are 2 possible solutions:

I'd love to show you this in code but I am on my phone and it's a little hard to type. Give the above suggestions a try first and if it still doesn't work, let me know I'll provide a code snippet later :)

ahetawal-p commented 6 months ago

Thanks @tjtanjin .. That fixed it.

Here my new flow

const processInput = (input: string) => {
  switch (input) {
    case 'A':
      return 'A'
    case 'B':
      return 'B'
    case 'C':
      return 'C'
  }
}

 const flow = {
    start: {
      message: 'Hey! Want to know insights. Try these options below',
      options: helpOptions,
      path: (params: Params) => {
        return processInput(params.userInput)
      },
    },
    A: {
      message: async (_params: Params) => {
        const result = await sleep(3000)
        return 'ADetails'
      },
      options: helpOptions,
      path: (params: Params) => {
        return processInput(params.userInput)
      },
    },

    B: {
      message: async (_params: Params) => {
        const result = await sleep(2000)
        return 'bDetails'
      },
      options: helpOptions,
      path: (params: Params) => {
        return processInput(params.userInput)
      },
    },
    C: {
      message: async (_params: Params) => {
        const result = await sleep(4000)
        return 'CDetails'
      },
      options: helpOptions,
      path: (params: Params) => {
        return processInput(params.userInput)
      },
    },
  }
ahetawal-p commented 6 months ago

@tjtanjin one last question, after user selects 'A' and and I see the message from bot with ADetails, how do I get the bot in the state to ask a repeat question.

 repeat: {
      message: 'Do you need any other help?',

      options: helpOptions,
      path: (params: Params) => {
        // params.injectMessage('Do you need any other help?')
        return processInput(params.userInput)
      },
    },
    A: {

      message: async (_params: Params) => {
        const result = await sleep(3000)
        return 'ADetails'
      },
     // options: helpOptions,
      path: 'repeat'
    },

Something along these lines ?

tjtanjin commented 6 months ago

@ahetawal-p Try adding a transition: {duration: 0} inside your A block

ahetawal-p commented 6 months ago

Great @tjtanjin that worked.

Thank you again for all your help !!!

ahetawal-p commented 6 months ago

Closing this out ...