fix(engine): 💄 Scroll when payment form appears
This commit is contained in:
@ -26,13 +26,13 @@ import {
|
|||||||
import { HostBubble } from './ChatStep/bubbles/HostBubble'
|
import { HostBubble } from './ChatStep/bubbles/HostBubble'
|
||||||
import { InputChatStep } from './ChatStep/InputChatStep'
|
import { InputChatStep } from './ChatStep/InputChatStep'
|
||||||
import { getLastChatStepType } from '../../services/chat'
|
import { getLastChatStepType } from '../../services/chat'
|
||||||
|
import { useChat } from 'contexts/ChatContext'
|
||||||
|
|
||||||
type ChatBlockProps = {
|
type ChatBlockProps = {
|
||||||
steps: Step[]
|
steps: Step[]
|
||||||
startStepIndex: number
|
startStepIndex: number
|
||||||
blockTitle: string
|
blockTitle: string
|
||||||
keepShowingHostAvatar: boolean
|
keepShowingHostAvatar: boolean
|
||||||
onScroll: () => void
|
|
||||||
onBlockEnd: (
|
onBlockEnd: (
|
||||||
edgeId?: string,
|
edgeId?: string,
|
||||||
updatedTypebot?: PublicTypebot | LinkedTypebot
|
updatedTypebot?: PublicTypebot | LinkedTypebot
|
||||||
@ -45,7 +45,6 @@ export const ChatBlock = ({
|
|||||||
steps,
|
steps,
|
||||||
startStepIndex,
|
startStepIndex,
|
||||||
blockTitle,
|
blockTitle,
|
||||||
onScroll,
|
|
||||||
onBlockEnd,
|
onBlockEnd,
|
||||||
keepShowingHostAvatar,
|
keepShowingHostAvatar,
|
||||||
}: ChatBlockProps) => {
|
}: ChatBlockProps) => {
|
||||||
@ -63,6 +62,7 @@ export const ChatBlock = ({
|
|||||||
pushEdgeIdInLinkedTypebotQueue,
|
pushEdgeIdInLinkedTypebotQueue,
|
||||||
} = useTypebot()
|
} = useTypebot()
|
||||||
const { resultValues, updateVariables, resultId } = useAnswers()
|
const { resultValues, updateVariables, resultId } = useAnswers()
|
||||||
|
const { scroll } = useChat()
|
||||||
const [processedSteps, setProcessedSteps] = useState<Step[]>([])
|
const [processedSteps, setProcessedSteps] = useState<Step[]>([])
|
||||||
const [displayedChunks, setDisplayedChunks] = useState<ChatDisplayChunk[]>([])
|
const [displayedChunks, setDisplayedChunks] = useState<ChatDisplayChunk[]>([])
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ export const ChatBlock = ({
|
|||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
onScroll()
|
scroll()
|
||||||
onNewStepDisplayed()
|
onNewStepDisplayed()
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [processedSteps])
|
}, [processedSteps])
|
||||||
@ -155,7 +155,7 @@ export const ChatBlock = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const displayNextStep = (answerContent?: string, isRetry?: boolean) => {
|
const displayNextStep = (answerContent?: string, isRetry?: boolean) => {
|
||||||
onScroll()
|
scroll()
|
||||||
const currentStep = [...processedSteps].pop()
|
const currentStep = [...processedSteps].pop()
|
||||||
if (currentStep) {
|
if (currentStep) {
|
||||||
if (isRetry && stepCanBeRetried(currentStep))
|
if (isRetry && stepCanBeRetried(currentStep))
|
||||||
|
@ -8,6 +8,7 @@ import { SendButton, Spinner } from '../SendButton'
|
|||||||
import { useFrame } from 'react-frame-component'
|
import { useFrame } from 'react-frame-component'
|
||||||
import { initStripe } from '../../../../../../lib/stripe'
|
import { initStripe } from '../../../../../../lib/stripe'
|
||||||
import { parseVariables } from 'services/variable'
|
import { parseVariables } from 'services/variable'
|
||||||
|
import { useChat } from 'contexts/ChatContext'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
options: PaymentInputOptions
|
options: PaymentInputOptions
|
||||||
@ -80,6 +81,7 @@ const CheckoutForm = ({
|
|||||||
variables: Variable[]
|
variables: Variable[]
|
||||||
viewerHost: string
|
viewerHost: string
|
||||||
}) => {
|
}) => {
|
||||||
|
const { scroll } = useChat()
|
||||||
const [ignoreFirstPaymentIntentCall, setIgnoreFirstPaymentIntentCall] =
|
const [ignoreFirstPaymentIntentCall, setIgnoreFirstPaymentIntentCall] =
|
||||||
useState(true)
|
useState(true)
|
||||||
|
|
||||||
@ -154,7 +156,10 @@ const CheckoutForm = ({
|
|||||||
setMessage('An unexpected error occured.')
|
setMessage('An unexpected error occured.')
|
||||||
}
|
}
|
||||||
|
|
||||||
const showPayButton = () => setIsPayButtonVisible(true)
|
const showPayButton = () => {
|
||||||
|
setIsPayButtonVisible(true)
|
||||||
|
scroll()
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
|
@ -8,6 +8,7 @@ import { Block, Edge, PublicTypebot, Theme, VariableWithValue } from 'models'
|
|||||||
import { byId, isNotDefined } from 'utils'
|
import { byId, isNotDefined } from 'utils'
|
||||||
import { animateScroll as scroll } from 'react-scroll'
|
import { animateScroll as scroll } from 'react-scroll'
|
||||||
import { LinkedTypebot, useTypebot } from 'contexts/TypebotContext'
|
import { LinkedTypebot, useTypebot } from 'contexts/TypebotContext'
|
||||||
|
import { ChatContext } from 'contexts/ChatContext'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
theme: Theme
|
theme: Theme
|
||||||
@ -104,17 +105,19 @@ export const ConversationContainer = ({
|
|||||||
ref={scrollableContainer}
|
ref={scrollableContainer}
|
||||||
className="overflow-y-scroll w-full lg:w-3/4 min-h-full rounded lg:px-5 px-3 pt-10 relative scrollable-container typebot-chat-view"
|
className="overflow-y-scroll w-full lg:w-3/4 min-h-full rounded lg:px-5 px-3 pt-10 relative scrollable-container typebot-chat-view"
|
||||||
>
|
>
|
||||||
{displayedBlocks.map((displayedBlock, idx) => (
|
<ChatContext onScroll={autoScrollToBottom}>
|
||||||
<ChatBlock
|
{displayedBlocks.map((displayedBlock, idx) => (
|
||||||
key={displayedBlock.block.id + idx}
|
<ChatBlock
|
||||||
steps={displayedBlock.block.steps}
|
key={displayedBlock.block.id + idx}
|
||||||
startStepIndex={displayedBlock.startStepIndex}
|
steps={displayedBlock.block.steps}
|
||||||
onScroll={autoScrollToBottom}
|
startStepIndex={displayedBlock.startStepIndex}
|
||||||
onBlockEnd={displayNextBlock}
|
onBlockEnd={displayNextBlock}
|
||||||
blockTitle={displayedBlock.block.title}
|
blockTitle={displayedBlock.block.title}
|
||||||
keepShowingHostAvatar={idx === displayedBlocks.length - 1}
|
keepShowingHostAvatar={idx === displayedBlocks.length - 1}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
|
</ChatContext>
|
||||||
|
|
||||||
{/* We use a block to simulate padding because it makes iOS scroll flicker */}
|
{/* We use a block to simulate padding because it makes iOS scroll flicker */}
|
||||||
<div className="w-full h-32" ref={bottomAnchor} />
|
<div className="w-full h-32" ref={bottomAnchor} />
|
||||||
</div>
|
</div>
|
||||||
|
28
packages/bot-engine/src/contexts/ChatContext.tsx
Normal file
28
packages/bot-engine/src/contexts/ChatContext.tsx
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import React, { createContext, ReactNode, useContext } from 'react'
|
||||||
|
|
||||||
|
const chatContext = createContext<{
|
||||||
|
scroll: () => void
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
//@ts-ignore
|
||||||
|
}>({})
|
||||||
|
|
||||||
|
export const ChatContext = ({
|
||||||
|
children,
|
||||||
|
onScroll,
|
||||||
|
}: {
|
||||||
|
children: ReactNode
|
||||||
|
onScroll: () => void
|
||||||
|
}) => {
|
||||||
|
const scroll = onScroll
|
||||||
|
return (
|
||||||
|
<chatContext.Provider
|
||||||
|
value={{
|
||||||
|
scroll,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</chatContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useChat = () => useContext(chatContext)
|
Reference in New Issue
Block a user