import { createSignal, onMount, Show, splitProps, onCleanup, createEffect, } from 'solid-js' import styles from '../../../assets/index.css' import { CommandData } from '../../commands' import { BubbleButton } from './BubbleButton' import { PreviewMessage, PreviewMessageProps } from './PreviewMessage' import { isDefined } from '@indite.io/lib' import { BubbleParams } from '../types' import { Bot, BotProps } from '../../../components/Bot' import { getPaymentInProgressInStorage } from '@/features/blocks/inputs/payment/helpers/paymentInProgressStorage' import { getBotOpenedStateFromStorage, removeBotOpenedStateInStorage, setBotOpenedStateInStorage, } from '@/utils/storage' import { EnvironmentProvider } from '@ark-ui/solid' export type BubbleProps = BotProps & BubbleParams & { onOpen?: () => void onClose?: () => void onPreviewMessageClick?: () => void } export const Bubble = (props: BubbleProps) => { const [bubbleProps, botProps] = splitProps(props, [ 'onOpen', 'onClose', 'previewMessage', 'onPreviewMessageClick', 'theme', 'autoShowDelay', ]) const [isMounted, setIsMounted] = createSignal(true) const [prefilledVariables, setPrefilledVariables] = createSignal( botProps.prefilledVariables ) const [isPreviewMessageDisplayed, setIsPreviewMessageDisplayed] = createSignal(false) const [previewMessage, setPreviewMessage] = createSignal< Pick >({ message: bubbleProps.previewMessage?.message ?? '', avatarUrl: bubbleProps.previewMessage?.avatarUrl, }) const [isBotOpened, setIsBotOpened] = createSignal(false) const [isBotStarted, setIsBotStarted] = createSignal(false) const [buttonSize, setButtonSize] = createSignal( parseButtonSize(bubbleProps.theme?.button?.size ?? 'medium') ) createEffect(() => { setButtonSize(parseButtonSize(bubbleProps.theme?.button?.size ?? 'medium')) }) let progressBarContainerRef onMount(() => { window.addEventListener('message', processIncomingEvent) const autoShowDelay = bubbleProps.autoShowDelay const previewMessageAutoShowDelay = bubbleProps.previewMessage?.autoShowDelay if (getBotOpenedStateFromStorage() || getPaymentInProgressInStorage()) openBot() if (isDefined(autoShowDelay)) { setTimeout(() => { openBot() }, autoShowDelay) } if (isDefined(previewMessageAutoShowDelay)) { setTimeout(() => { showMessage() }, previewMessageAutoShowDelay) } }) onCleanup(() => { window.removeEventListener('message', processIncomingEvent) }) createEffect(() => { if (!props.prefilledVariables) return setPrefilledVariables((existingPrefilledVariables) => ({ ...existingPrefilledVariables, ...props.prefilledVariables, })) }) const processIncomingEvent = (event: MessageEvent) => { const { data } = event if (!data.isFromBot) return if (data.command === 'open') openBot() if (data.command === 'close') closeBot() if (data.command === 'toggle') toggleBot() if (data.command === 'showPreviewMessage') showMessage(data.message) if (data.command === 'hidePreviewMessage') hideMessage() if (data.command === 'setPrefilledVariables') setPrefilledVariables((existingPrefilledVariables) => ({ ...existingPrefilledVariables, ...data.variables, })) if (data.command === 'unmount') unmount() } const openBot = () => { if (!isBotStarted()) setIsBotStarted(true) hideMessage() setIsBotOpened(true) if (isBotOpened()) bubbleProps.onOpen?.() } const closeBot = () => { setIsBotOpened(false) removeBotOpenedStateInStorage() if (isBotOpened()) bubbleProps.onClose?.() } const toggleBot = () => { isBotOpened() ? closeBot() : openBot() } const handlePreviewMessageClick = () => { bubbleProps.onPreviewMessageClick?.() openBot() } const showMessage = ( previewMessage?: Pick ) => { if (previewMessage) setPreviewMessage(previewMessage) if (isBotOpened()) return setIsPreviewMessageDisplayed(true) } const hideMessage = () => { setIsPreviewMessageDisplayed(false) } const unmount = () => { if (isBotOpened()) { closeBot() setTimeout(() => { setIsMounted(false) }, 200) } else setIsMounted(false) } const handleOnChatStatePersisted = (isPersisted: boolean) => { botProps.onChatStatePersisted?.(isPersisted) if (isPersisted) setBotOpenedStateInStorage() } console.log('botProps', botProps); return (
) } const parseButtonSize = ( size: NonNullable['button']>['size'] ): `${number}px` => size === 'medium' ? '48px' : size === 'large' ? '64px' : size ? size : '48px'