2
0

feat(bot): ️ Improve first paint delay

This commit is contained in:
Baptiste Arnaud
2022-06-12 07:57:35 +02:00
parent 4fd5d452a3
commit aeaaa5c398
13 changed files with 42 additions and 22 deletions

View File

@ -33,6 +33,7 @@ export const AvatarSideContainer = forwardRef(
}))
useEffect(() => {
if (!document) return
setShow(true)
const resizeObserver = new ResizeObserver(refreshTopOffset)
resizeObserver.observe(document.body)

View File

@ -12,7 +12,7 @@ type Props = {
export const showAnimationDuration = 400
export const EmbedBubble = ({ block, onTransitionEnd }: Props) => {
const { typebot } = useTypebot()
const { typebot, isLoading } = useTypebot()
const messageContainer = useRef<HTMLDivElement | null>(null)
const [isTyping, setIsTyping] = useState(true)
@ -22,9 +22,10 @@ export const EmbedBubble = ({ block, onTransitionEnd }: Props) => {
)
useEffect(() => {
if (!isTyping || isLoading) return
showContentAfterMediaLoad()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
}, [isLoading])
const showContentAfterMediaLoad = () => {
setTimeout(() => {

View File

@ -14,7 +14,7 @@ export const showAnimationDuration = 400
export const mediaLoadingFallbackTimeout = 5000
export const ImageBubble = ({ block, onTransitionEnd }: Props) => {
const { typebot } = useTypebot()
const { typebot, isLoading } = useTypebot()
const messageContainer = useRef<HTMLDivElement | null>(null)
const image = useRef<HTMLImageElement | null>(null)
const [isTyping, setIsTyping] = useState(true)
@ -25,9 +25,10 @@ export const ImageBubble = ({ block, onTransitionEnd }: Props) => {
)
useEffect(() => {
if (!isTyping || isLoading) return
showContentAfterMediaLoad()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
}, [isLoading])
const showContentAfterMediaLoad = () => {
if (!image.current) return

View File

@ -19,7 +19,7 @@ const defaultTypingEmulation = {
}
export const TextBubble = ({ block, onTransitionEnd }: Props) => {
const { typebot } = useTypebot()
const { typebot, isLoading } = useTypebot()
const messageContainer = useRef<HTMLDivElement | null>(null)
const [isTyping, setIsTyping] = useState(true)
@ -28,6 +28,7 @@ export const TextBubble = ({ block, onTransitionEnd }: Props) => {
)
useEffect(() => {
if (!isTyping || isLoading) return
const typingTimeout = computeTypingTimeout(
block.content.plainText,
typebot.settings?.typingEmulation ?? defaultTypingEmulation
@ -36,7 +37,7 @@ export const TextBubble = ({ block, onTransitionEnd }: Props) => {
onTypingEnd()
}, typingTimeout)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
}, [isLoading])
const onTypingEnd = () => {
setIsTyping(false)

View File

@ -19,14 +19,15 @@ export const showAnimationDuration = 400
export const mediaLoadingFallbackTimeout = 5000
export const VideoBubble = ({ block, onTransitionEnd }: Props) => {
const { typebot } = useTypebot()
const { typebot, isLoading } = useTypebot()
const messageContainer = useRef<HTMLDivElement | null>(null)
const [isTyping, setIsTyping] = useState(true)
useEffect(() => {
if (!isTyping || isLoading) return
showContentAfterMediaLoad()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
}, [isLoading])
const showContentAfterMediaLoad = () => {
setTimeout(() => {

View File

@ -42,7 +42,7 @@ export const StripePaymentForm = ({ options, onSuccess }: Props) => {
description: error.name + ' ' + error.message,
details: error.message,
})
if (!data) return
if (!data || !frameDocument || !frameWindow?.Stripe) return
await initStripe(frameDocument)
setStripe(frameWindow.Stripe(data.publicKey))
setClientSecret(data.clientSecret)

View File

@ -5,7 +5,7 @@ import { useFrame } from 'react-frame-component'
import { setCssVariablesValue } from '../services/theme'
import { useAnswers } from '../contexts/AnswersContext'
import { Group, Edge, PublicTypebot, Theme, VariableWithValue } from 'models'
import { byId, isNotDefined } from 'utils'
import { byId, isDefined, isNotDefined } from 'utils'
import { animateScroll as scroll } from 'react-scroll'
import { LinkedTypebot, useTypebot } from 'contexts/TypebotContext'
import { ChatContext } from 'contexts/ChatContext'
@ -83,8 +83,13 @@ export const ConversationContainer = ({
}
useEffect(() => {
const prefilledVariables = injectPredefinedVariables(predefinedVariables)
updateVariables(prefilledVariables)
if (
isDefined(predefinedVariables) &&
Object.keys(predefinedVariables).length > 0
) {
const prefilledVariables = injectPredefinedVariables(predefinedVariables)
updateVariables(prefilledVariables)
}
displayNextGroup({
edgeId: startGroupId
? undefined
@ -92,13 +97,13 @@ export const ConversationContainer = ({
groupId: startGroupId,
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
}, [predefinedVariables])
const injectPredefinedVariables = (predefinedVariables?: {
const injectPredefinedVariables = (predefinedVariables: {
[key: string]: string | undefined
}) => {
const prefilledVariables: VariableWithValue[] = []
Object.keys(predefinedVariables ?? {}).forEach((key) => {
Object.keys(predefinedVariables).forEach((key) => {
const matchingVariable = typebot.variables.find(
(v) => v.name.toLowerCase() === key.toLowerCase()
)
@ -112,6 +117,7 @@ export const ConversationContainer = ({
}
useEffect(() => {
if (!frameDocument) return
setCssVariablesValue(theme, frameDocument.body.style)
}, [theme, frameDocument])

View File

@ -6,6 +6,7 @@ export const LiteBadge = () => {
const liteBadge = useRef<HTMLAnchorElement | null>(null)
useEffect(() => {
if (!document) return
const container = document.querySelector(
'[data-testid="container"]'
) as HTMLDivElement

View File

@ -31,6 +31,7 @@ export type TypebotViewerProps = {
predefinedVariables?: { [key: string]: string | undefined }
resultId?: string
startGroupId?: string
isLoading?: boolean
onNewGroupVisible?: (edge: Edge) => void
onNewAnswer?: (answer: Answer) => Promise<void>
onNewLog?: (log: Omit<Log, 'id' | 'createdAt' | 'resultId'>) => void
@ -42,6 +43,7 @@ export const TypebotViewer = ({
typebot,
apiHost = process.env.NEXT_PUBLIC_VIEWER_URL?.split(',')[0],
isPreview = false,
isLoading = false,
style,
resultId,
startGroupId,
@ -98,6 +100,7 @@ export const TypebotViewer = ({
apiHost={apiHost}
isPreview={isPreview}
onNewLog={handleNewLog}
isLoading={isLoading}
>
<AnswersContext
resultId={resultId}

View File

@ -25,6 +25,7 @@ const typebotContext = createContext<{
apiHost: string
isPreview: boolean
linkedBotQueue: LinkedTypebotQueue
isLoading: boolean
setCurrentTypebotId: (id: string) => void
updateVariableValue: (variableId: string, value: string) => void
createEdge: (edge: Edge) => void
@ -44,11 +45,13 @@ export const TypebotContext = ({
typebot,
apiHost,
isPreview,
isLoading,
onNewLog,
}: {
children: ReactNode
typebot: PublicTypebot
apiHost: string
isLoading: boolean
isPreview: boolean
onNewLog: (log: Omit<Log, 'id' | 'createdAt' | 'resultId'>) => void
}) => {
@ -123,6 +126,7 @@ export const TypebotContext = ({
injectLinkedTypebot,
onNewLog,
linkedBotQueue,
isLoading,
pushEdgeIdInLinkedTypebotQueue,
popEdgeIdFromLinkedTypebotQueue,
currentTypebotId,