diff --git a/apps/builder/src/features/graph/components/Nodes/BlockNode/BlockNode.tsx b/apps/builder/src/features/graph/components/Nodes/BlockNode/BlockNode.tsx index 4d237c19c..424dbd20e 100644 --- a/apps/builder/src/features/graph/components/Nodes/BlockNode/BlockNode.tsx +++ b/apps/builder/src/features/graph/components/Nodes/BlockNode/BlockNode.tsx @@ -63,6 +63,7 @@ export const BlockNode = ({ setOpenedBlockId, setFocusedGroupId, previewingEdge, + isReadOnly, } = useGraph() const { mouseOverBlock, setMouseOverBlock } = useBlockDnd() const { typebot, updateBlock } = useTypebot() @@ -111,6 +112,7 @@ export const BlockNode = ({ } const handleMouseEnter = () => { + if (isReadOnly) return if (mouseOverBlock?.id !== block.id) setMouseOverBlock({ id: block.id, ref: blockRef }) if (connectingIds) diff --git a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/HostBubble.tsx b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/HostBubble.tsx index 5b06ad033..6cb82296e 100644 --- a/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/HostBubble.tsx +++ b/packages/bot-engine/src/components/ChatGroup/ChatBlock/bubbles/HostBubble.tsx @@ -4,7 +4,6 @@ import { ImageBubble } from '@/features/blocks/bubbles/image' import { TextBubble } from '@/features/blocks/bubbles/textBubble' import { VideoBubble } from '@/features/blocks/bubbles/video' import { BubbleBlock, BubbleBlockType } from 'models' -import React from 'react' type Props = { block: BubbleBlock diff --git a/packages/bot-engine/src/components/ChatGroup/ChatGroup.tsx b/packages/bot-engine/src/components/ChatGroup/ChatGroup.tsx index 92069c9e7..a0b18e987 100644 --- a/packages/bot-engine/src/components/ChatGroup/ChatGroup.tsx +++ b/packages/bot-engine/src/components/ChatGroup/ChatGroup.tsx @@ -307,7 +307,7 @@ const ChatChunks = ({ unmountOnExit in={isDefined(input)} > - {input && ( + {input ? ( + ) : ( +
)} )} diff --git a/packages/bot-engine/src/features/blocks/bubbles/embed/components/EmbedBubble.tsx b/packages/bot-engine/src/features/blocks/bubbles/embed/components/EmbedBubble.tsx index 7a3e1bd72..85282f917 100644 --- a/packages/bot-engine/src/features/blocks/bubbles/embed/components/EmbedBubble.tsx +++ b/packages/bot-engine/src/features/blocks/bubbles/embed/components/EmbedBubble.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { EmbedBubbleBlock } from 'models' import { TypingBubble } from '../../../../../components/TypingBubble' import { parseVariables } from '@/features/variables' @@ -21,25 +21,24 @@ export const EmbedBubble = ({ block, onTransitionEnd }: Props) => { [block.content?.url, typebot.variables] ) - useEffect(() => { - if (!isTyping || isLoading) return - showContentAfterMediaLoad() - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isLoading]) - - const showContentAfterMediaLoad = () => { - setTimeout(() => { - setIsTyping(false) - onTypingEnd() - }, 1000) - } - - const onTypingEnd = () => { + const onTypingEnd = useCallback(() => { setIsTyping(false) setTimeout(() => { onTransitionEnd() }, showAnimationDuration) - } + }, [onTransitionEnd]) + + useEffect(() => { + if (!isTyping || isLoading) return + const timeout = setTimeout(() => { + setIsTyping(false) + onTypingEnd() + }, 1000) + + return () => { + clearTimeout(timeout) + } + }, [isLoading, isTyping, onTypingEnd]) return (
diff --git a/packages/bot-engine/src/features/blocks/bubbles/image/components/ImageBubble.tsx b/packages/bot-engine/src/features/blocks/bubbles/image/components/ImageBubble.tsx index 12b59fe33..8f63ea3ac 100644 --- a/packages/bot-engine/src/features/blocks/bubbles/image/components/ImageBubble.tsx +++ b/packages/bot-engine/src/features/blocks/bubbles/image/components/ImageBubble.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTypebot } from '@/providers/TypebotProvider' import { ImageBubbleBlock } from 'models' import { TypingBubble } from '@/components/TypingBubble' @@ -24,31 +24,37 @@ export const ImageBubble = ({ block, onTransitionEnd }: Props) => { [block.content?.url, typebot.variables] ) - useEffect(() => { - if (!isTyping || isLoading) return - showContentAfterMediaLoad() - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isLoading]) - - const showContentAfterMediaLoad = () => { - if (!image.current) return - const timeout = setTimeout(() => { - setIsTyping(false) - onTypingEnd() - }, mediaLoadingFallbackTimeout) - image.current.onload = () => { - clearTimeout(timeout) - setIsTyping(false) - onTypingEnd() - } - } - - const onTypingEnd = () => { + const onTypingEnd = useCallback(() => { setIsTyping(false) setTimeout(() => { onTransitionEnd() }, showAnimationDuration) - } + }, [onTransitionEnd]) + + useEffect(() => { + if (!isTyping || isLoading) return + + const timeout = setTimeout(() => { + setIsTyping(false) + onTypingEnd() + }, mediaLoadingFallbackTimeout) + + return () => { + clearTimeout(timeout) + } + }, [isLoading, isTyping, onTypingEnd]) + + useEffect(() => { + const currentImage = image.current + if (!currentImage || isLoading || !isTyping) return + currentImage.onload = () => { + setIsTyping(false) + onTypingEnd() + } + return () => { + currentImage.onload = null + } + }, [isLoading, isTyping, onTypingEnd]) return (
diff --git a/packages/bot-engine/src/features/blocks/bubbles/textBubble/components/TextBubble.tsx b/packages/bot-engine/src/features/blocks/bubbles/textBubble/components/TextBubble.tsx index 2d8d01973..77e0403c6 100644 --- a/packages/bot-engine/src/features/blocks/bubbles/textBubble/components/TextBubble.tsx +++ b/packages/bot-engine/src/features/blocks/bubbles/textBubble/components/TextBubble.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, useState } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { useTypebot } from '@/providers/TypebotProvider' import { BubbleBlockType, TextBubbleBlock } from 'models' import { computeTypingDuration } from '../utils/computeTypingDuration' @@ -27,24 +27,34 @@ export const TextBubble = ({ block, onTransitionEnd }: Props) => { parseVariables(typebot.variables)(block.content.html) ) - useEffect(() => { - if (!isTyping || isLoading) return - const typingTimeout = computeTypingDuration( - block.content.plainText, - typebot.settings?.typingEmulation ?? defaultTypingEmulation - ) - setTimeout(() => { - onTypingEnd() - }, typingTimeout) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [isLoading]) - - const onTypingEnd = () => { + const onTypingEnd = useCallback(() => { setIsTyping(false) setTimeout(() => { onTransitionEnd() }, showAnimationDuration) - } + }, [onTransitionEnd]) + + useEffect(() => { + if (!isTyping || isLoading) return + + const typingTimeout = computeTypingDuration( + block.content.plainText, + typebot.settings?.typingEmulation ?? defaultTypingEmulation + ) + const timeout = setTimeout(() => { + onTypingEnd() + }, typingTimeout) + + return () => { + clearTimeout(timeout) + } + }, [ + block.content.plainText, + isLoading, + isTyping, + onTypingEnd, + typebot.settings?.typingEmulation, + ]) return (
diff --git a/packages/bot-engine/src/features/blocks/bubbles/video/components/VideoBubble.tsx b/packages/bot-engine/src/features/blocks/bubbles/video/components/VideoBubble.tsx index 46bbf1af7..a401cf224 100644 --- a/packages/bot-engine/src/features/blocks/bubbles/video/components/VideoBubble.tsx +++ b/packages/bot-engine/src/features/blocks/bubbles/video/components/VideoBubble.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useRef, useState } from 'react' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTypebot } from '@/providers/TypebotProvider' import { Variable, @@ -23,25 +23,24 @@ export const VideoBubble = ({ block, onTransitionEnd }: Props) => { 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(() => { - setIsTyping(false) - onTypingEnd() - }, 1000) - } - - const onTypingEnd = () => { + const onTypingEnd = useCallback(() => { setIsTyping(false) setTimeout(() => { onTransitionEnd() }, showAnimationDuration) - } + }, [onTransitionEnd]) + + useEffect(() => { + if (!isTyping || isLoading) return + const timeout = setTimeout(() => { + setIsTyping(false) + onTypingEnd() + }, 1000) + + return () => { + clearTimeout(timeout) + } + }, [isLoading, isTyping, onTypingEnd]) return (