2
0

feat(bubbles): Add video bubble

This commit is contained in:
Baptiste Arnaud
2022-01-20 17:45:25 +01:00
parent 2d178978ef
commit df2474ef43
14 changed files with 432 additions and 40 deletions

View File

@ -4,16 +4,17 @@ import {
PopoverArrow,
PopoverBody,
} from '@chakra-ui/react'
import { ImagePopoverContent } from 'components/shared/ImageUploadContent'
import { ImageUploadContent } from 'components/shared/ImageUploadContent'
import { useTypebot } from 'contexts/TypebotContext'
import {
BubbleStep,
BubbleStepContent,
BubbleStepType,
ImageBubbleContent,
ImageBubbleStep,
TextBubbleStep,
} from 'models'
import { useRef } from 'react'
import { VideoUploadContent } from './VideoUploadContent'
type Props = {
step: Exclude<BubbleStep, TextBubbleStep>
@ -25,7 +26,7 @@ export const ContentPopover = ({ step }: Props) => {
return (
<Portal>
<PopoverContent onMouseDown={handleMouseDown} w="500px">
<PopoverContent onMouseDown={handleMouseDown}>
<PopoverArrow />
<PopoverBody ref={ref} shadow="lg">
<StepContent step={step} />
@ -37,16 +38,24 @@ export const ContentPopover = ({ step }: Props) => {
export const StepContent = ({ step }: Props) => {
const { updateStep } = useTypebot()
const handleContentChange = (content: ImageBubbleContent) =>
const handleContentChange = (content: BubbleStepContent) =>
updateStep(step.id, { content } as Partial<ImageBubbleStep>)
const handleNewImageSubmit = (url: string) => handleContentChange({ url })
switch (step.type) {
case BubbleStepType.IMAGE: {
return (
<ImagePopoverContent
url={step.content?.url}
onSubmit={handleNewImageSubmit}
<ImageUploadContent
content={step.content}
onSubmit={handleContentChange}
/>
)
}
case BubbleStepType.VIDEO: {
return (
<VideoUploadContent
content={step.content}
onSubmit={handleContentChange}
/>
)
}

View File

@ -0,0 +1,38 @@
import { Stack, Text } from '@chakra-ui/react'
import { InputWithVariableButton } from 'components/shared/InputWithVariableButton'
import { VideoBubbleContent, VideoBubbleContentType } from 'models'
import urlParser from 'js-video-url-parser/lib/base'
import 'js-video-url-parser/lib/provider/vimeo'
import 'js-video-url-parser/lib/provider/youtube'
import { isDefined } from 'utils'
type Props = {
content?: VideoBubbleContent
onSubmit: (content: VideoBubbleContent) => void
}
export const VideoUploadContent = ({ content, onSubmit }: Props) => {
const handleUrlChange = (url: string) => {
const info = urlParser.parse(url)
return isDefined(info) && info.provider && info.id
? onSubmit({
type: info.provider as VideoBubbleContentType,
url,
id: info.id,
})
: onSubmit({ type: VideoBubbleContentType.URL, url })
}
return (
<Stack p="2">
<InputWithVariableButton
placeholder="Paste the video link..."
initialValue={content?.url ?? ''}
onChange={handleUrlChange}
delay={100}
/>
<Text fontSize="sm" color="gray.400" textAlign="center">
Works with Youtube, Vimeo and others
</Text>
</Stack>
)
}

View File

@ -9,6 +9,8 @@ import {
SetVariableStep,
ConditionStep,
IntegrationStepType,
VideoBubbleStep,
VideoBubbleContentType,
} from 'models'
import { ChoiceItemsList } from './ChoiceInputStepNode/ChoiceItemsList'
import { SourceEndpoint } from './SourceEndpoint'
@ -48,6 +50,9 @@ export const StepNodeContent = ({ step }: Props) => {
</Box>
)
}
case BubbleStepType.VIDEO: {
return <VideoStepNodeContent step={step} />
}
case InputStepType.TEXT: {
return (
<Text color={'gray.500'}>
@ -182,3 +187,52 @@ const ConditionNodeContent = ({ step }: { step: ConditionStep }) => {
</Flex>
)
}
const VideoStepNodeContent = ({ step }: { step: VideoBubbleStep }) => {
if (!step.content?.url || !step.content.type)
return <Text color="gray.500">Click to edit...</Text>
switch (step.content.type) {
case VideoBubbleContentType.URL:
return (
<Box w="full" h="120px" pos="relative">
<video
key={step.content.url}
controls
style={{
width: '100%',
height: '100%',
position: 'absolute',
left: '0',
top: '0',
borderRadius: '10px',
}}
>
<source src={step.content.url} />
</video>
</Box>
)
case VideoBubbleContentType.VIMEO:
case VideoBubbleContentType.YOUTUBE: {
const baseUrl =
step.content.type === VideoBubbleContentType.VIMEO
? 'https://player.vimeo.com/video'
: 'https://www.youtube.com/embed'
return (
<Box w="full" h="120px" pos="relative">
<iframe
src={`${baseUrl}/${step.content.id}`}
allowFullScreen
style={{
width: '100%',
height: '100%',
position: 'absolute',
left: '0',
top: '0',
borderRadius: '10px',
}}
/>
</Box>
)
}
}
}