Delay between different answers

Hi,

Our goal is to have delay between different output and using typing indicator. We want to set it globally and not in every flow.
We need to have delay both when giving the first response but also after every chatbubble if its more than one answer after each other.

Our developer have try to use this:

But we have a problem when using || to create a new bubble.

I need to understand if its possible to fix this in some way?

Hi. Please use the following extension (to be placed where you usually place TWC extensions - between the core code and initialization):


(() => {

var storage, delayId, messageQueue, bAlreadyStarted, bHeadBeingProcessed;


const splitter = /\s*\|\|\s*/m, typingIndicator = { author: 'bot' },

MESSAGE_QUEUE = 'twc_responseDelay_messageQueue',
ALREADY_STARTED = 'twc_responseDelay_alreadyStarted',

stringAsBoolean = s => s && (s = s.trim()).length !== 0 && s != 0 && s.toLowerCase() !== 'false',


queueMessage = message => {
    messageQueue.push(message);
    storage.setItem(MESSAGE_QUEUE, JSON.stringify(messageQueue));
},


queueTextsAsBotMessages = tt => {
    for (var i = 0; i < tt.length; i++) {
        messageQueue.push({
            type: 'text',
            author: 'bot',
            data: { text: tt[i] }
        });
    }
    storage.setItem(MESSAGE_QUEUE, JSON.stringify(messageQueue));
},


processQueuedMessages = () => {
    if (messageQueue.length === 0 || bHeadBeingProcessed) return;
    bHeadBeingProcessed = true;
    const m = messageQueue[0];
    var x;
    if (bAlreadyStarted) {
        if (m.type === 'system') x = 0;
        else {
            TeneoWebChat.call('show_typing_indicator', typingIndicator);
            x = m.data.text;
            x = ('string' === typeof x) ? 1400 * (x.length / (x.length + 50)) + 600 : 1000;
        }
    } else {
        storage.setItem(ALREADY_STARTED, '1');
        bAlreadyStarted = true;
        x = 0;
    }
    delayId = setTimeout(() => {
        TeneoWebChat.call('hide_typing_indicator', typingIndicator);
        messageQueue.shift();
        bHeadBeingProcessed = false;
        m.data._responseDelayExtensionProcessed = true;
        TeneoWebChat.call('add_message', m);
        if (messageQueue.length === 0) {
            storage.setItem(MESSAGE_QUEUE, '');
            delayId = null;
        } else {
            storage.setItem(MESSAGE_QUEUE, JSON.stringify(messageQueue));
            setTimeout(processQueuedMessages);
        }
    }, x);
},


rushQueuedMessages = () => {
    if (messageQueue.length === 0) return;
    if (delayId != null) {
        clearTimeout(delayId);
        delayId = null;
    }
    TeneoWebChat.call('hide_typing_indicator', typingIndicator);
    messageQueue.forEach(m => {
        m.data._responseDelayExtensionProcessed = true;
        TeneoWebChat.call('add_message', m);
    });
    messageQueue = [];
    storage.setItem(MESSAGE_QUEUE, '');
    bHeadBeingProcessed = false;
};


TeneoWebChat.on('ready', () => {
    storage = TeneoWebChat.get('storage');
    bAlreadyStarted = stringAsBoolean(storage.getItem(ALREADY_STARTED));
    messageQueue = storage.getItem(MESSAGE_QUEUE);
    if (messageQueue == null || (messageQueue = messageQueue.trim()).length === 0) messageQueue = [];
    else {
        try {
            messageQueue = JSON.parse(messageQueue);
            if (Array.isArray(messageQueue)) processQueuedMessages();
            else {
                console.warn(MESSAGE_QUEUE + ' value is not an array', messageQueue);
                storage.removeItem(MESSAGE_QUEUE);
                messageQueue = [];
            }
        } catch (err) {
            console.warn(MESSAGE_QUEUE + ' value [ ' + messageQueue + ' ] could not be parsed', err);
            storage.removeItem(MESSAGE_QUEUE);
            messageQueue = [];
        }
    }
});


TeneoWebChat.on('new_message', payload => {
    const m = payload.message;
    if (m.data._responseDelayExtensionProcessed) return;
    payload.handledState.handled = true;
    if (m.author === 'bot' || !m.author) {
        if (m.type === 'text') {
            const tt = m.data.text.split(splitter);
            if (tt.length === 1) queueMessage(m);
            else queueTextsAsBotMessages(tt);
        } else {
            queueMessage(m);
        }
        processQueuedMessages();
    } else {
        rushQueuedMessages();
        bAlreadyStarted = true;
        storage.setItem(ALREADY_STARTED, '1');
        m.data._responseDelayExtensionProcessed = true;
        TeneoWebChat.call('add_message', m);
    }
});


TeneoWebChat.on('reset', () => {
    if (delayId != null) {
        clearTimeout(delayId);
        delayId = null;
    }
    messageQueue = [];
    bAlreadyStarted = false;
    bHeadBeingProcessed = false;
    storage.removeItem(MESSAGE_QUEUE);
    storage.removeItem(ALREADY_STARTED);
});

})();

Hi Alexander, thank you for the quick reply! The code you sent works great to add delay between chat bubbles. However, now if we want to add delay directly from Teneo in a script using sleep(300), that script delay won’t work. Would this issue be related to the above code? Since we are interrupting the natural handling of messages? Or is it unrelated?

Hi. You can use both delays (the TWC extension and the sleep() function). Even though they shouldn’t conflict with each other, I don’t see much use in combining both. You can then also get sequences of visual waiting and typing indicator effects you might not like, and you will have to mitigate them by changing the CSS.
You can adjust the delays of the messages in extension code.