diff --git a/packages/botonic-react/src/experimental/dev-app.jsx b/packages/botonic-react/src/experimental/dev-app.jsx index 5b7ec22341..f71cf09fec 100644 --- a/packages/botonic-react/src/experimental/dev-app.jsx +++ b/packages/botonic-react/src/experimental/dev-app.jsx @@ -99,8 +99,10 @@ export class DevApp extends WebchatApp { enableAnimations={enableAnimations} storage={storage} storageKey={storageKey} - getString={(stringId, session) => this.bot.getString(stringId, session)} - setLocale={(locale, session) => this.bot.setLocale(locale, session)} + getString={(stringId, botState) => + this.bot.getString(stringId, botState) + } + setLocale={(locale, botState) => this.bot.setLocale(locale, botState)} onInit={(...args) => this.onInitWebchat(...args)} onOpen={(...args) => this.onOpenWebchat(...args)} onClose={(...args) => this.onCloseWebchat(...args)} diff --git a/packages/botonic-react/src/experimental/index.js b/packages/botonic-react/src/experimental/index.js index 04ac998e1e..e2ea640cc3 100644 --- a/packages/botonic-react/src/experimental/index.js +++ b/packages/botonic-react/src/experimental/index.js @@ -38,9 +38,9 @@ class WebsocketBackendService { // On Event Received... this.wsClient.addEventListener('message', event => { console.log(event, this.onEvent) - const message = JSON.parse(decode(event.data)) + const eventData = JSON.parse(decode(event.data)) if (this.onEvent && typeof this.onEvent === 'function') - this.onEvent({ message }) + this.onEvent(eventData) }) } async doAuthAndUpdateJwt() { @@ -72,7 +72,7 @@ class WebsocketBackendService { `${REST_API_URL}events/`, { message, - sender: user, + sender: user, // TODO: Really needed or we should pass user information through JWT? }, { headers: { Authorization: 'Bearer ' + this.jwt } } // Note: Do not use string template as it will convert the token with commas, which will be invalid ) @@ -85,14 +85,14 @@ class WebsocketBackendService { if (hasErrors) { // TODO: Handle rest of errors await this.doAuthAndUpdateJwt() - await this.postMessage(user, message) + // await this.postMessage(user, message) // Temporary, avoid infinite events loop } } } export class FullstackProdApp extends WebchatApp { - async onUserInput({ user, input }) { - this.onMessage && this.onMessage(this, { from: 'user', message: input }) + async onUserInput({ user, input, session, botState }) { + this.onMessage && this.onMessage(this, { from: input.from, message: input }) this.backendService.postMessage(user, input) } @@ -100,7 +100,7 @@ export class FullstackProdApp extends WebchatApp { return await this.backendService.doAuth({ userId }) } - onStateChange({ session: { user }, messagesJSON, jwt, updateJwt }) { + onStateChange({ user, messagesJSON, jwt, updateJwt }) { if (!this.backendService && user) { const lastMessage = messagesJSON[messagesJSON.length - 1] this.backendService = new WebsocketBackendService({ @@ -121,8 +121,8 @@ export class FullstackDevApp extends DevApp { console.log('FullstackDevApp ', args.playgroundCode) } - async onUserInput({ user, input }) { - this.onMessage && this.onMessage(this, { from: 'user', message: input }) + async onUserInput({ user, input, session, botState }) { + this.onMessage && this.onMessage(this, { from: input.from, message: input }) this.backendService && this.backendService.postMessage(user, input) } @@ -176,8 +176,10 @@ export class FullstackDevApp extends DevApp { storageKey={storageKey} playgroundCode={this.playgroundCode} onStateChange={webchatState => this.onStateChange(webchatState)} - getString={(stringId, session) => this.bot.getString(stringId, session)} - setLocale={(locale, session) => this.bot.setLocale(locale, session)} + getString={(stringId, botState) => + this.bot.getString(stringId, botState) + } + setLocale={(locale, botState) => this.bot.setLocale(locale, botState)} onInit={(...args) => this.onInitWebchat(...args)} onOpen={(...args) => this.onOpenWebchat(...args)} onClose={(...args) => this.onCloseWebchat(...args)} @@ -191,7 +193,7 @@ export class FullstackDevApp extends DevApp { return await this.backendService.doAuth({ userId }) } - onStateChange({ session: { user }, messagesJSON, jwt, updateJwt }) { + onStateChange({ user, messagesJSON, jwt, updateJwt }) { if (!this.backendService && user) { const lastMessage = messagesJSON[messagesJSON.length - 1] this.backendService = new WebsocketBackendService({ @@ -257,6 +259,7 @@ export class BrowserProdApp extends WebchatApp { ...botOptions, }) } + // TODO: Review how this be done for only browser versions async onUserInput({ input, session, lastRoutePath }) { this.onMessage && this.onMessage(this, { from: 'user', message: input }) const resp = await this.bot.input({ input, session, lastRoutePath }) @@ -277,10 +280,10 @@ export { ShareButton } from '../components/share-button' export { Subtitle } from '../components/subtitle' export { Title } from '../components/title' export { WebchatSettings } from '../components/webchat-settings' -export { RequestContext, WebchatContext } from '../contexts' export { staticAsset } from '../util/environment' export { getBotonicApp } from '../webchat' export { WebviewApp } from '../webview' +export { RequestContext, WebchatContext } from './contexts' // Experimental export { Audio } from './components/audio' export { Carousel } from './components/carousel' diff --git a/packages/botonic-react/src/experimental/util/webchat.js b/packages/botonic-react/src/experimental/util/webchat.js index 217f38da15..806aa4339f 100644 --- a/packages/botonic-react/src/experimental/util/webchat.js +++ b/packages/botonic-react/src/experimental/util/webchat.js @@ -1,3 +1,4 @@ +import { PROVIDER } from '@botonic/core' import merge from 'lodash.merge' import UAParser from 'ua-parser-js' import { v4 as uuidv4 } from 'uuid' @@ -34,14 +35,14 @@ export const createUser = () => { return { id: uuidv4(), name, + channel: PROVIDER.DEV, } } -export const initSession = session => { - if (!session) session = {} - const hasUserId = session.user && session.user.id !== undefined - if (!session.user || Object.keys(session.user).length === 0 || !hasUserId) - session.user = !hasUserId ? merge(session.user, createUser()) : createUser() - return session + +export const initUser = user => { + if (!user) return createUser() + if (user && !user.id) return merge(user, createUser()) + return user } export const shouldKeepSessionOnReload = ({ diff --git a/packages/botonic-react/src/experimental/webchat-app.jsx b/packages/botonic-react/src/experimental/webchat-app.jsx index c8356af188..7fbec07bec 100644 --- a/packages/botonic-react/src/experimental/webchat-app.jsx +++ b/packages/botonic-react/src/experimental/webchat-app.jsx @@ -139,22 +139,27 @@ export class WebchatApp { } onServiceEvent(event) { - if (event.action === 'connectionChange') + const { action, ...eventData } = event + if (action === 'connectionChange') this.webchatRef.current.setOnline(event.online) - // TODO: Temporary solution, decide how we will send these events in next iterations - else if (event.message.action === 'update_message_info') { - const { message } = event.message - this.updateMessageInfo(message.id, message) - } else if (event.action === 'update_message_info') - this.updateMessageInfo(event.message.id, event.message) - else if (event.message.type === 'update_webchat_settings') - this.updateWebchatSettings(event.message.data) - else if (event.message.type === 'sender_action') - this.setTyping(event.message.data === 'typing_on') - else { + else if (action === 'update_message_info') { + this.updateMessageInfo(eventData.id, eventData) + } else if (action === 'update_user') { + this.updateUser(eventData) + } else if (action === 'update_session') { + this.updateSession(eventData) + } else if (action === 'update_bot_state') { + this.updateBotState(eventData) + } + // TODO: Discuss how this updates to be done + else if (eventData.type === 'update_webchat_settings') + this.updateWebchatSettings(event.data) + else if (eventData.type === 'sender_action') + this.setTyping(event.data === 'typing_on') + else if (eventData.eventType === 'message') { this.onMessage && - this.onMessage(this, { from: SENDERS.bot, message: event.message }) - this.addBotMessage(event.message) + this.onMessage(this, { from: SENDERS.bot, message: eventData }) + this.addBotMessage(eventData) } } @@ -162,6 +167,14 @@ export class WebchatApp { this.webchatRef.current.updateUser(user) } + updateSession(session) { + this.webchatRef.current.updateSession(session) + } + + updateBotState(botState) { + this.webchatRef.current.updateBotState(botState) + } + addBotMessage(message) { this.webchatRef.current.addBotResponse({ response: msgToBotonic( diff --git a/packages/botonic-react/src/experimental/webchat/actions.jsx b/packages/botonic-react/src/experimental/webchat/actions.jsx index 2c11e7acc9..c2dad111b3 100644 --- a/packages/botonic-react/src/experimental/webchat/actions.jsx +++ b/packages/botonic-react/src/experimental/webchat/actions.jsx @@ -20,3 +20,5 @@ export const UPDATE_LAST_MESSAGE_DATE = 'updateLastMessageDate' export const SET_CURRENT_ATTACHMENT = 'setCurrentAttachment' export const SET_ONLINE = 'setOnline' export const UPDATE_JWT = 'updateJwt' +export const UPDATE_USER = 'updateUser' +export const UPDATE_BOT_STATE = 'updateBotState' diff --git a/packages/botonic-react/src/experimental/webchat/hooks.js b/packages/botonic-react/src/experimental/webchat/hooks.js index ea0d5067d8..740f69fef8 100644 --- a/packages/botonic-react/src/experimental/webchat/hooks.js +++ b/packages/botonic-react/src/experimental/webchat/hooks.js @@ -13,6 +13,7 @@ import { TOGGLE_EMOJI_PICKER, TOGGLE_PERSISTENT_MENU, TOGGLE_WEBCHAT, + UPDATE_BOT_STATE, UPDATE_DEV_SETTINGS, UPDATE_HANDOFF, UPDATE_JWT, @@ -24,10 +25,32 @@ import { UPDATE_SESSION, UPDATE_THEME, UPDATE_TYPING, + UPDATE_USER, UPDATE_WEBVIEW, } from './actions' import { webchatReducer } from './webchat-reducer' +export const initialUser = { + id: undefined, + name: undefined, + userName: undefined, + channel: undefined, + idFromChannel: undefined, + isOnline: true, +} + +const initialBotState = { + botId: undefined, + lastRoutePath: null, + isFirstInteraction: true, + retries: 0, + locale: undefined, + isHandoff: false, + isShadowing: false, +} + +const initialSession = {} + export const webchatInitialState = { width: WEBCHAT.DEFAULTS.WIDTH, height: WEBCHAT.DEFAULTS.HEIGHT, @@ -38,9 +61,9 @@ export const webchatInitialState = { typing: false, webview: null, webviewParams: null, - session: { user: null }, - lastRoutePath: null, - handoff: false, + // session: { user: null }, + // lastRoutePath: null, + // handoff: false, theme: { headerTitle: WEBCHAT.DEFAULTS.TITLE, brandColor: COLORS.BOTONIC_BLUE, @@ -53,7 +76,7 @@ export const webchatInitialState = { }, themeUpdates: {}, error: {}, - online: true, + isWebchatOnline: true, devSettings: { keepSessionOnReload: false }, isWebchatOpen: false, isEmojiPickerOpen: false, @@ -62,6 +85,9 @@ export const webchatInitialState = { lastMessageUpdate: undefined, currentAttachment: undefined, jwt: null, + user: initialUser, + session: initialSession, + botState: initialBotState, } export function useWebchat() { @@ -87,12 +113,23 @@ export function useWebchat() { type: UPDATE_WEBVIEW, payload: { webview, webviewParams: params }, }) - const updateSession = session => { + const updateSession = session => webchatDispatch({ type: UPDATE_SESSION, payload: session, }) - } + + const updateUser = user => + webchatDispatch({ + type: UPDATE_USER, + payload: user, + }) + + const updateBotState = botState => + webchatDispatch({ + type: UPDATE_BOT_STATE, + payload: botState, + }) const updateLastRoutePath = path => webchatDispatch({ @@ -198,6 +235,8 @@ export function useWebchat() { updateLastMessageDate, setCurrentAttachment, updateJwt, + updateBotState, + updateUser, } } diff --git a/packages/botonic-react/src/experimental/webchat/session-view.jsx b/packages/botonic-react/src/experimental/webchat/session-view.jsx index 85d254b703..cbf8d2a7b5 100644 --- a/packages/botonic-react/src/experimental/webchat/session-view.jsx +++ b/packages/botonic-react/src/experimental/webchat/session-view.jsx @@ -100,7 +100,9 @@ const KeepSessionContainer = styled.div` export const SessionView = props => { // eslint-disable-next-line react-hooks/rules-of-hooks const { webchatState, updateDevSettings } = props.webchatHooks || useWebchat() - const { latestInput: input, session, lastRoutePath } = webchatState + const { latestInput: input, session, botState } = webchatState + const { type, id, ...latestInputData } = input + const toggleSessionView = () => updateDevSettings({ ...webchatState.devSettings, @@ -122,7 +124,7 @@ export const SessionView = props => { label='INPUT:' value={ input && Object.keys(input).length - ? `[${input.type}] ${input.data || ''}` + ? `[${type}] ${JSON.stringify(latestInputData) || ''}` : '' } /> @@ -137,8 +139,12 @@ export const SessionView = props => { /> + + + + diff --git a/packages/botonic-react/src/experimental/webchat/webchat-dev.jsx b/packages/botonic-react/src/experimental/webchat/webchat-dev.jsx index 57c4b20d37..738705f577 100644 --- a/packages/botonic-react/src/experimental/webchat/webchat-dev.jsx +++ b/packages/botonic-react/src/experimental/webchat/webchat-dev.jsx @@ -5,7 +5,6 @@ import React, { forwardRef, useEffect, useState } from 'react' import { createPortal } from 'react-dom' import styled from 'styled-components' -import { SessionView } from '../../webchat/session-view' import MessengerLogo from './assets/messenger.svg' import Open from './assets/open.svg' import OpenNewWindow from './assets/open-new-window.svg' @@ -13,6 +12,7 @@ import TelegramLogo from './assets/telegram.svg' import WebchatLogo from './assets/webchat.svg' import WhatsappLogo from './assets/whatsapp.svg' import { useWebchat } from './hooks' +import { SessionView } from './session-view' import { Webchat } from './webchat' export const DebugTab = styled.div` @@ -341,22 +341,25 @@ export const PlaygroundPortal = props => document.body ) -const initialSession = { - is_first_interaction: true, - last_session: {}, - user: { - id: '000001', - username: 'johndoe', - name: 'John Doe', - provider: PROVIDER.DEV, - provider_id: '0000000', - extra_data: {}, - }, - organization: '', - bot: { - id: '0000000', - name: 'botName', - }, +const initialUser = { + id: '000001', + name: 'John Doe', + username: 'johndoe', + channel: PROVIDER.DEV, + idFromChannel: '0000000', + details: {}, +} + +const initialSession = {} + +const initialBotState = { + botId: '0000000', + isFirstInteraction: true, + retries: 0, + locale: undefined, + lastRoutePath: null, + isHandoff: false, + isShadowing: false, } // eslint-disable-next-line react/display-name @@ -377,7 +380,9 @@ export const WebchatDev = forwardRef((props, ref) => { {...props} ref={ref} webchatHooks={webchatHooks} + initialUser={initialUser} initialSession={initialSession} + initialBotState={initialBotState} initialDevSettings={{ keepSessionOnReload: webchatState.devSettings.keepSessionOnReload, showSessionView: webchatState.devSettings.showSessionView, diff --git a/packages/botonic-react/src/experimental/webchat/webchat-reducer.js b/packages/botonic-react/src/experimental/webchat/webchat-reducer.js index 06e9a0e4d4..c42ed9f5ea 100644 --- a/packages/botonic-react/src/experimental/webchat/webchat-reducer.js +++ b/packages/botonic-react/src/experimental/webchat/webchat-reducer.js @@ -6,6 +6,7 @@ import { TOGGLE_EMOJI_PICKER, TOGGLE_PERSISTENT_MENU, TOGGLE_WEBCHAT, + UPDATE_BOT_STATE, UPDATE_DEV_SETTINGS, UPDATE_HANDOFF, UPDATE_JWT, @@ -14,16 +15,16 @@ import { UPDATE_SESSION, UPDATE_THEME, UPDATE_TYPING, + UPDATE_USER, UPDATE_WEBVIEW, } from './actions' import { messagesReducer } from './messages-reducer' +// eslint-disable-next-line complexity export function webchatReducer(state, action) { switch (action.type) { case UPDATE_WEBVIEW: return { ...state, ...action.payload } - case UPDATE_SESSION: - return { ...state, session: { ...action.payload } } case UPDATE_TYPING: return { ...state, typing: action.payload } case UPDATE_THEME: @@ -55,6 +56,12 @@ export function webchatReducer(state, action) { return { ...state, currentAttachment: action.payload } case UPDATE_JWT: return { ...state, jwt: action.payload } + case UPDATE_USER: + return { ...state, user: action.payload } + case UPDATE_SESSION: + return { ...state, session: action.payload } + case UPDATE_BOT_STATE: + return { ...state, botState: action.payload } default: return messagesReducer(state, action) } diff --git a/packages/botonic-react/src/experimental/webchat/webchat.jsx b/packages/botonic-react/src/experimental/webchat/webchat.jsx index 9694184206..881b965a31 100644 --- a/packages/botonic-react/src/experimental/webchat/webchat.jsx +++ b/packages/botonic-react/src/experimental/webchat/webchat.jsx @@ -44,12 +44,6 @@ import { scrollToBottom } from '../../util/dom' import { isDev, resolveImage } from '../../util/environment' import { ConditionalWrapper } from '../../util/react' import { deserializeRegex, stringifyWithRegexs } from '../../util/regexs' -import { - _getThemeProperty, - getServerErrorMessage, - initSession, - shouldKeepSessionOnReload, -} from '../../util/webchat' import { Attachment } from '../../webchat/components/attachment' import { EmojiPicker, @@ -63,12 +57,6 @@ import { SendButton } from '../../webchat/components/send-button' import { TypingIndicator } from '../../webchat/components/typing-indicator' import { DeviceAdapter } from '../../webchat/devices/device-adapter' import { StyledWebchatHeader } from '../../webchat/header' -import { - useComponentWillMount, - usePrevious, - useTyping, - useWebchat, -} from '../../webchat/hooks' import { WebchatMessageList } from '../../webchat/message-list' import { WebchatReplies } from '../../webchat/replies' import { useStorageState } from '../../webchat/use-storage-state-hook' @@ -76,6 +64,18 @@ import { WebviewContainer } from '../../webchat/webview' import { Audio, Document, Image, Video } from '../components' import { Text } from '../components/text' import { msgToBotonic } from '../msg-to-botonic' +import { + _getThemeProperty, + getServerErrorMessage, + initUser, + shouldKeepSessionOnReload, +} from '../util/webchat' +import { + useComponentWillMount, + usePrevious, + useTyping, + useWebchat, +} from '../webchat/hooks' export const getParsedAction = botonicAction => { const splittedAction = botonicAction.split('create_case:') if (splittedAction.length <= 1) return undefined @@ -183,7 +183,6 @@ export const Webchat = forwardRef((props, ref) => { updateLatestInput, updateTyping, updateWebview, - updateSession, updateLastRoutePath, updateHandoff, updateTheme, @@ -200,14 +199,23 @@ export const Webchat = forwardRef((props, ref) => { updateLastMessageDate, setCurrentAttachment, updateJwt, + updateUser, + updateSession, + updateBotState, // eslint-disable-next-line react-hooks/rules-of-hooks } = props.webchatHooks || useWebchat() const firstUpdate = useRef(true) - const isOnline = () => webchatState.online + const isOnline = () => webchatState.isWebchatOnline const currentDateString = () => new Date().toISOString() const theme = merge(webchatState.theme, props.theme) - const { initialSession, initialDevSettings, onStateChange } = props + const { + initialUser, + initialSession, + initialBotState, + initialDevSettings, + onStateChange, + } = props const getThemeProperty = _getThemeProperty(theme) const storage = props.storage === undefined ? localStorage : props.storage @@ -229,14 +237,13 @@ export const Webchat = forwardRef((props, ref) => { JSON.parse( stringifyWithRegexs({ messages: webchatState.messagesJSON, - session: webchatState.session, - botState: webchatState.botState, - user: webchatState.user, - lastRoutePath: webchatState.lastRoutePath, devSettings: webchatState.devSettings, lastMessageUpdate: webchatState.lastMessageUpdate, themeUpdates: webchatState.themeUpdates, jwt: webchatState.jwt, + user: webchatState.user, + session: webchatState.session, + botState: webchatState.botState, }) ) ) @@ -263,16 +270,16 @@ export const Webchat = forwardRef((props, ref) => { const sendUserInput = async input => { input = { - ...input, ack: MessageEventAck.DRAFT, from: MessageEventFrom.USER, + ...input, } props.onUserInput && props.onUserInput({ - user: webchatState.session.user, + user: webchatState.user, input, session: webchatState.session, - lastRoutePath: webchatState.lastRoutePath, + botState: webchatState.botState, }) } @@ -306,16 +313,18 @@ export const Webchat = forwardRef((props, ref) => { // Load initial state from storage useEffect(() => { - let { + const { messages, - session, lastRoutePath, devSettings, lastMessageUpdate, themeUpdates, + user, + session, + botState, } = botonicState || {} - session = initSession(session) - updateSession(session) + updateUser({ ...initialUser, ...initUser(user) }) + if (shouldKeepSessionOnReload({ initialDevSettings, devSettings })) { if (messages) { messages.forEach(m => { @@ -328,12 +337,15 @@ export const Webchat = forwardRef((props, ref) => { if (newComponent) addMessageComponent(newComponent) }) } - if (initialSession) updateSession(merge(initialSession, session)) - if (lastRoutePath) updateLastRoutePath(lastRoutePath) + if (initialSession) { + updateSession(merge(initialSession, session)) + } + if (initialBotState) { + updateBotState({ ...initialBotState, ...botState }) + } } else { - session.__retries = 0 - session.is_first_interaction = true updateSession(merge(initialSession, session)) + updateBotState({ ...initialBotState, ...botState }) } if (devSettings) updateDevSettings(devSettings) else if (initialDevSettings) updateDevSettings(initialDevSettings) @@ -350,21 +362,26 @@ export const Webchat = forwardRef((props, ref) => { }, [webchatState.isWebchatOpen]) useEffect(() => { - if (onStateChange && typeof onStateChange === 'function') { + if ( + onStateChange && + typeof onStateChange === 'function' && + webchatState.user.id + ) { onStateChange({ ...webchatState, updateJwt }) } saveWebchatState(webchatState) }, [ webchatState.messagesJSON, - webchatState.session, - webchatState.lastRoutePath, webchatState.devSettings, webchatState.lastMessageUpdate, webchatState.jwt, + webchatState.user, + webchatState.session, + webchatState.botState, ]) useAsyncEffect(async () => { - if (!webchatState.online) { + if (!webchatState.isWebchatOnline) { setError({ message: getServerErrorMessage(props.server), }) @@ -373,7 +390,7 @@ export const Webchat = forwardRef((props, ref) => { setError(undefined) } } - }, [webchatState.online]) + }, [webchatState.isWebchatOnline]) useTyping({ webchatState, updateTyping, updateMessage, host }) @@ -557,27 +574,28 @@ export const Webchat = forwardRef((props, ref) => { https://stackoverflow.com/questions/37949981/call-child-method-from-parent */ - const updateSessionWithUser = userToUpdate => - updateSession(merge(webchatState.session, { user: userToUpdate })) + const mergeAndUpdateUser = userToUpdate => + updateUser(merge(webchatState.user, userToUpdate)) useImperativeHandle(ref, () => ({ addBotResponse: ({ response, session, lastRoutePath }) => { updateTyping(false) if (Array.isArray(response)) response.map(r => addMessageComponent(r)) else if (response) addMessageComponent(response) - if (session) { - updateSession(merge(session, { user: webchatState.session.user })) - const action = session._botonic_action || '' - const handoff = action.startsWith('create_case') - if (handoff && isDev) addMessageComponent() - updateHandoff(handoff) - } - if (lastRoutePath) updateLastRoutePath(lastRoutePath) updateLastMessageDate(currentDateString()) }, setTyping: typing => updateTyping(typing), addUserMessage: message => sendInput(message), - updateUser: updateSessionWithUser, + updateUser: mergeAndUpdateUser, + updateBotState: botState => { + // TODO: Review handoff logic for 1.0 + // const action = botState.botonicAction || '' + // // const isHandoff = action.startsWith('create_case') + if (botState.isHandoff && isDev) addMessageComponent() + updateBotState(botState) + // updateHandoff(botState.isHandoff) + }, + updateSession: updateSession, openWebchat: () => toggleWebchat(true), closeWebchat: () => toggleWebchat(false), toggleWebchat: () => toggleWebchat(!webchatState.isWebchatOpen), @@ -610,22 +628,26 @@ export const Webchat = forwardRef((props, ref) => { })) const resolveCase = () => { - updateHandoff(false) - updateSession({ ...webchatState.session, _botonic_action: null }) + // updateHandoff(false) + updateBotState({ + ...webchatState.botState, + isHandoff: false, + botonicAction: null, + }) } - const prevSession = usePrevious(webchatState.session) + const previousBotState = usePrevious(webchatState.botState) useEffect(() => { // Resume conversation after handoff if ( - prevSession && - prevSession._botonic_action && - !webchatState.session._botonic_action + previousBotState && + previousBotState.botonicAction && + !webchatState.botState.botonicAction ) { - const action = getParsedAction(prevSession._botonic_action) + const action = getParsedAction(previousBotState.botonicAction) if (action && action.on_finish) sendPayload(action.on_finish) } - }, [webchatState.session._botonic_action]) + }, [webchatState.botState.botonicAction]) const sendText = async (text, payload) => { if (!text) return @@ -665,8 +687,8 @@ export const Webchat = forwardRef((props, ref) => { } const webviewRequestContext = { - getString: stringId => props.getString(stringId, webchatState.session), - setLocale: locale => props.getString(locale, webchatState.session), + getString: stringId => props.getString(stringId, webchatState.botState), + setLocale: locale => props.getString(locale, webchatState.botState), session: webchatState.session || {}, params: webchatState.webviewParams || {}, closeWebview: closeWebview, @@ -926,7 +948,7 @@ export const Webchat = forwardRef((props, ref) => { updateMessage, updateReplies, updateLatestInput, - updateUser: updateSessionWithUser, + updateUser: mergeAndUpdateUser, updateWebchatDevSettings: updateWebchatDevSettings, }} >