2
0

🐛 (js) Improve bubbles callback reliability

This commit is contained in:
Baptiste Arnaud
2023-03-01 08:42:47 +01:00
parent 5024c1b22b
commit f6e128be37
8 changed files with 68 additions and 33 deletions

View File

@@ -4,7 +4,23 @@ const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN
Sentry.init({ Sentry.init({
dsn: SENTRY_DSN, dsn: SENTRY_DSN,
ignoreErrors: ['ResizeObserver loop limit exceeded'], ignoreErrors: [
debug: true, 'ResizeObserver loop limit exceeded',
'ResizeObserver loop completed with undelivered notifications.',
'ResizeObserver is not defined',
"Can't find variable: ResizeObserver",
],
release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-builder', release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-builder',
beforeBreadcrumb(breadcrumb, hint) {
try {
if (breadcrumb.category.startsWith('ui')) {
breadcrumb.message = `${hint.event.target.tagName.toLowerCase()}: ${
hint.event.target.innerText
}`
}
} catch (e) {
/* empty */
}
return breadcrumb
},
}) })

View File

@@ -1,7 +1,3 @@
// This file configures the initialization of Sentry on the browser.
// The config you add here will be used whenever a page is visited.
// https://docs.sentry.io/platforms/javascript/guides/nextjs/
import * as Sentry from '@sentry/nextjs' import * as Sentry from '@sentry/nextjs'
const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN
@@ -15,4 +11,16 @@ Sentry.init({
"Can't find variable: ResizeObserver", "Can't find variable: ResizeObserver",
], ],
release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-viewer', release: process.env.NEXT_PUBLIC_VERCEL_GIT_COMMIT_SHA + '-viewer',
beforeBreadcrumb(breadcrumb, hint) {
try {
if (breadcrumb.category.startsWith('ui')) {
breadcrumb.message = `${hint.event.target.tagName.toLowerCase()}: ${
hint.event.target.innerText
}`
}
} catch (e) {
/* empty */
}
return breadcrumb
},
}) })

View File

@@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/js", "name": "@typebot.io/js",
"version": "0.0.16", "version": "0.0.17",
"description": "Javascript library to display typebots on your website", "description": "Javascript library to display typebots on your website",
"type": "module", "type": "module",
"main": "dist/index.js", "main": "dist/index.js",

View File

