2
0

fix(engine): 💄 Scroll when payment form appears

This commit is contained in:
Baptiste Arnaud
2022-06-01 09:29:13 +02:00
parent 4f208a2d05
commit caa6015359
4 changed files with 52 additions and 16 deletions

View File

@ -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))

View File

@ -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

View File

@ -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>

View 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)