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 ? (
-
- ) : (
-
-
+
+ {videoTrack && !videoTrack.isMuted ? (
+
+ ) : (
+
- {t('activateCamera')}
-
-
- )}
-
+ {t('activateCamera')}
+
+
+ )}
+
+
{t('heading')}
@@ -173,16 +201,9 @@ export const Effects = () => {
{t('notAvailable')}
)}
-
- ⚠︎ {t('experimental')}
-
+ ⚠︎ {t('experimental')}
-
-
+
+
)
}