✨(front) add loading state on effects component
useSyncAfterDelay allows to enable loading indicators only if the loading takes more than a specific time. It prevent blinking effect when the loading time is nearly instant.
This commit is contained in:
@@ -12,6 +12,8 @@ import { styled } from '@/styled-system/jsx'
|
||||
import { BackgroundOptions } from '@livekit/track-processors'
|
||||
import { BlurOn } from '@/components/icons/BlurOn'
|
||||
import { BlurOnStrong } from '@/components/icons/BlurOnStrong'
|
||||
import { Loader } from '@/primitives/Loader'
|
||||
import { useSyncAfterDelay } from '@/hooks/useSyncAfterDelay'
|
||||
|
||||
enum BlurRadius {
|
||||
NONE = 0,
|
||||
@@ -44,6 +46,7 @@ export const EffectsConfiguration = ({
|
||||
const videoRef = useRef<HTMLVideoElement>(null)
|
||||
const { t } = useTranslation('rooms', { keyPrefix: 'effects' })
|
||||
const [processorPending, setProcessorPending] = useState(false)
|
||||
const processorPendingReveal = useSyncAfterDelay(processorPending)
|
||||
|
||||
useEffect(() => {
|
||||
const videoElement = videoRef.current
|
||||
@@ -134,6 +137,7 @@ export const EffectsConfiguration = ({
|
||||
className={css({
|
||||
width: '100%',
|
||||
aspectRatio: 16 / 9,
|
||||
position: 'relative',
|
||||
})}
|
||||
>
|
||||
{videoTrack && !videoTrack.isMuted ? (
|
||||
@@ -170,6 +174,17 @@ export const EffectsConfiguration = ({
|
||||
</P>
|
||||
</div>
|
||||
)}
|
||||
{processorPendingReveal && (
|
||||
<div
|
||||
className={css({
|
||||
position: 'absolute',
|
||||
right: '8px',
|
||||
bottom: '8px',
|
||||
})}
|
||||
>
|
||||
<Loader />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div
|
||||
className={css(
|
||||
@@ -212,7 +227,7 @@ export const EffectsConfiguration = ({
|
||||
tooltip={tooltipLabel(ProcessorType.BLUR, {
|
||||
blurRadius: BlurRadius.LIGHT,
|
||||
})}
|
||||
isDisabled={processorPending}
|
||||
isDisabled={processorPendingReveal}
|
||||
onChange={async () =>
|
||||
await toggleEffect(ProcessorType.BLUR, {
|
||||
blurRadius: BlurRadius.LIGHT,
|
||||
@@ -232,7 +247,7 @@ export const EffectsConfiguration = ({
|
||||
tooltip={tooltipLabel(ProcessorType.BLUR, {
|
||||
blurRadius: BlurRadius.NORMAL,
|
||||
})}
|
||||
isDisabled={processorPending}
|
||||
isDisabled={processorPendingReveal}
|
||||
onChange={async () =>
|
||||
await toggleEffect(ProcessorType.BLUR, {
|
||||
blurRadius: BlurRadius.NORMAL,
|
||||
@@ -280,7 +295,7 @@ export const EffectsConfiguration = ({
|
||||
tooltip={tooltipLabel(ProcessorType.VIRTUAL, {
|
||||
imagePath,
|
||||
})}
|
||||
isDisabled={processorPending}
|
||||
isDisabled={processorPendingReveal}
|
||||
onChange={async () =>
|
||||
await toggleEffect(ProcessorType.VIRTUAL, {
|
||||
imagePath,
|
||||
|
||||
30
src/frontend/src/hooks/useSyncAfterDelay.ts
Normal file
30
src/frontend/src/hooks/useSyncAfterDelay.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { useEffect, useRef, useState } from 'react'
|
||||
|
||||
/**
|
||||
* If value stays truthy for more than waitFor ms, syncValue takes the value of value.
|
||||
* @param value
|
||||
* @param waitFor
|
||||
* @returns
|
||||
*/
|
||||
export function useSyncAfterDelay<T>(value: T, waitFor: number = 300) {
|
||||
const valueRef = useRef(value)
|
||||
const timeoutRef = useRef<NodeJS.Timeout>()
|
||||
const [syncValue, setSyncValue] = useState<T>()
|
||||
|
||||
useEffect(() => {
|
||||
valueRef.current = value
|
||||
if (value) {
|
||||
if (!timeoutRef.current) {
|
||||
timeoutRef.current = setTimeout(() => {
|
||||
setSyncValue(valueRef.current)
|
||||
timeoutRef.current = undefined
|
||||
}, waitFor)
|
||||
}
|
||||
} else {
|
||||
setSyncValue(value)
|
||||
}
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [value])
|
||||
|
||||
return syncValue
|
||||
}
|
||||
@@ -101,6 +101,11 @@ export const buttonRecipe = cva({
|
||||
'&[data-selected]': {
|
||||
boxShadow: 'token(colors.primary.400) 0px 0px 0px 3px inset',
|
||||
},
|
||||
'&[data-disabled]': {
|
||||
backgroundColor: 'greyscale.100',
|
||||
color: 'greyscale.400',
|
||||
opacity: '0.7',
|
||||
},
|
||||
},
|
||||
tertiary: {
|
||||
backgroundColor: 'primary.100',
|
||||
|
||||
Reference in New Issue
Block a user