2
0

Add audio bubble block

Closes #167
This commit is contained in:
Baptiste Arnaud
2022-11-17 10:33:17 +01:00
parent 473d315e0f
commit 7db0e01aca
29 changed files with 306 additions and 26 deletions

View File

@ -1,3 +1,4 @@
import { AudioBubble } from '@/features/blocks/bubbles/audio'
import { EmbedBubble } from '@/features/blocks/bubbles/embed'
import { ImageBubble } from '@/features/blocks/bubbles/image'
import { TextBubble } from '@/features/blocks/bubbles/textBubble'
@ -20,5 +21,12 @@ export const HostBubble = ({ block, onTransitionEnd }: Props) => {
return <VideoBubble block={block} onTransitionEnd={onTransitionEnd} />
case BubbleBlockType.EMBED:
return <EmbedBubble block={block} onTransitionEnd={onTransitionEnd} />
case BubbleBlockType.AUDIO:
return (
<AudioBubble
url={block.content.url}
onTransitionEnd={onTransitionEnd}
/>
)
}
}

View File

@ -0,0 +1,68 @@
import React, { useEffect, useMemo, useRef, useState } from 'react'
import { useTypebot } from '@/providers/TypebotProvider'
import { AudioBubbleContent } from 'models'
import { TypingBubble } from '@/components/TypingBubble'
import { parseVariables } from '@/features/variables'
type Props = {
url: AudioBubbleContent['url']
onTransitionEnd: () => void
}
const showAnimationDuration = 400
const typingDuration = 500
export const AudioBubble = ({ url, onTransitionEnd }: Props) => {
const { typebot, isLoading } = useTypebot()
const audio = useRef<HTMLAudioElement | null>(null)
const [isTyping, setIsTyping] = useState(true)
const parsedUrl = useMemo(
() => parseVariables(typebot.variables)(url),
[url, typebot.variables]
)
useEffect(() => {
if (!isTyping || isLoading) return
const typingTimeout = setTimeout(() => {
setIsTyping(false)
setTimeout(() => {
onTransitionEnd()
}, showAnimationDuration)
}, typingDuration)
return () => {
clearTimeout(typingTimeout)
}
}, [isLoading, isTyping, onTransitionEnd])
return (
<div className="flex flex-col">
<div className="flex mb-2 w-full lg:w-11/12 items-center">
<div className={'flex relative z-10 items-start typebot-host-bubble'}>
<div
className="flex items-center absolute px-4 py-2 rounded-lg bubble-typing z-10 "
style={{
width: isTyping ? '4rem' : '100%',
height: isTyping ? '2rem' : '100%',
}}
>
{isTyping ? <TypingBubble /> : null}
</div>
<audio
ref={audio}
src={parsedUrl}
className={
'z-10 content-opacity m-2 ' +
(isTyping ? 'opacity-0' : 'opacity-100')
}
style={{ height: isTyping ? '2rem' : 'revert' }}
autoPlay
controls
/>
</div>
</div>
</div>
)
}

View File

@ -0,0 +1 @@
export * from './AudioBubble'

View File

@ -0,0 +1 @@
export * from './components'

View File

@ -0,0 +1,18 @@
import { z } from 'zod'
import { blockBaseSchema, BubbleBlockType } from '../shared'
export const audioBubbleContentSchema = z.object({
url: z.string().optional(),
})
export const audioBubbleBlockSchema = blockBaseSchema.and(
z.object({
type: z.enum([BubbleBlockType.AUDIO]),
content: audioBubbleContentSchema,
})
)
export const defaultAudioBubbleContent = {}
export type AudioBubbleBlock = z.infer<typeof audioBubbleBlockSchema>
export type AudioBubbleContent = z.infer<typeof audioBubbleContentSchema>

View File

@ -1,4 +1,5 @@
import { z } from 'zod'
import { audioBubbleBlockSchema, audioBubbleContentSchema } from './audio'
import { embedBubbleContentSchema, embedBubbleBlockSchema } from './embed'
import { imageBubbleContentSchema, imageBubbleBlockSchema } from './image'
import { textBubbleContentSchema, textBubbleBlockSchema } from './text'
@ -8,11 +9,13 @@ export const bubbleBlockContentSchema = textBubbleContentSchema
.or(imageBubbleContentSchema)
.or(videoBubbleContentSchema)
.or(embedBubbleContentSchema)
.or(audioBubbleContentSchema)
export const bubbleBlockSchema = textBubbleBlockSchema
.or(imageBubbleBlockSchema)
.or(videoBubbleBlockSchema)
.or(embedBubbleBlockSchema)
.or(audioBubbleBlockSchema)
export type BubbleBlock = z.infer<typeof bubbleBlockSchema>
export type BubbleBlockContent = z.infer<typeof bubbleBlockContentSchema>

View File

@ -3,3 +3,4 @@ export * from './text'
export * from './image'
export * from './video'
export * from './embed'
export * from './audio'

View File

@ -28,6 +28,7 @@ export enum BubbleBlockType {
IMAGE = 'image',
VIDEO = 'video',
EMBED = 'embed',
AUDIO = 'audio',
}
export enum InputBlockType {