Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/botonic-plugin-flow-builder/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ export class FlowBuilderApi {
headers: { Authorization: `Bearer ${token}` },
})
this.request.session.organization_id = response.data.organization_id
this.request.session.bot.id = response.data.bot_id
this.request.session.bot = {
...this.request.session.bot,
id: response.data.bot_id,
}
}

getNodeByFlowId(id: string): HtNodeWithContent {
Expand Down
13 changes: 7 additions & 6 deletions packages/botonic-react/src/index-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
WebchatSettingsProps,
} from './components'
import { CloseWebviewOptions } from './contexts'
import { DevSettings } from './webchat/context/types'
import { UseWebchat } from './webchat/context/use-webchat'
import {
CoverComponentOptions,
Expand Down Expand Up @@ -90,7 +91,7 @@ export interface WebchatArgs {
defaultTyping?: number
storage?: Storage | null
storageKey?: string
onInit?: (app: WebchatApp, args: any) => void
onInit?: (app: WebchatApp, args: any) => Promise<void>
onOpen?: (app: WebchatApp, args: any) => void
onClose?: (app: WebchatApp, args: any) => void
onMessage?: (app: WebchatApp, message: WebchatMessage) => void
Expand All @@ -102,18 +103,18 @@ export interface WebchatArgs {
}

export interface WebchatProps {
webchatHooks?: UseWebchat
webchatHooks: UseWebchat
initialSession?: any
initialDevSettings?: any
initialDevSettings?: DevSettings
onStateChange: (args: OnStateChangeArgs) => void

shadowDOM?: any
theme?: WebchatTheme
storage?: Storage | null
storageKey?: string | (() => string)
storage: Storage
storageKey: string
defaultDelay?: number
defaultTyping?: number
onInit?: (args?: any) => void
onInit?: (args?: any) => Promise<void>
onOpen?: (args?: any) => void
onClose?: (args?: any) => void
onUserInput(args: OnUserInputArgs): Promise<void>
Expand Down
2 changes: 1 addition & 1 deletion packages/botonic-react/src/util/webchat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function getSystemLocale(user: Partial<ClientUser>) {
export const shouldKeepSessionOnReload = ({
initialDevSettings,
devSettings,
}) => !initialDevSettings || (devSettings && devSettings.keepSessionOnReload)
}) => !initialDevSettings || devSettings?.keepSessionOnReload

//TODO: Review param serverConfig if is of type ServerConfig this never have errorMessage
export const getServerErrorMessage = serverConfig => {
Expand Down
37 changes: 31 additions & 6 deletions packages/botonic-react/src/webchat-app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
WebchatTheme,
} from './webchat/theme/types'
import { Webchat } from './webchat/webchat'
import { WebchatHooks } from './webchat/webchat-hooks'

export class WebchatApp {
public theme?: Partial<WebchatTheme>
Expand All @@ -41,9 +42,9 @@ export class WebchatApp {
public shadowDOM?: boolean | (() => boolean)
public defaultDelay?: number
public defaultTyping?: number
public storage?: Storage | null
public storage: Storage
public storageKey: string
public onInit?: (app: WebchatApp, args: any) => void
public onInit?: (app: WebchatApp, args: any) => Promise<void>
public onOpen?: (app: WebchatApp, args: any) => void
public onClose?: (app: WebchatApp, args: any) => void
public onMessage?: (app: WebchatApp, message: WebchatMessage) => void
Expand Down Expand Up @@ -107,7 +108,7 @@ export class WebchatApp {
this.hostId = hostId || WEBCHAT.DEFAULTS.HOST_ID
this.defaultDelay = defaultDelay
this.defaultTyping = defaultTyping
this.storage = storage === undefined ? localStorage : storage
this.storage = !storage ? localStorage : storage
this.storageKey = storageKey || WEBCHAT.DEFAULTS.STORAGE_KEY
this.onInit = onInit
this.onOpen = onOpen
Expand Down Expand Up @@ -175,8 +176,8 @@ export class WebchatApp {
return node
}

onInitWebchat(...args: [any]) {
this.onInit && this.onInit(this, ...args)
async onInitWebchat(...args: [any]) {
this.onInit && (await this.onInit(this, ...args))
}

onOpenWebchat(...args: [any]) {
Expand Down Expand Up @@ -485,7 +486,31 @@ export class WebchatApp {
this.createRootElement(host)

return (
<Webchat
// <Webchat
// {...webchatOptions}
// ref={this.webchatRef}
// host={this.host}
// shadowDOM={this.shadowDOM}
// theme={theme as WebchatTheme}
// storage={this.storage}
// storageKey={this.storageKey}
// defaultDelay={defaultDelay}
// defaultTyping={defaultTyping}
// onInit={(...args: [any]) => this.onInitWebchat(...args)}
// onOpen={(...args: [any]) => this.onOpenWebchat(...args)}
// onClose={(...args: [any]) => this.onCloseWebchat(...args)}
// onUserInput={(...args: [any]) => this.onUserInput(...args)}
// onStateChange={(args: OnStateChangeArgs) => {
// this.onStateChange(args)
// }}
// onTrackEvent={(
// request: ActionRequest,
// eventName: string,
// args?: EventArgs
// ) => this.onTrackEventWebchat(request, eventName, args)}
// server={server}
// />
<WebchatHooks
{...webchatOptions}
ref={this.webchatRef}
host={this.host}
Expand Down
70 changes: 61 additions & 9 deletions packages/botonic-react/src/webchat/context/use-webchat.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
import { Session } from '@botonic/core'
import { useReducer, useRef } from 'react'
import merge from 'lodash.merge'
import { useEffect, useReducer, useRef } from 'react'

import { Reply } from '../../components'
import { Webview } from '../../components/index-types'
import { WebchatMessage } from '../../index-types'
import { msgToBotonic } from '../../msg-to-botonic'
import { initSession, shouldKeepSessionOnReload } from '../../util'
import { defaultTheme } from '../theme/default-theme'
import { WebchatTheme } from '../theme/types'
import { BotonicStorage } from '../use-botonic-storage'
import { WebchatAction } from './actions'
import { ClientInput, DevSettings, ErrorMessage, WebchatState } from './types'
import { webchatReducer } from './webchat-reducer'

function getWebchatInitialState(initialTheme: WebchatTheme): WebchatState {
function getWebchatInitialState(
initialTheme: WebchatTheme,
botonicStorage?: BotonicStorage,
initialSession?: Partial<Session>,
devSettings?: DevSettings
): WebchatState {
const initialStorageSession = initSession(botonicStorage?.session)
const session = merge(initialSession, initialStorageSession)
const lastMessageUpdate = botonicStorage?.lastMessageUpdate
const themeUpdates = botonicStorage?.themeUpdates || {}
const lastRoutePath = botonicStorage?.lastRoutePath
console.log('getWebchatInitialState devSettings', devSettings)

return {
replies: [],
messagesJSON: [],
Expand All @@ -19,20 +35,20 @@ function getWebchatInitialState(initialTheme: WebchatTheme): WebchatState {
typing: false,
webview: null,
webviewParams: null,
session: { user: undefined },
lastRoutePath: undefined,
session: session as Partial<Session>,
lastRoutePath: lastRoutePath,
handoff: false,
theme: initialTheme,
themeUpdates: {},
themeUpdates: themeUpdates,
error: {},
online: true,
devSettings: { keepSessionOnReload: false },
devSettings: devSettings || { keepSessionOnReload: false },
isWebchatOpen: false,
isEmojiPickerOpen: false,
isPersistentMenuOpen: false,
isCoverComponentOpen: false,
isCustomComponentRendered: false,
lastMessageUpdate: undefined,
lastMessageUpdate: lastMessageUpdate,
currentAttachment: undefined,
numUnreadMessages: 0,
isLastMessageVisible: true,
Expand Down Expand Up @@ -77,9 +93,20 @@ export interface UseWebchat {
inputPanelRef: React.MutableRefObject<HTMLDivElement | null>
}

export function useWebchat(theme?: WebchatTheme): UseWebchat {
export function useWebchat(
theme?: WebchatTheme,
botonicStorage?: BotonicStorage,
initialSession?: Partial<Session>,
devSettings?: DevSettings
): UseWebchat {
const initialTheme = theme || defaultTheme
const webchatInitialState = getWebchatInitialState(initialTheme)
console.log('useWebchat devSettings', devSettings)
const webchatInitialState = getWebchatInitialState(
initialTheme,
botonicStorage,
initialSession,
devSettings
)

const [webchatState, webchatDispatch] = useReducer(
webchatReducer,
Expand Down Expand Up @@ -245,6 +272,31 @@ export function useWebchat(theme?: WebchatTheme): UseWebchat {
})
}

useEffect(() => {
// const keepSessionOnReload = shouldKeepSessionOnReload({
// devSettings,
// initialDevSettings,
// })

const keepSessionOnReload = devSettings?.keepSessionOnReload
console.log('useWebchat useEffect keepSessionOnReload', keepSessionOnReload)
if (keepSessionOnReload) {
const messagesJSON = botonicStorage?.messages || []
for (const message of messagesJSON) {
addMessage(message)

const newMessageComponent = msgToBotonic(
{ ...message, delay: 0, typing: 0 },
initialTheme.message?.customTypes
)
if (newMessageComponent) {
//@ts-ignore
addMessageComponent(newMessageComponent)
}
}
}
}, [])

return {
addMessage,
addMessageComponent,
Expand Down
40 changes: 40 additions & 0 deletions packages/botonic-react/src/webchat/use-botonic-storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Session } from 'node:inspector'

import { WebchatMessage } from '../index-types'
import { stringifyWithRegexs } from '../util/regexs'
import { DevSettings } from './context/types'
import { WebchatTheme } from './theme/types'

export interface BotonicStorage {
messages: WebchatMessage[]
session: Session
lastRoutePath: string
devSettings: DevSettings
lastMessageUpdate: string
themeUpdates: WebchatTheme
}

export function useBotonicStorage(storage: Storage, storageKey: string) {
const getBotonicStorage = (): BotonicStorage | undefined => {
const botonicStorage = storage.getItem(storageKey)
return botonicStorage ? JSON.parse(botonicStorage) : undefined
}

const getBotonicStorageAttribute = <T = any>(key: string): T => {
const botonicStorage = getBotonicStorage()
return botonicStorage?.[key]
}

const setBotonicStorage = (value: any) => {
const stringValueJSON = JSON.stringify(
JSON.parse(stringifyWithRegexs(value))
)
storage.setItem(storageKey, stringValueJSON)
}

return {
getBotonicStorage,
setBotonicStorage,
getBotonicStorageAttribute,
}
}
8 changes: 3 additions & 5 deletions packages/botonic-react/src/webchat/use-storage-state-hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const IS_BROWSER =
typeof navigator !== 'undefined' &&
typeof document !== 'undefined'

export function useStorageState(storage, key, defaultValue) {
export function useStorageState(storage, key) {
let evtTarget

try {
Expand All @@ -17,7 +17,7 @@ export function useStorageState(storage, key, defaultValue) {

const raw = storage?.getItem(key)

const [value, setValue] = useState(raw ? JSON.parse(raw) : defaultValue)
const [value, setValue] = useState(raw ? JSON.parse(raw) : undefined)

const updater = useCallback(
(updatedValue, remove = false) => {
Expand All @@ -33,8 +33,6 @@ export function useStorageState(storage, key, defaultValue) {
[key]
)

defaultValue != null && !raw && updater(defaultValue)

useEffect(() => {
const listener = ({ detail }) => {
if (detail.key === key) {
Expand All @@ -51,5 +49,5 @@ export function useStorageState(storage, key, defaultValue) {
if (storage === null) {
return [undefined, undefined]
}
return [value, updater, () => updater(null, true)]
return [value, updater]
}
22 changes: 20 additions & 2 deletions packages/botonic-react/src/webchat/webchat-dev.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import styled from 'styled-components'

import { useWebchat } from './context/use-webchat'
import { SessionView } from './session-view'
import { useBotonicStorage } from './use-botonic-storage'
import { Webchat } from './webchat'

export const DebugTab = styled.div`
Expand Down Expand Up @@ -46,7 +47,24 @@ const initialSession = {

// eslint-disable-next-line react/display-name
export const WebchatDev = forwardRef((props, ref) => {
const webchatHooks = useWebchat()
const { getBotonicStorage } = useBotonicStorage(
props.storage,
props.storageKey
)
const devSettings =
getBotonicStorage()?.devSettings || props.initialDevSettings

console.log('devSettings', {
keepSessionOnReload: devSettings?.keepSessionOnReload,
showSessionView: devSettings?.showSessionView,
})

const webchatHooks = useWebchat(
undefined,
getBotonicStorage(),
initialSession,
devSettings
)
const { webchatState, updateTheme } = webchatHooks

/* TODO: webchatState.theme should be included in the dependencies array
Expand All @@ -63,7 +81,7 @@ export const WebchatDev = forwardRef((props, ref) => {
{...props}
ref={ref}
webchatHooks={webchatHooks}
initialSession={initialSession}
// initialSession={initialSession}
initialDevSettings={{
keepSessionOnReload: webchatState.devSettings.keepSessionOnReload,
showSessionView: webchatState.devSettings.showSessionView,
Expand Down
Loading
Loading