diff --git a/frontend/src/Context/PreviewPublisherProvider/usePreviewPublisher/usePreviewPublisher.tsx b/frontend/src/Context/PreviewPublisherProvider/usePreviewPublisher/usePreviewPublisher.tsx index a499771b0..c17da750e 100644 --- a/frontend/src/Context/PreviewPublisherProvider/usePreviewPublisher/usePreviewPublisher.tsx +++ b/frontend/src/Context/PreviewPublisherProvider/usePreviewPublisher/usePreviewPublisher.tsx @@ -228,6 +228,9 @@ const usePreviewPublisher = (): PreviewPublisherContextType => { if (publisherRef.current) { return; } + // We reset user preferences as we want to start with both devices enabled + setStorageItem(STORAGE_KEYS.AUDIO_SOURCE_ENABLED, 'true'); + setStorageItem(STORAGE_KEYS.VIDEO_SOURCE_ENABLED, 'true'); // Set videoFilter based on user's selected background let videoFilter: VideoFilter | undefined; @@ -282,6 +285,7 @@ const usePreviewPublisher = (): PreviewPublisherContextType => { return; } publisherRef.current.publishVideo(!isVideoEnabled); + setStorageItem(STORAGE_KEYS.VIDEO_SOURCE_ENABLED, (!isVideoEnabled).toString()); setIsVideoEnabled(!isVideoEnabled); if (setUser) { setUser((prevUser: UserType) => ({ @@ -306,6 +310,7 @@ const usePreviewPublisher = (): PreviewPublisherContextType => { } publisherRef.current.publishAudio(!isAudioEnabled); setIsAudioEnabled(!isAudioEnabled); + setStorageItem(STORAGE_KEYS.AUDIO_SOURCE_ENABLED, (!isAudioEnabled).toString()); if (setUser) { setUser((prevUser: UserType) => ({ ...prevUser, diff --git a/frontend/src/Context/PublisherProvider/usePublisher/usePublisher.tsx b/frontend/src/Context/PublisherProvider/usePublisher/usePublisher.tsx index 396373f26..1d196254b 100644 --- a/frontend/src/Context/PublisherProvider/usePublisher/usePublisher.tsx +++ b/frontend/src/Context/PublisherProvider/usePublisher/usePublisher.tsx @@ -8,6 +8,7 @@ import OT, { PublisherProperties, } from '@vonage/client-sdk-video'; import { useTranslation } from 'react-i18next'; +import { setStorageItem, STORAGE_KEYS } from '@utils/storage'; import usePublisherQuality, { NetworkQuality } from '../usePublisherQuality/usePublisherQuality'; import usePublisherOptions from '../usePublisherOptions'; import useSessionContext from '../../../hooks/useSessionContext'; @@ -291,6 +292,7 @@ const usePublisher = (): PublisherContextType => { } publisherRef.current.publishVideo(!isVideoEnabled); setIsVideoEnabled(!isVideoEnabled); + setStorageItem(STORAGE_KEYS.VIDEO_SOURCE_ENABLED, (!isVideoEnabled).toString()); }; /** @@ -305,6 +307,7 @@ const usePublisher = (): PublisherContextType => { } publisherRef.current.publishAudio(!isAudioEnabled); setIsAudioEnabled(!isAudioEnabled); + setStorageItem(STORAGE_KEYS.AUDIO_SOURCE_ENABLED, (!isAudioEnabled).toString()); setIsForceMuted(false); }; diff --git a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx index 5e5c25960..91c6e53a9 100644 --- a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx +++ b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx @@ -191,6 +191,20 @@ describe('usePublisherOptions', () => { }); }); }); + + it('should disable audio and video from storage options', async () => { + vi.spyOn(OT, 'hasMediaProcessorSupport').mockReturnValue(true); + setStorageItem(STORAGE_KEYS.AUDIO_SOURCE_ENABLED, 'false'); + setStorageItem(STORAGE_KEYS.VIDEO_SOURCE_ENABLED, 'true'); + + await deviceStore.init(); + vi.mocked(useUserContext).mockImplementation(() => mockUserContextWithCustomSettings); + const { result } = renderHook(() => usePublisherOptions()); + await waitFor(() => { + expect(result.current?.publishAudio).toBe(false); + expect(result.current?.publishVideo).toBe(true); + }); + }); }); function renderHook( diff --git a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx index 5e6fb964d..9be295c09 100644 --- a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx +++ b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx @@ -9,6 +9,7 @@ import useAppConfig from '@Context/AppConfig/hooks/useAppConfig'; import useUserContext from '@hooks/useUserContext'; import getInitials from '@utils/getInitials'; import DeviceStore from '@utils/DeviceStore'; +import { getStorageItem, STORAGE_KEYS } from '@utils/storage'; /** * React hook to get PublisherProperties combining default options and options set in UserContext @@ -53,14 +54,17 @@ const usePublisherOptions = (): PublisherProperties | null => { const videoFilter: VideoFilter | undefined = backgroundFilter && hasMediaProcessorSupport() ? backgroundFilter : undefined; + const isAudioDisabled = getStorageItem(STORAGE_KEYS.AUDIO_SOURCE_ENABLED) === 'false'; + const isVideoDisabled = getStorageItem(STORAGE_KEYS.VIDEO_SOURCE_ENABLED) === 'false'; + setPublisherOptions({ audioFallback: { publisher: true }, audioSource, initials, insertDefaultUI: false, name, - publishAudio: allowAudioOnJoin && publishAudio, - publishVideo: allowVideoOnJoin && publishVideo, + publishAudio: allowAudioOnJoin && publishAudio && !isAudioDisabled, + publishVideo: allowVideoOnJoin && publishVideo && !isVideoDisabled, resolution: defaultResolution, audioFilter, videoFilter, diff --git a/frontend/src/utils/storage.ts b/frontend/src/utils/storage.ts index bd0c76f71..d1d21eaf0 100644 --- a/frontend/src/utils/storage.ts +++ b/frontend/src/utils/storage.ts @@ -1,6 +1,8 @@ export const STORAGE_KEYS = { AUDIO_SOURCE: 'audioSource', + AUDIO_SOURCE_ENABLED: 'audioSourceEnabled', VIDEO_SOURCE: 'videoSource', + VIDEO_SOURCE_ENABLED: 'videoSourceEnabled', NOISE_SUPPRESSION: 'noiseSuppression', BACKGROUND_REPLACEMENT: 'backgroundReplacement', USERNAME: 'username',