diff --git a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx index 44e5cb1d..49b573e1 100644 --- a/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx +++ b/src/frontend/src/features/rooms/livekit/components/SidePanel.tsx @@ -8,9 +8,9 @@ import { useTranslation } from 'react-i18next' import { ParticipantsList } from './controls/Participants/ParticipantsList' import { useSidePanel } from '../hooks/useSidePanel' import { ReactNode } from 'react' -import { Effects } from './Effects' import { Chat } from '../prefabs/Chat' import { Transcript } from './Transcript' +import { Effects } from './effects/Effects' type StyledSidePanelProps = { title: string diff --git a/src/frontend/src/features/rooms/livekit/components/effects/Effects.tsx b/src/frontend/src/features/rooms/livekit/components/effects/Effects.tsx new file mode 100644 index 00000000..3c2aee55 --- /dev/null +++ b/src/frontend/src/features/rooms/livekit/components/effects/Effects.tsx @@ -0,0 +1,18 @@ +import { useLocalParticipant } from '@livekit/components-react' +import { LocalVideoTrack } from 'livekit-client' +import { css } from '@/styled-system/css' +import { EffectsConfiguration } from './EffectsConfiguration' + +export const Effects = () => { + const { cameraTrack } = useLocalParticipant() + const localCameraTrack = cameraTrack?.track as LocalVideoTrack + return ( +
+ +
+ ) +} diff --git a/src/frontend/src/features/rooms/livekit/components/Effects.tsx b/src/frontend/src/features/rooms/livekit/components/effects/EffectsConfiguration.tsx similarity index 52% rename from src/frontend/src/features/rooms/livekit/components/Effects.tsx rename to src/frontend/src/features/rooms/livekit/components/effects/EffectsConfiguration.tsx index bbdc9a0b..235a31b8 100644 --- a/src/frontend/src/features/rooms/livekit/components/Effects.tsx +++ b/src/frontend/src/features/rooms/livekit/components/effects/EffectsConfiguration.tsx @@ -1,13 +1,21 @@ +import { LocalVideoTrack, Track, TrackProcessor } from 'livekit-client' import { useEffect, useRef, useState } from 'react' -import { useLocalParticipant } from '@livekit/components-react' -import { LocalVideoTrack } from 'livekit-client' -import { Text, P, ToggleButton, Div, H } from '@/primitives' import { useTranslation } from 'react-i18next' -import { HStack, styled, VStack } from '@/styled-system/jsx' import { BackgroundBlurFactory, BackgroundBlurProcessorInterface, -} from './blur/index' +} from '../blur' +import { css } from '@/styled-system/css' +import { Text, P, ToggleButton, H } from '@/primitives' +import { HStack, styled } from '@/styled-system/jsx' + +enum BlurRadius { + NONE = 0, + LIGHT = 5, + NORMAL = 10, +} + +const isSupported = BackgroundBlurFactory.isSupported() const Information = styled('div', { base: { @@ -19,48 +27,45 @@ const Information = styled('div', { }, }) -enum BlurRadius { - NONE = 0, - LIGHT = 5, - NORMAL = 10, -} - -const isSupported = BackgroundBlurFactory.isSupported() - -export const Effects = () => { - const { t } = useTranslation('rooms', { keyPrefix: 'effects' }) - const { isCameraEnabled, cameraTrack, localParticipant } = - useLocalParticipant() +export const EffectsConfiguration = ({ + videoTrack, + onSubmit, + layout = 'horizontal', +}: { + videoTrack: LocalVideoTrack + onSubmit?: (processor?: TrackProcessor) => void + layout?: 'vertical' | 'horizontal' +}) => { const videoRef = useRef(null) + const { t } = useTranslation('rooms', { keyPrefix: 'effects' }) const [processorPending, setProcessorPending] = useState(false) - const localCameraTrack = cameraTrack?.track as LocalVideoTrack + useEffect(() => { + const videoElement = videoRef.current + if (!videoElement) return - const getProcessor = () => { - return localCameraTrack?.getProcessor() as BackgroundBlurProcessorInterface - } + const attachVideoTrack = async () => videoTrack?.attach(videoElement) + attachVideoTrack() - const getBlurRadius = (): BlurRadius => { - const processor = getProcessor() - return processor?.options.blurRadius || BlurRadius.NONE - } + return () => { + if (!videoElement) return + videoTrack.detach(videoElement) + } + }, [videoTrack, videoTrack?.isMuted]) const toggleBlur = async (blurRadius: number) => { - if (!isCameraEnabled) await localParticipant.setCameraEnabled(true) - if (!localCameraTrack) return - + if (!videoTrack) return setProcessorPending(true) - const processor = getProcessor() const currentBlurRadius = getBlurRadius() - try { if (blurRadius == currentBlurRadius && processor) { - await localCameraTrack.stopProcessor() + await videoTrack.stopProcessor() + onSubmit?.(undefined) } else if (!processor) { - await localCameraTrack.setProcessor( - BackgroundBlurFactory.getProcessor({ blurRadius })! - ) + const newProcessor = BackgroundBlurFactory.getProcessor({ blurRadius })! + await videoTrack.setProcessor(newProcessor) + onSubmit?.(newProcessor) } else { processor?.update({ blurRadius }) } @@ -71,21 +76,17 @@ export const Effects = () => { } } - useEffect(() => { - const videoElement = videoRef.current - if (!videoElement) return + const getProcessor = () => { + return videoTrack?.getProcessor() as BackgroundBlurProcessorInterface + } - const attachVideoTrack = async () => localCameraTrack?.attach(videoElement) - attachVideoTrack() - - return () => { - if (!videoElement) return - localCameraTrack.detach(videoElement) - } - }, [localCameraTrack, isCameraEnabled]) + const getBlurRadius = (): BlurRadius => { + const processor = getProcessor() + return processor?.options.blurRadius || BlurRadius.NONE + } const isSelected = (blurRadius: BlurRadius) => { - return isCameraEnabled && getBlurRadius() == blurRadius + return getBlurRadius() == blurRadius } const tooltipLabel = (blurRadius: BlurRadius) => { @@ -93,55 +94,82 @@ export const Effects = () => { } return ( - - {localCameraTrack && isCameraEnabled ? ( -