From aeaaa5c39814fccfdcdcd35e4c601ef2643826f1 Mon Sep 17 00:00:00 2001 From: Baptiste Arnaud Date: Sun, 12 Jun 2022 07:57:35 +0200 Subject: [PATCH] =?UTF-8?q?feat(bot):=20=E2=9A=A1=EF=B8=8F=20Improve=20fir?= =?UTF-8?q?st=20paint=20delay?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/viewer/layouts/TypebotPage.tsx | 5 +++-- packages/bot-engine/package.json | 2 +- .../ChatGroup/AvatarSideContainer.tsx | 1 + .../ChatBlock/bubbles/EmbedBubble.tsx | 5 +++-- .../ChatBlock/bubbles/ImageBubble.tsx | 5 +++-- .../ChatGroup/ChatBlock/bubbles/TextBubble.tsx | 5 +++-- .../ChatBlock/bubbles/VideoBubble.tsx | 5 +++-- .../inputs/PaymentForm/StripePaymentForm.tsx | 2 +- .../src/components/ConversationContainer.tsx | 18 ++++++++++++------ .../bot-engine/src/components/LiteBadge.tsx | 1 + .../src/components/TypebotViewer.tsx | 3 +++ .../bot-engine/src/contexts/TypebotContext.tsx | 4 ++++ yarn.lock | 8 ++++---- 13 files changed, 42 insertions(+), 22 deletions(-) diff --git a/apps/viewer/layouts/TypebotPage.tsx b/apps/viewer/layouts/TypebotPage.tsx index 2deb0eafbc3..f3446423970 100644 --- a/apps/viewer/layouts/TypebotPage.tsx +++ b/apps/viewer/layouts/TypebotPage.tsx @@ -3,7 +3,7 @@ import { Answer, PublicTypebot, VariableWithValue } from 'models' import { useRouter } from 'next/router' import React, { useEffect, useState } from 'react' import { upsertAnswer } from 'services/answer' -import { isDefined } from 'utils' +import { isDefined, isNotDefined } from 'utils' import { SEO } from '../components/Seo' import { createResult, updateResult } from '../services/result' import { ErrorPage } from './ErrorPage' @@ -34,6 +34,7 @@ export const TypebotPage = ({ const [resultId, setResultId] = useState() useEffect(() => { + setShowTypebot(true) const urlParams = new URLSearchParams(location.search) clearQueryParams() const predefinedVariables: { [key: string]: string } = {} @@ -68,7 +69,6 @@ export const TypebotPage = ({ setResultInSession(result.id) } } - setShowTypebot(true) } const handleNewVariables = async (variables: VariableWithValue[]) => { @@ -108,6 +108,7 @@ export const TypebotPage = ({ onNewAnswer={handleNewAnswer} onCompleted={handleCompleted} onVariablesUpdated={handleNewVariables} + isLoading={isNotDefined(resultId)} /> )} diff --git a/packages/bot-engine/package.json b/packages/bot-engine/package.json index 67fb6abe85d..44eb1e4b469 100644 --- a/packages/bot-engine/package.json +++ b/packages/bot-engine/package.json @@ -10,7 +10,7 @@ "db": "*", "models": "*", "qs": "^6.10.3", - "react-frame-component": "5.2.2-alpha.1", + "react-frame-component": "5.2.3", "react-phone-number-input": "^3.1.52", "react-scroll": "^1.8.7", "react-transition-group": "^4.4.2", diff --git a/packages/bot-engine/src/components/ChatGroup/AvatarSideContainer.tsx b/packages/bot-engine/src/components/ChatGroup/AvatarSideContainer.tsx index 9df626752e4..70b845aeffb 100644 --- a/packages/bot-engine/src/components/ChatGroup/AvatarSideContainer.tsx +++ b/packages/bot-engine/src/components/ChatGroup/AvatarSideContainer.tsx @@ -33,6 +33,7 @@ export const AvatarSideContainer = forwardRef( })) useEffect(() => { + if (!document) return setShow(true) const resizeObserver = new ResizeObserver(refreshTopOffset) resizeObserver.observe(document.body) diff --git a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/EmbedBubble.tsx b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/EmbedBubble.tsx index 9da99e59f13..4edce15d631 100644 --- a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/EmbedBubble.tsx +++ b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/EmbedBubble.tsx @@ -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(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(() => { diff --git a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/ImageBubble.tsx b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/ImageBubble.tsx index 0971df03fa7..0754573eff0 100644 --- a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/ImageBubble.tsx +++ b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/ImageBubble.tsx @@ -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(null) const image = useRef(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 diff --git a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/TextBubble.tsx b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/TextBubble.tsx index e3a74d46808..59b91bfa258 100644 --- a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/TextBubble.tsx +++ b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/TextBubble.tsx @@ -19,7 +19,7 @@ const defaultTypingEmulation = { } export const TextBubble = ({ block, onTransitionEnd }: Props) => { - const { typebot } = useTypebot() + const { typebot, isLoading } = useTypebot() const messageContainer = useRef(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) diff --git a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/VideoBubble.tsx b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/VideoBubble.tsx index a427a2a2952..d4d6b61b2c4 100644 --- a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/VideoBubble.tsx +++ b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/VideoBubble.tsx @@ -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(null) const [isTyping, setIsTyping] = useState(true) useEffect(() => { + if (!isTyping || isLoading) return showContentAfterMediaLoad() // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }, [isLoading]) const showContentAfterMediaLoad = () => { setTimeout(() => { diff --git a/packages/bot-engine/src/components/ChatGroup/ChatBlock/inputs/PaymentForm/StripePaymentForm.tsx b/packages/bot-engine/src/components/ChatGroup/ChatBlock/inputs/PaymentForm/StripePaymentForm.tsx index f0907a75153..61a130a5619 100644 --- a/packages/bot-engine/src/components/ChatGroup/ChatBlock/inputs/PaymentForm/StripePaymentForm.tsx +++ b/packages/bot-engine/src/components/ChatGroup/ChatBlock/inputs/PaymentForm/StripePaymentForm.tsx @@ -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) diff --git a/packages/bot-engine/src/components/ConversationContainer.tsx b/packages/bot-engine/src/components/ConversationContainer.tsx index 9017e278839..19a0e1cf093 100644 --- a/packages/bot-engine/src/components/ConversationContainer.tsx +++ b/packages/bot-engine/src/components/ConversationContainer.tsx @@ -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]) diff --git a/packages/bot-engine/src/components/LiteBadge.tsx b/packages/bot-engine/src/components/LiteBadge.tsx index d3ae31b322b..167ecaccb56 100644 --- a/packages/bot-engine/src/components/LiteBadge.tsx +++ b/packages/bot-engine/src/components/LiteBadge.tsx @@ -6,6 +6,7 @@ export const LiteBadge = () => { const liteBadge = useRef(null) useEffect(() => { + if (!document) return const container = document.querySelector( '[data-testid="container"]' ) as HTMLDivElement diff --git a/packages/bot-engine/src/components/TypebotViewer.tsx b/packages/bot-engine/src/components/TypebotViewer.tsx index 7751112aec1..6a65a4bc657 100644 --- a/packages/bot-engine/src/components/TypebotViewer.tsx +++ b/packages/bot-engine/src/components/TypebotViewer.tsx @@ -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 onNewLog?: (log: Omit) => 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} > 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) => void }) => { @@ -123,6 +126,7 @@ export const TypebotContext = ({ injectLinkedTypebot, onNewLog, linkedBotQueue, + isLoading, pushEdgeIdInLinkedTypebotQueue, popEdgeIdFromLinkedTypebotQueue, currentTypebotId, diff --git a/yarn.lock b/yarn.lock index b87c7a873ee..3e45f8b1618 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12440,10 +12440,10 @@ react-focus-lock@2.5.2: use-callback-ref "^1.2.5" use-sidecar "^1.0.5" -react-frame-component@5.2.2-alpha.1: - version "5.2.2-alpha.1" - resolved "https://registry.yarnpkg.com/react-frame-component/-/react-frame-component-5.2.2-alpha.1.tgz#fcfec38e0670ea78b3e9b6d00ef7a18613b3b089" - integrity sha512-pCXLlBDO8+yh4qbax8M2U+Cl+5tFxyZ0p6HzD0MP+P47u3ZK4fPiOzWQIOi7Eand4tq6nawKZC+vsSHC2KT1Zg== +react-frame-component@5.2.3: + version "5.2.3" + resolved "https://registry.yarnpkg.com/react-frame-component/-/react-frame-component-5.2.3.tgz#2d5d1e29b23d5b915c839b44980d03bb9cafc453" + integrity sha512-r+h0o3r/uqOLNT724z4CRVkxQouKJvoi3OPfjqWACD30Y87rtEmeJrNZf1WYPGknn1Y8200HAjx7hY/dPUGgmA== react-helmet-async@*, react-helmet-async@^1.2.3, react-helmet-async@^1.3.0: version "1.3.0"