@@ -1,24 +1,30 @@
import { TypingBubble } from '@/components' import { TypingBubble } from '@/components'
import type { EmbedBubbleContent } from 'models' import type { EmbedBubbleContent } from 'models'
import { createSignal, onMount } from 'solid-js' import { createSignal, onCleanup, onMount } from 'solid-js'
type Props = { type Props = {
content: EmbedBubbleContent content: EmbedBubbleContent
onTransitionEnd: () => void onTransitionEnd: () => void
} }
let typingTimeout: NodeJS.Timeout
export const showAnimationDuration = 400 export const showAnimationDuration = 400
export const EmbedBubble = (props: Props) => { export const EmbedBubble = (props: Props) => {
const [isTyping, setIsTyping] = createSignal(true) const [isTyping, setIsTyping] = createSignal(true)
onMount(() => { onMount(() => {
setTimeout(() => { typingTimeout = setTimeout(() => {
setIsTyping(false) setIsTyping(false)
setTimeout(() => { setTimeout(() => {
props.onTransitionEnd() props.onTransitionEnd()
}, showAnimationDuration) }, showAnimationDuration)
}, 1000) }, 2000)
})
onCleanup(() => {
if (typingTimeout) clearTimeout(typingTimeout)
}) })
return ( return (

View File

@@ -1,6 +1,6 @@
import { TypingBubble } from '@/components' import { TypingBubble } from '@/components'
import type { ImageBubbleContent } from 'models' import type { ImageBubbleContent } from 'models'
import { createSignal, onMount } from 'solid-js' import { createSignal, onCleanup, onMount } from 'solid-js'
type Props = { type Props = {
url: ImageBubbleContent['url'] url: ImageBubbleContent['url']
@@ -11,11 +11,14 @@ export const showAnimationDuration = 400
export const mediaLoadingFallbackTimeout = 5000 export const mediaLoadingFallbackTimeout = 5000
let typingTimeout: NodeJS.Timeout
export const ImageBubble = (props: Props) => { export const ImageBubble = (props: Props) => {
let image: HTMLImageElement | undefined let image: HTMLImageElement | undefined
const [isTyping, setIsTyping] = createSignal(true) const [isTyping, setIsTyping] = createSignal(true)
const onTypingEnd = () => { const onTypingEnd = () => {
if (!isTyping()) return
setIsTyping(false) setIsTyping(false)
setTimeout(() => { setTimeout(() => {
props.onTransitionEnd() props.onTransitionEnd()
@@ -24,17 +27,17 @@ export const ImageBubble = (props: Props) => {
onMount(() => { onMount(() => {
if (!image) return if (!image) return
const timeout = setTimeout(() => { typingTimeout = setTimeout(onTypingEnd, mediaLoadingFallbackTimeout)
setIsTyping(false)
onTypingEnd()
}, mediaLoadingFallbackTimeout)
image.onload = () => { image.onload = () => {
clearTimeout(timeout) clearTimeout(typingTimeout)
setIsTyping(false)
onTypingEnd() onTypingEnd()
} }
}) })
onCleanup(() => {
if (typingTimeout) clearTimeout(typingTimeout)
})
return ( return (
<div class="flex flex-col animate-fade-in"> <div class="flex flex-col animate-fade-in">
<div class="flex mb-2 w-full lg:w-11/12 items-center"> <div class="flex mb-2 w-full lg:w-11/12 items-center">

View File

@@ -1,6 +1,6 @@
import { TypingBubble } from '@/components' import { TypingBubble } from '@/components'
import type { TextBubbleContent, TypingEmulation } from 'models' import type { TextBubbleContent, TypingEmulation } from 'models'
import { createSignal, onMount } from 'solid-js' import { createSignal, onCleanup, onMount } from 'solid-js'
import { computeTypingDuration } from '../utils/computeTypingDuration' import { computeTypingDuration } from '../utils/computeTypingDuration'
type Props = { type Props = {
@@ -17,10 +17,13 @@ const defaultTypingEmulation = {
maxDelay: 1.5, maxDelay: 1.5,
} }
let typingTimeout: NodeJS.Timeout
export const TextBubble = (props: Props) => { export const TextBubble = (props: Props) => {
const [isTyping, setIsTyping] = createSignal(true) const [isTyping, setIsTyping] = createSignal(true)
const onTypingEnd = () => { const onTypingEnd = () => {
if (!isTyping()) return
setIsTyping(false) setIsTyping(false)
setTimeout(() => { setTimeout(() => {
props.onTransitionEnd() props.onTransitionEnd()
@@ -36,9 +39,11 @@ export const TextBubble = (props: Props) => {
props.content.plainText, props.content.plainText,
props.typingEmulation ?? defaultTypingEmulation props.typingEmulation ?? defaultTypingEmulation
) )
setTimeout(() => { typingTimeout = setTimeout(onTypingEnd, typingDuration)
onTypingEnd() })
}, typingDuration)
onCleanup(() => {
if (typingTimeout) clearTimeout(typingTimeout)
}) })
return ( return (

View File

@@ -1,7 +1,7 @@
import { TypingBubble } from '@/components' import { TypingBubble } from '@/components'
import type { VideoBubbleContent } from 'models' import type { VideoBubbleContent } from 'models'
import { VideoBubbleContentType } from 'models/features/blocks/bubbles/video/enums' import { VideoBubbleContentType } from 'models/features/blocks/bubbles/video/enums'
import { createSignal, Match, onMount, Switch } from 'solid-js' import { createSignal, Match, onCleanup, onMount, Switch } from 'solid-js'
type Props = { type Props = {
content: VideoBubbleContent content: VideoBubbleContent
@@ -10,28 +10,25 @@ type Props = {
export const showAnimationDuration = 400 export const showAnimationDuration = 400
export const mediaLoadingFallbackTimeout = 5000 let typingTimeout: NodeJS.Timeout
export const VideoBubble = (props: Props) => { export const VideoBubble = (props: Props) => {
const [isTyping, setIsTyping] = createSignal(true) const [isTyping, setIsTyping] = createSignal(true)
const onTypingEnd = () => { const onTypingEnd = () => {
if (!isTyping()) return
setIsTyping(false) setIsTyping(false)
setTimeout(() => { setTimeout(() => {
props.onTransitionEnd() props.onTransitionEnd()
}, showAnimationDuration) }, showAnimationDuration)
} }
const showContentAfterMediaLoad = () => {
setTimeout(() => {
setIsTyping(false)
onTypingEnd()
}, 1000)
}
onMount(() => { onMount(() => {
if (!isTyping) return typingTimeout = setTimeout(onTypingEnd, 2000)
showContentAfterMediaLoad() })
onCleanup(() => {
if (typingTimeout) clearTimeout(typingTimeout)
}) })
return ( return (

View File

@@ -1,6 +1,6 @@
{ {
"name": "@typebot.io/react", "name": "@typebot.io/react",
"version": "0.0.16", "version": "0.0.17",
"description": "React library to display typebots on your website", "description": "React library to display typebots on your website",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",