-
-
}
- variant="outlined"
- startIcon={
}
- aria-controls={openVideoInput ? 'basic-menu' : undefined}
- aria-haspopup="true"
- aria-expanded={openVideoInput ? 'true' : undefined}
- onClick={handleAudioInputOpen}
- >
- {isSmallViewport ? 'Mic' : 'Microphone'}
-
-
-
}
- sx={buttonSx}
- variant="outlined"
- startIcon={
}
- aria-label="video"
- >
- Camera
-
+ waitingRoomSettings.allowDeviceSelection && (
+
+
+ }
+ variant="outlined"
+ startIcon={}
+ aria-controls={openVideoInput ? 'basic-menu' : undefined}
+ aria-haspopup="true"
+ aria-expanded={openVideoInput ? 'true' : undefined}
+ onClick={handleAudioInputOpen}
+ >
+ {isSmallViewport ? 'Mic' : 'Microphone'}
+
+
+ }
+ sx={buttonSx}
+ variant="outlined"
+ startIcon={}
+ aria-label="video"
+ >
+ Camera
+
-
- }
- sx={buttonSx}
- variant="outlined"
- startIcon={}
- >
- Speaker
-
-
+
+ }
+ sx={buttonSx}
+ variant="outlined"
+ startIcon={}
+ >
+ Speaker
+
+
+
-
+ )
);
};
From f4c15abcf9c91b37c5daa86c2d7dd3a38d5e66fd Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Fri, 12 Sep 2025 14:23:53 -0700
Subject: [PATCH 26/58] fix that test
---
.../useConfig/useConfig.spec.tsx | 71 +++++++++++--------
.../ConfigProvider/useConfig/useConfig.tsx | 2 +
2 files changed, 45 insertions(+), 28 deletions(-)
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index 9003bef8..0e385608 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -1,4 +1,4 @@
-import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from 'vitest';
+import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
import { renderHook, waitFor } from '@testing-library/react';
import useConfig from './useConfig';
@@ -9,6 +9,12 @@ describe('useConfig', () => {
nativeFetch = global.fetch;
});
+ beforeEach(() => {
+ global.fetch = vi.fn().mockResolvedValue({
+ json: async () => ({}),
+ });
+ });
+
afterEach(() => {
vi.resetAllMocks();
});
@@ -17,21 +23,28 @@ describe('useConfig', () => {
global.fetch = nativeFetch;
});
- it('returns the default config when no config.json is loaded', () => {
+ it('returns the default config when no config.json is loaded', async () => {
const { result } = renderHook(() => useConfig());
- expect(result.current).toMatchObject({
- videoSettings: {
- enableDisableCapableCamera: true,
- resolution: '1280x720',
- videoOnJoin: true,
- backgroundEffects: true,
- },
- audioSettings: {
- advancedNoiseSuppression: true,
- audioOnJoin: true,
- enableDisableCapableMicrophone: true,
- },
- layoutMode: 'active-speaker',
+
+ await waitFor(() => {
+ expect(result.current).toEqual({
+ videoSettings: {
+ enableDisableCapableCamera: true,
+ resolution: '1280x720',
+ videoOnJoin: true,
+ backgroundEffects: true,
+ },
+ audioSettings: {
+ advancedNoiseSuppression: true,
+ audioOnJoin: true,
+ enableDisableCapableMicrophone: true,
+ },
+ waitingRoomSettings: {
+ allowDeviceSelection: true,
+ enableWaitingRoom: true,
+ },
+ layoutMode: 'active-speaker',
+ });
});
});
@@ -64,19 +77,21 @@ describe('useConfig', () => {
global.fetch = vi.fn().mockRejectedValue(new Error('mocking a failure to fetch'));
const { result } = renderHook(() => useConfig());
- expect(result.current).toMatchObject({
- videoSettings: {
- enableDisableCapableCamera: true,
- resolution: '1280x720',
- videoOnJoin: true,
- backgroundEffects: true,
- },
- audioSettings: {
- advancedNoiseSuppression: true,
- audioOnJoin: true,
- enableDisableCapableMicrophone: true,
- },
- layoutMode: 'active-speaker',
+ await waitFor(() => {
+ expect(result.current).toMatchObject({
+ videoSettings: {
+ enableDisableCapableCamera: true,
+ resolution: '1280x720',
+ videoOnJoin: true,
+ backgroundEffects: true,
+ },
+ audioSettings: {
+ advancedNoiseSuppression: true,
+ audioOnJoin: true,
+ enableDisableCapableMicrophone: true,
+ },
+ layoutMode: 'active-speaker',
+ });
});
});
});
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index d625ead8..390b1572 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -16,6 +16,7 @@ export type AudioSettings = {
export type WaitingRoomSettings = {
allowDeviceSelection: boolean;
+ enableWaitingRoom: boolean;
};
export type AppConfig = {
@@ -39,6 +40,7 @@ export const defaultConfig: AppConfig = {
},
waitingRoomSettings: {
allowDeviceSelection: true,
+ enableWaitingRoom: true,
},
layoutMode: 'active-speaker',
};
From 587471ca2282d774b9d2d7dc6c7b518bc81d96a1 Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Fri, 12 Sep 2025 14:24:28 -0700
Subject: [PATCH 27/58] too excited
---
.../src/Context/ConfigProvider/useConfig/useConfig.spec.tsx | 1 -
frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx | 2 --
2 files changed, 3 deletions(-)
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index 0e385608..caeca838 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -41,7 +41,6 @@ describe('useConfig', () => {
},
waitingRoomSettings: {
allowDeviceSelection: true,
- enableWaitingRoom: true,
},
layoutMode: 'active-speaker',
});
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index 390b1572..d625ead8 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -16,7 +16,6 @@ export type AudioSettings = {
export type WaitingRoomSettings = {
allowDeviceSelection: boolean;
- enableWaitingRoom: boolean;
};
export type AppConfig = {
@@ -40,7 +39,6 @@ export const defaultConfig: AppConfig = {
},
waitingRoomSettings: {
allowDeviceSelection: true,
- enableWaitingRoom: true,
},
layoutMode: 'active-speaker',
};
From 61707885de368b57009f76ad2c0996209006080b Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Tue, 16 Sep 2025 11:21:27 -0700
Subject: [PATCH 28/58] participant-list
---
.../useConfig/useConfig.spec.tsx | 14 ++++-
.../ConfigProvider/useConfig/useConfig.tsx | 24 +++++++-
.../src/Context/SessionProvider/session.tsx | 2 +-
.../ParticipantListButton.tsx | 57 ++++++++++---------
.../ParticipantsListButton.spec.tsx | 25 +++++++-
5 files changed, 89 insertions(+), 33 deletions(-)
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index caeca838..4f48be14 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -42,7 +42,10 @@ describe('useConfig', () => {
waitingRoomSettings: {
allowDeviceSelection: true,
},
- layoutMode: 'active-speaker',
+ meetingRoomSettings: {
+ layoutMode: 'active-speaker',
+ showParticipantList: true,
+ },
});
});
});
@@ -60,7 +63,13 @@ describe('useConfig', () => {
audioOnJoin: false,
enableDisableCapableMicrophone: false,
},
- layoutMode: 'grid',
+ waitingRoomSettings: {
+ allowDeviceSelection: false,
+ },
+ meetingRoomSettings: {
+ layoutMode: 'grid',
+ showParticipantList: false,
+ },
};
global.fetch = vi.fn().mockResolvedValue({
json: async () => mockConfig,
@@ -89,7 +98,6 @@ describe('useConfig', () => {
audioOnJoin: true,
enableDisableCapableMicrophone: true,
},
- layoutMode: 'active-speaker',
});
});
});
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index d625ead8..54fa33c4 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -18,11 +18,16 @@ export type WaitingRoomSettings = {
allowDeviceSelection: boolean;
};
+export type MeetingRoomSettings = {
+ layoutMode: LayoutMode;
+ showParticipantList: boolean;
+};
+
export type AppConfig = {
videoSettings: VideoSettings;
audioSettings: AudioSettings;
waitingRoomSettings: WaitingRoomSettings;
- layoutMode: LayoutMode;
+ meetingRoomSettings: MeetingRoomSettings;
};
export const defaultConfig: AppConfig = {
@@ -40,7 +45,10 @@ export const defaultConfig: AppConfig = {
waitingRoomSettings: {
allowDeviceSelection: true,
},
- layoutMode: 'active-speaker',
+ meetingRoomSettings: {
+ layoutMode: 'active-speaker',
+ showParticipantList: true,
+ },
};
/**
@@ -77,6 +85,18 @@ const useConfig = (): AppConfig => {
...defaultConfig.videoSettings,
...(typedConfigFile.videoSettings || {}),
},
+ audioSettings: {
+ ...defaultConfig.audioSettings,
+ ...(typedConfigFile.audioSettings || {}),
+ },
+ waitingRoomSettings: {
+ ...defaultConfig.waitingRoomSettings,
+ ...(typedConfigFile.waitingRoomSettings || {}),
+ },
+ meetingRoomSettings: {
+ ...defaultConfig.meetingRoomSettings,
+ ...(typedConfigFile.meetingRoomSettings || {}),
+ },
};
}, [config]);
diff --git a/frontend/src/Context/SessionProvider/session.tsx b/frontend/src/Context/SessionProvider/session.tsx
index 74dcd509..9726c386 100644
--- a/frontend/src/Context/SessionProvider/session.tsx
+++ b/frontend/src/Context/SessionProvider/session.tsx
@@ -134,7 +134,7 @@ const SessionProvider = ({ children }: SessionProviderProps): ReactElement => {
const [reconnecting, setReconnecting] = useState(false);
const [subscriberWrappers, setSubscriberWrappers] = useState
([]);
const [ownCaptions, setOwnCaptions] = useState(null);
- const [layoutMode, setLayoutMode] = useState(config.layoutMode);
+ const [layoutMode, setLayoutMode] = useState(config.meetingRoomSettings.layoutMode);
const [archiveId, setArchiveId] = useState(null);
const activeSpeakerTracker = useRef(new ActiveSpeakerTracker());
const [activeSpeakerId, setActiveSpeakerId] = useState();
diff --git a/frontend/src/components/MeetingRoom/ParticipantListButton/ParticipantListButton.tsx b/frontend/src/components/MeetingRoom/ParticipantListButton/ParticipantListButton.tsx
index a4176de5..daf4e045 100644
--- a/frontend/src/components/MeetingRoom/ParticipantListButton/ParticipantListButton.tsx
+++ b/frontend/src/components/MeetingRoom/ParticipantListButton/ParticipantListButton.tsx
@@ -4,6 +4,7 @@ import { blue } from '@mui/material/colors';
import { Badge } from '@mui/material';
import { ReactElement } from 'react';
import ToolbarButton from '../ToolbarButton';
+import useConfigContext from '../../../hooks/useConfigContext';
export type ParticipantListButtonProps = {
handleClick: () => void;
@@ -28,36 +29,40 @@ const ParticipantListButton = ({
isOpen,
participantCount,
isOverflowButton = false,
-}: ParticipantListButtonProps): ReactElement => {
+}: ParticipantListButtonProps): ReactElement | false => {
+ const { meetingRoomSettings } = useConfigContext();
+
return (
-
-
- }
- isOverflowButton={isOverflowButton}
- />
-
-
+ overlap="circular"
+ >
+ }
+ isOverflowButton={isOverflowButton}
+ />
+
+
+ )
);
};
diff --git a/frontend/src/components/MeetingRoom/ParticipantListButton/ParticipantsListButton.spec.tsx b/frontend/src/components/MeetingRoom/ParticipantListButton/ParticipantsListButton.spec.tsx
index 8ff47c55..9b92b7f9 100644
--- a/frontend/src/components/MeetingRoom/ParticipantListButton/ParticipantsListButton.spec.tsx
+++ b/frontend/src/components/MeetingRoom/ParticipantListButton/ParticipantsListButton.spec.tsx
@@ -1,8 +1,22 @@
import { render, screen } from '@testing-library/react';
-import { describe, expect, it, vi } from 'vitest';
+import { describe, expect, it, Mock, vi, beforeEach } from 'vitest';
import ParticipantListButton from './ParticipantListButton';
+import useConfigContext from '../../../hooks/useConfigContext';
+import { ConfigContextType } from '../../../Context/ConfigProvider';
+
+vi.mock('../../../hooks/useConfigContext');
+
+const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
describe('ParticipantListButton', () => {
+ beforeEach(() => {
+ mockUseConfigContext.mockReturnValue({
+ meetingRoomSettings: {
+ showParticipantList: true,
+ },
+ } as unknown as ConfigContextType);
+ });
+
it('should show participant number', () => {
render( {}} isOpen={false} participantCount={10} />);
expect(screen.getByText('10')).toBeVisible();
@@ -21,4 +35,13 @@ describe('ParticipantListButton', () => {
screen.getByRole('button').click();
expect(handleClick).toHaveBeenCalled();
});
+ it('should not render if showParticipantList is false in config', () => {
+ mockUseConfigContext.mockReturnValue({
+ meetingRoomSettings: {
+ showParticipantList: false,
+ },
+ } as unknown as ConfigContextType);
+ render( {}} isOpen={false} participantCount={10} />);
+ expect(screen.queryByTestId('participant-list-button')).not.toBeInTheDocument();
+ });
});
From 3e10a68608bbf61790fffc71102b2da35c0946dd Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Tue, 16 Sep 2025 11:22:52 -0700
Subject: [PATCH 29/58] lint
---
frontend/src/Context/ConfigProvider/index.tsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/frontend/src/Context/ConfigProvider/index.tsx b/frontend/src/Context/ConfigProvider/index.tsx
index 7e332e15..7bbeb424 100644
--- a/frontend/src/Context/ConfigProvider/index.tsx
+++ b/frontend/src/Context/ConfigProvider/index.tsx
@@ -8,9 +8,10 @@ export type ConfigProviderProps = {
export type ConfigContextType = ReturnType;
export const ConfigContext = createContext({
- videoSettings: defaultConfig.videoSettings,
- layoutMode: defaultConfig.layoutMode,
audioSettings: defaultConfig.audioSettings,
+ meetingRoomSettings: defaultConfig.meetingRoomSettings,
+ waitingRoomSettings: defaultConfig.waitingRoomSettings,
+ videoSettings: defaultConfig.videoSettings,
});
export const ConfigContextProvider = ({ children }: ConfigProviderProps) => {
From 01713d731f83ec0bf4ff8f2b5d4f3149964ef94a Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Tue, 16 Sep 2025 12:56:08 -0700
Subject: [PATCH 30/58] config file
---
config.example.json | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
diff --git a/config.example.json b/config.example.json
index 2421e7e9..4f35211a 100644
--- a/config.example.json
+++ b/config.example.json
@@ -1,9 +1,20 @@
{
"videoSettings": {
+ "backgroundEffects": true,
"enableDisableCapableCamera": true,
"resolution": "1280x720",
- "videoOnJoin": true,
- "backgroundEffects": true
+ "videoOnJoin": true
},
- "layoutMode": "active-speaker"
+ "audioSettings": {
+ "advancedNoiseSuppression": true,
+ "audioOnJoin": true,
+ "enableDisableCapableMicrophone": true
+ },
+ "waitingRoomSettings": {
+ "allowDeviceSelection": true
+ },
+ "meetingRoomSettings": {
+ "layoutMode": "active-speaker",
+ "showParticipantList": true
+ }
}
From 84e7ec3468702f9234100414317474bea28fe084 Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Tue, 16 Sep 2025 13:14:49 -0700
Subject: [PATCH 31/58] resolve another bug
---
.../useBackgroundPublisher/useBackgroundPublisher.tsx | 6 +++---
.../src/components/MeetingRoom/Toolbar/Toolbar.tsx | 5 ++++-
frontend/src/pages/MeetingRoom/MeetingRoom.tsx | 10 +---------
3 files changed, 8 insertions(+), 13 deletions(-)
diff --git a/frontend/src/Context/BackgroundPublisherProvider/useBackgroundPublisher/useBackgroundPublisher.tsx b/frontend/src/Context/BackgroundPublisherProvider/useBackgroundPublisher/useBackgroundPublisher.tsx
index 750ade76..69e7adbd 100644
--- a/frontend/src/Context/BackgroundPublisherProvider/useBackgroundPublisher/useBackgroundPublisher.tsx
+++ b/frontend/src/Context/BackgroundPublisherProvider/useBackgroundPublisher/useBackgroundPublisher.tsx
@@ -166,7 +166,7 @@ const useBackgroundPublisher = (): BackgroundPublisherContextType => {
);
const initBackgroundLocalPublisher = useCallback(async () => {
- if (backgroundPublisherRef.current || !defaultPublisherOptions) {
+ if (backgroundPublisherRef.current) {
return;
}
@@ -185,7 +185,7 @@ const useBackgroundPublisher = (): BackgroundPublisherContextType => {
resolution: '1280x720',
videoSource,
publishAudio: false,
- publishVideo: defaultPublisherOptions?.publishVideo,
+ publishVideo: isVideoEnabled,
};
backgroundPublisherRef.current = initPublisher(undefined, publisherOptions, (err: unknown) => {
@@ -197,7 +197,7 @@ const useBackgroundPublisher = (): BackgroundPublisherContextType => {
}
});
addPublisherListeners(backgroundPublisherRef.current);
- }, [addPublisherListeners, defaultPublisherOptions]);
+ }, [addPublisherListeners, isVideoEnabled]);
/**
* Destroys the background publisher
diff --git a/frontend/src/components/MeetingRoom/Toolbar/Toolbar.tsx b/frontend/src/components/MeetingRoom/Toolbar/Toolbar.tsx
index 1afdd407..cf844a35 100644
--- a/frontend/src/components/MeetingRoom/Toolbar/Toolbar.tsx
+++ b/frontend/src/components/MeetingRoom/Toolbar/Toolbar.tsx
@@ -15,6 +15,7 @@ import EmojiGridButton from '../EmojiGridButton';
import isReportIssueEnabled from '../../../utils/isReportIssueEnabled';
import useToolbarButtons from '../../../hooks/useToolbarButtons';
import DeviceControlButton from '../DeviceControlButton';
+import useBackgroundPublisherContext from '../../../hooks/useBackgroundPublisherContext';
export type CaptionsState = {
isUserCaptionsEnabled: boolean;
@@ -69,6 +70,7 @@ const Toolbar = ({
captionsState,
}: ToolbarProps): ReactElement => {
const { disconnect, subscriberWrappers } = useSessionContext();
+ const { destroyBackgroundPublisher } = useBackgroundPublisherContext();
const isViewingScreenShare = subscriberWrappers.some((subWrapper) => subWrapper.isScreenshare);
const isScreenSharePresent = isViewingScreenShare || isSharingScreen;
const isPinningPresent = subscriberWrappers.some((subWrapper) => subWrapper.isPinned);
@@ -77,7 +79,8 @@ const Toolbar = ({
return;
}
disconnect();
- }, [disconnect]);
+ destroyBackgroundPublisher();
+ }, [destroyBackgroundPublisher, disconnect]);
const [openEmojiGridDesktop, setOpenEmojiGridDesktop] = useState(false);
// An array of buttons available for the toolbar. As the toolbar resizes, buttons may be hidden and moved to the
diff --git a/frontend/src/pages/MeetingRoom/MeetingRoom.tsx b/frontend/src/pages/MeetingRoom/MeetingRoom.tsx
index b23da15d..968440c4 100644
--- a/frontend/src/pages/MeetingRoom/MeetingRoom.tsx
+++ b/frontend/src/pages/MeetingRoom/MeetingRoom.tsx
@@ -38,7 +38,6 @@ const MeetingRoom = (): ReactElement => {
initBackgroundLocalPublisher,
publisher: backgroundPublisher,
accessStatus,
- destroyBackgroundPublisher,
} = useBackgroundPublisherContext();
const {
@@ -99,14 +98,7 @@ const MeetingRoom = (): ReactElement => {
if (!backgroundPublisher) {
initBackgroundLocalPublisher();
}
-
- return () => {
- // Ensure we destroy the backgroundPublisher and release any media devices.
- if (backgroundPublisher) {
- destroyBackgroundPublisher();
- }
- };
- }, [initBackgroundLocalPublisher, backgroundPublisher, destroyBackgroundPublisher]);
+ }, [initBackgroundLocalPublisher, backgroundPublisher]);
// After changing device permissions, reload the page to reflect the device's permission change.
useEffect(() => {
From f5fa301691c9cdca5234384fc4f501478e22b190 Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Wed, 17 Sep 2025 08:10:46 -0700
Subject: [PATCH 32/58] fixed tests
---
frontend/src/Context/SessionProvider/session.spec.tsx | 9 +++++++++
frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx | 3 +++
2 files changed, 12 insertions(+)
diff --git a/frontend/src/Context/SessionProvider/session.spec.tsx b/frontend/src/Context/SessionProvider/session.spec.tsx
index 68725136..0018de4c 100644
--- a/frontend/src/Context/SessionProvider/session.spec.tsx
+++ b/frontend/src/Context/SessionProvider/session.spec.tsx
@@ -20,6 +20,15 @@ vi.mock('../../utils/constants', () => ({
MAX_PIN_COUNT_DESKTOP: 1,
}));
vi.mock('../../api/fetchCredentials');
+vi.mock('../../hooks/useConfigContext', () => {
+ return {
+ default: () => ({
+ meetingRoomSettings: {
+ layoutMode: 'active-speaker',
+ },
+ }),
+ };
+});
const mockFetchCredentials = fetchCredentials as Mock;
diff --git a/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx b/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
index bf1781c5..7fdd1c44 100644
--- a/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
+++ b/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
@@ -63,6 +63,9 @@ vi.mock('../../hooks/useConfigContext', () => {
audioSettings: {
enableDisableCapableMicrophone: true,
},
+ meetingRoomSettings: {
+ layoutMode: 'active-speaker',
+ },
}),
};
});
From 4d478d5f4b1a7f3c659958dee9bac57ab409f3f1 Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Wed, 17 Sep 2025 08:58:41 -0700
Subject: [PATCH 33/58] chat button
---
config.example.json | 3 +-
.../useConfig/useConfig.spec.tsx | 61 ++++++++-----------
.../ConfigProvider/useConfig/useConfig.tsx | 2 +
.../ChatButton/ChatButton.spec.tsx | 20 ++++++
.../MeetingRoom/ChatButton/ChatButton.tsx | 37 ++++++-----
.../UnreadMessagesBadge.spec.tsx | 34 +++++++++++
.../UnreadMessagesBadge.tsx | 6 +-
.../pages/MeetingRoom/MeetingRoom.spec.tsx | 1 +
8 files changed, 111 insertions(+), 53 deletions(-)
diff --git a/config.example.json b/config.example.json
index 4f35211a..3aa6c64f 100644
--- a/config.example.json
+++ b/config.example.json
@@ -15,6 +15,7 @@
},
"meetingRoomSettings": {
"layoutMode": "active-speaker",
- "showParticipantList": true
+ "showParticipantList": true,
+ "showChat": true
}
}
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index 4f48be14..a46f3299 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -1,9 +1,30 @@
import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
import { renderHook, waitFor } from '@testing-library/react';
-import useConfig from './useConfig';
+import useConfig, { AppConfig } from './useConfig';
describe('useConfig', () => {
let nativeFetch: typeof global.fetch;
+ const defaultConfig: AppConfig = {
+ videoSettings: {
+ enableDisableCapableCamera: true,
+ resolution: '1280x720',
+ videoOnJoin: true,
+ backgroundEffects: true,
+ },
+ audioSettings: {
+ advancedNoiseSuppression: true,
+ audioOnJoin: true,
+ enableDisableCapableMicrophone: true,
+ },
+ waitingRoomSettings: {
+ allowDeviceSelection: true,
+ },
+ meetingRoomSettings: {
+ layoutMode: 'active-speaker',
+ showParticipantList: true,
+ showChat: true,
+ },
+ };
beforeAll(() => {
nativeFetch = global.fetch;
@@ -27,31 +48,12 @@ describe('useConfig', () => {
const { result } = renderHook(() => useConfig());
await waitFor(() => {
- expect(result.current).toEqual({
- videoSettings: {
- enableDisableCapableCamera: true,
- resolution: '1280x720',
- videoOnJoin: true,
- backgroundEffects: true,
- },
- audioSettings: {
- advancedNoiseSuppression: true,
- audioOnJoin: true,
- enableDisableCapableMicrophone: true,
- },
- waitingRoomSettings: {
- allowDeviceSelection: true,
- },
- meetingRoomSettings: {
- layoutMode: 'active-speaker',
- showParticipantList: true,
- },
- });
+ expect(result.current).toEqual(defaultConfig);
});
});
it('merges config.json values if loaded (mocked fetch)', async () => {
- const mockConfig = {
+ const mockConfig: AppConfig = {
videoSettings: {
enableDisableCapableCamera: false,
resolution: '640x480',
@@ -69,6 +71,7 @@ describe('useConfig', () => {
meetingRoomSettings: {
layoutMode: 'grid',
showParticipantList: false,
+ showChat: false,
},
};
global.fetch = vi.fn().mockResolvedValue({
@@ -86,19 +89,7 @@ describe('useConfig', () => {
const { result } = renderHook(() => useConfig());
await waitFor(() => {
- expect(result.current).toMatchObject({
- videoSettings: {
- enableDisableCapableCamera: true,
- resolution: '1280x720',
- videoOnJoin: true,
- backgroundEffects: true,
- },
- audioSettings: {
- advancedNoiseSuppression: true,
- audioOnJoin: true,
- enableDisableCapableMicrophone: true,
- },
- });
+ expect(result.current).toEqual(defaultConfig);
});
});
});
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index 54fa33c4..87873f0b 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -21,6 +21,7 @@ export type WaitingRoomSettings = {
export type MeetingRoomSettings = {
layoutMode: LayoutMode;
showParticipantList: boolean;
+ showChat: boolean;
};
export type AppConfig = {
@@ -48,6 +49,7 @@ export const defaultConfig: AppConfig = {
meetingRoomSettings: {
layoutMode: 'active-speaker',
showParticipantList: true,
+ showChat: true,
},
};
diff --git a/frontend/src/components/MeetingRoom/ChatButton/ChatButton.spec.tsx b/frontend/src/components/MeetingRoom/ChatButton/ChatButton.spec.tsx
index f18f11c1..fbcd8ea3 100644
--- a/frontend/src/components/MeetingRoom/ChatButton/ChatButton.spec.tsx
+++ b/frontend/src/components/MeetingRoom/ChatButton/ChatButton.spec.tsx
@@ -3,16 +3,26 @@ import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
import ChatButton from './ChatButton';
import useSessionContext from '../../../hooks/useSessionContext';
import { SessionContextType } from '../../../Context/SessionProvider/session';
+import useConfigContext from '../../../hooks/useConfigContext';
+import { ConfigContextType } from '../../../Context/ConfigProvider';
vi.mock('../../../hooks/useSessionContext');
+vi.mock('../../../hooks/useConfigContext');
const mockUseSessionContext = useSessionContext as Mock<[], SessionContextType>;
const sessionContext = {
unreadCount: 10,
} as unknown as SessionContextType;
+const mockConfigContext = {
+ meetingRoomSettings: {
+ showChat: true,
+ },
+} as unknown as ConfigContextType;
+const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
describe('ChatButton', () => {
beforeEach(() => {
mockUseSessionContext.mockReturnValue(sessionContext);
+ mockUseConfigContext.mockReturnValue(mockConfigContext);
});
it('should show unread message number', () => {
@@ -51,4 +61,14 @@ describe('ChatButton', () => {
screen.getByRole('button').click();
expect(handleClick).toHaveBeenCalled();
});
+
+ it('should not be displayed when chat is disabled', () => {
+ mockUseConfigContext.mockReturnValue({
+ meetingRoomSettings: {
+ showChat: false,
+ },
+ } as unknown as ConfigContextType);
+ render( {}} isOpen />);
+ expect(screen.queryByTestId('ChatIcon')).not.toBeInTheDocument();
+ });
});
diff --git a/frontend/src/components/MeetingRoom/ChatButton/ChatButton.tsx b/frontend/src/components/MeetingRoom/ChatButton/ChatButton.tsx
index fcb34722..d2feeea7 100644
--- a/frontend/src/components/MeetingRoom/ChatButton/ChatButton.tsx
+++ b/frontend/src/components/MeetingRoom/ChatButton/ChatButton.tsx
@@ -4,6 +4,7 @@ import { blue } from '@mui/material/colors';
import { ReactElement } from 'react';
import ToolbarButton from '../ToolbarButton';
import UnreadMessagesBadge from '../UnreadMessagesBadge';
+import useConfigContext from '../../../hooks/useConfigContext';
export type ChatButtonProps = {
handleClick: () => void;
@@ -20,28 +21,32 @@ export type ChatButtonProps = {
* @property {() => void} handleClick - click handler to toggle open chat panel
* @property {boolean} isOpen - true if chat is currently open, false if not
* @property {boolean} isOverflowButton - (optional) whether the button is in the ToolbarOverflowMenu
- * @returns {ReactElement} - ChatButton
+ * @returns {ReactElement | false} - ChatButton
*/
const ChatButton = ({
handleClick,
isOpen,
isOverflowButton = false,
-}: ChatButtonProps): ReactElement => {
+}: ChatButtonProps): ReactElement | false => {
+ const { meetingRoomSettings } = useConfigContext();
+
return (
-
-
- }
- isOverflowButton={isOverflowButton}
- />
-
-
+ meetingRoomSettings.showChat && (
+
+
+ }
+ isOverflowButton={isOverflowButton}
+ />
+
+
+ )
);
};
diff --git a/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.spec.tsx b/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.spec.tsx
index 116882f9..c14360a9 100644
--- a/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.spec.tsx
+++ b/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.spec.tsx
@@ -5,17 +5,27 @@ import useSessionContext from '../../../hooks/useSessionContext';
import { SessionContextType } from '../../../Context/SessionProvider/session';
import UnreadMessagesBadge from './UnreadMessagesBadge';
import ToolbarButton from '../ToolbarButton';
+import useConfigContext from '../../../hooks/useConfigContext';
+import { ConfigContextType } from '../../../Context/ConfigProvider';
vi.mock('../../../hooks/useSessionContext');
+vi.mock('../../../hooks/useConfigContext');
const mockUseSessionContext = useSessionContext as Mock<[], SessionContextType>;
const sessionContext = {
unreadCount: 0,
} as unknown as SessionContextType;
const LittleButton = () => {}} icon={} />;
+const mockConfigContext = {
+ meetingRoomSettings: {
+ showChat: true,
+ },
+} as unknown as ConfigContextType;
+const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
describe('UnreadMessagesBadge', () => {
beforeEach(() => {
mockUseSessionContext.mockReturnValue(sessionContext);
+ mockUseConfigContext.mockReturnValue(mockConfigContext);
});
it('shows badge with correct unread message count', () => {
@@ -160,4 +170,28 @@ describe('UnreadMessagesBadge', () => {
expect(updatedBadge).toBeVisible();
expect(updatedBadge.textContent).toBe('1');
});
+
+ it('should not show the message badge when it is configured to be hidden', () => {
+ const sessionContextWithMessages: SessionContextType = {
+ ...sessionContext,
+ unreadCount: 8,
+ } as unknown as SessionContextType;
+ mockUseSessionContext.mockReturnValue(sessionContextWithMessages);
+ mockUseConfigContext.mockReturnValue({
+ meetingRoomSettings: {
+ showChat: false,
+ },
+ } as unknown as ConfigContextType);
+
+ render(
+
+
+
+ );
+
+ const badge = screen.getByTestId('chat-button-unread-count');
+ // Check badge is hidden: MUI hides badge by setting dimensions to 0x0
+ expect(badge.offsetHeight).toBe(0);
+ expect(badge.offsetWidth).toBe(0);
+ });
});
diff --git a/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.tsx b/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.tsx
index 494e832c..62b6a642 100644
--- a/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.tsx
+++ b/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.tsx
@@ -1,6 +1,7 @@
import { Badge } from '@mui/material';
import { ForwardedRef, forwardRef, ReactElement } from 'react';
import useSessionContext from '../../../hooks/useSessionContext';
+import useConfigContext from '../../../hooks/useConfigContext';
export type UnreadMessagesBadgeProps = {
children: ReactElement;
@@ -20,9 +21,12 @@ const UnreadMessagesBadge = forwardRef(function UnreadMessagesBadge(
props: UnreadMessagesBadgeProps,
ref: ForwardedRef
) {
+ const { meetingRoomSettings } = useConfigContext();
const { children, isToolbarOverflowMenuOpen, ...rest } = props;
const { unreadCount } = useSessionContext();
- const isInvisible = unreadCount === 0 || isToolbarOverflowMenuOpen;
+ const isInvisible =
+ unreadCount === 0 || isToolbarOverflowMenuOpen || !meetingRoomSettings.showChat;
+
return (
{
},
meetingRoomSettings: {
layoutMode: 'active-speaker',
+ showChat: true,
},
}),
};
From f37c7a862952b0cb68e770efe8458a6a2c844c82 Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Wed, 17 Sep 2025 13:02:20 -0700
Subject: [PATCH 34/58] screen-sharing
---
config.example.json | 3 ++-
.../useConfig/useConfig.spec.tsx | 2 ++
.../ConfigProvider/useConfig/useConfig.tsx | 2 ++
.../ScreenSharingButton.spec.tsx | 23 ++++++++++++++++++-
.../ScreenSharingButton.tsx | 5 +++-
.../pages/MeetingRoom/MeetingRoom.spec.tsx | 1 +
6 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/config.example.json b/config.example.json
index 3aa6c64f..ee253e74 100644
--- a/config.example.json
+++ b/config.example.json
@@ -16,6 +16,7 @@
"meetingRoomSettings": {
"layoutMode": "active-speaker",
"showParticipantList": true,
- "showChat": true
+ "showChat": true,
+ "showScreenShareButton": true
}
}
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index a46f3299..f95b99e3 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -23,6 +23,7 @@ describe('useConfig', () => {
layoutMode: 'active-speaker',
showParticipantList: true,
showChat: true,
+ showScreenShareButton: true,
},
};
@@ -72,6 +73,7 @@ describe('useConfig', () => {
layoutMode: 'grid',
showParticipantList: false,
showChat: false,
+ showScreenShareButton: false,
},
};
global.fetch = vi.fn().mockResolvedValue({
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index 87873f0b..69e523b9 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -22,6 +22,7 @@ export type MeetingRoomSettings = {
layoutMode: LayoutMode;
showParticipantList: boolean;
showChat: boolean;
+ showScreenShareButton: boolean;
};
export type AppConfig = {
@@ -50,6 +51,7 @@ export const defaultConfig: AppConfig = {
layoutMode: 'active-speaker',
showParticipantList: true,
showChat: true,
+ showScreenShareButton: true,
},
};
diff --git a/frontend/src/components/ScreenSharingButton/ScreenSharingButton.spec.tsx b/frontend/src/components/ScreenSharingButton/ScreenSharingButton.spec.tsx
index 70c948f6..f9ad6502 100644
--- a/frontend/src/components/ScreenSharingButton/ScreenSharingButton.spec.tsx
+++ b/frontend/src/components/ScreenSharingButton/ScreenSharingButton.spec.tsx
@@ -1,8 +1,23 @@
-import { describe, expect, it, vi } from 'vitest';
+import { beforeEach, describe, expect, it, Mock, vi } from 'vitest';
import { fireEvent, render, screen } from '@testing-library/react';
import ScreenSharingButton, { ScreenShareButtonProps } from './ScreenSharingButton';
+import useConfigContext from '../../hooks/useConfigContext';
+import { ConfigContextType } from '../../Context/ConfigProvider';
+
+vi.mock('../../hooks/useConfigContext');
+
+const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
+const mockConfigContext = {
+ meetingRoomSettings: {
+ showScreenShareButton: true,
+ },
+} as unknown as ConfigContextType;
describe('ScreenSharingButton', () => {
+ beforeEach(() => {
+ mockUseConfigContext.mockReturnValue(mockConfigContext);
+ });
+
const mockToggleScreenShare = vi.fn();
const defaultProps: ScreenShareButtonProps = {
@@ -41,4 +56,10 @@ describe('ScreenSharingButton', () => {
)
).toBeInTheDocument();
});
+
+ it('does not show the button when the button is configured to be hidden', () => {
+ mockConfigContext.meetingRoomSettings.showScreenShareButton = false;
+ render();
+ expect(screen.queryByTestId('ScreenShareIcon')).not.toBeInTheDocument();
+ });
});
diff --git a/frontend/src/components/ScreenSharingButton/ScreenSharingButton.tsx b/frontend/src/components/ScreenSharingButton/ScreenSharingButton.tsx
index dfb4a8c3..1aac1444 100644
--- a/frontend/src/components/ScreenSharingButton/ScreenSharingButton.tsx
+++ b/frontend/src/components/ScreenSharingButton/ScreenSharingButton.tsx
@@ -5,6 +5,7 @@ import { ReactElement, useState } from 'react';
import ToolbarButton from '../MeetingRoom/ToolbarButton';
import PopupDialog, { DialogTexts } from '../MeetingRoom/PopupDialog';
import { isMobile } from '../../utils/util';
+import useConfigContext from '../../hooks/useConfigContext';
export type ScreenShareButtonProps = {
toggleScreenShare: () => void;
@@ -30,6 +31,7 @@ const ScreenSharingButton = ({
isViewingScreenShare,
isOverflowButton = false,
}: ScreenShareButtonProps): ReactElement | false => {
+ const { meetingRoomSettings } = useConfigContext();
const title = isSharingScreen ? 'Stop screen share' : 'Start screen share';
const [isModalOpen, setIsModalOpen] = useState(false);
@@ -56,7 +58,8 @@ const ScreenSharingButton = ({
return (
// Screensharing relies on the getDisplayMedia browser API which is unsupported on mobile devices
// See: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getDisplayMedia#browser_compatibility
- !isMobile() && (
+ !isMobile() &&
+ meetingRoomSettings.showScreenShareButton && (
<>
{
meetingRoomSettings: {
layoutMode: 'active-speaker',
showChat: true,
+ showScreenShareButton: true,
},
}),
};
From 83808773548cdfb54bbe83b33ee6b6f6bb2af56a Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Wed, 17 Sep 2025 13:16:36 -0700
Subject: [PATCH 35/58] archiving button. layoutMode --> defaultLayoutMode
---
config.example.json | 3 +-
.../useConfig/useConfig.spec.tsx | 6 ++-
.../ConfigProvider/useConfig/useConfig.tsx | 6 ++-
.../Context/SessionProvider/session.spec.tsx | 2 +-
.../src/Context/SessionProvider/session.tsx | 4 +-
.../ArchivingButton/ArchivingButton.spec.tsx | 22 ++++++++
.../ArchivingButton/ArchivingButton.tsx | 52 ++++++++++---------
.../pages/MeetingRoom/MeetingRoom.spec.tsx | 3 +-
8 files changed, 66 insertions(+), 32 deletions(-)
diff --git a/config.example.json b/config.example.json
index ee253e74..e2f00318 100644
--- a/config.example.json
+++ b/config.example.json
@@ -17,6 +17,7 @@
"layoutMode": "active-speaker",
"showParticipantList": true,
"showChat": true,
- "showScreenShareButton": true
+ "showScreenShareButton": true,
+ "showArchiveButton": true
}
}
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index f95b99e3..02988f09 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -20,10 +20,11 @@ describe('useConfig', () => {
allowDeviceSelection: true,
},
meetingRoomSettings: {
- layoutMode: 'active-speaker',
+ defaultLayoutMode: 'active-speaker',
showParticipantList: true,
showChat: true,
showScreenShareButton: true,
+ showArchiveButton: true,
},
};
@@ -70,10 +71,11 @@ describe('useConfig', () => {
allowDeviceSelection: false,
},
meetingRoomSettings: {
- layoutMode: 'grid',
+ defaultLayoutMode: 'grid',
showParticipantList: false,
showChat: false,
showScreenShareButton: false,
+ showArchiveButton: false,
},
};
global.fetch = vi.fn().mockResolvedValue({
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index 69e523b9..d85096d8 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -19,10 +19,11 @@ export type WaitingRoomSettings = {
};
export type MeetingRoomSettings = {
- layoutMode: LayoutMode;
+ defaultLayoutMode: LayoutMode;
showParticipantList: boolean;
showChat: boolean;
showScreenShareButton: boolean;
+ showArchiveButton: boolean;
};
export type AppConfig = {
@@ -48,10 +49,11 @@ export const defaultConfig: AppConfig = {
allowDeviceSelection: true,
},
meetingRoomSettings: {
- layoutMode: 'active-speaker',
+ defaultLayoutMode: 'active-speaker',
showParticipantList: true,
showChat: true,
showScreenShareButton: true,
+ showArchiveButton: true,
},
};
diff --git a/frontend/src/Context/SessionProvider/session.spec.tsx b/frontend/src/Context/SessionProvider/session.spec.tsx
index 0018de4c..51a6ef99 100644
--- a/frontend/src/Context/SessionProvider/session.spec.tsx
+++ b/frontend/src/Context/SessionProvider/session.spec.tsx
@@ -24,7 +24,7 @@ vi.mock('../../hooks/useConfigContext', () => {
return {
default: () => ({
meetingRoomSettings: {
- layoutMode: 'active-speaker',
+ defaultLayoutMode: 'active-speaker',
},
}),
};
diff --git a/frontend/src/Context/SessionProvider/session.tsx b/frontend/src/Context/SessionProvider/session.tsx
index 9726c386..0cc7e7cf 100644
--- a/frontend/src/Context/SessionProvider/session.tsx
+++ b/frontend/src/Context/SessionProvider/session.tsx
@@ -134,7 +134,9 @@ const SessionProvider = ({ children }: SessionProviderProps): ReactElement => {
const [reconnecting, setReconnecting] = useState(false);
const [subscriberWrappers, setSubscriberWrappers] = useState([]);
const [ownCaptions, setOwnCaptions] = useState(null);
- const [layoutMode, setLayoutMode] = useState(config.meetingRoomSettings.layoutMode);
+ const [layoutMode, setLayoutMode] = useState(
+ config.meetingRoomSettings.defaultLayoutMode
+ );
const [archiveId, setArchiveId] = useState(null);
const activeSpeakerTracker = useRef(new ActiveSpeakerTracker());
const [activeSpeakerId, setActiveSpeakerId] = useState();
diff --git a/frontend/src/components/MeetingRoom/ArchivingButton/ArchivingButton.spec.tsx b/frontend/src/components/MeetingRoom/ArchivingButton/ArchivingButton.spec.tsx
index 1a6dea53..7d36758c 100644
--- a/frontend/src/components/MeetingRoom/ArchivingButton/ArchivingButton.spec.tsx
+++ b/frontend/src/components/MeetingRoom/ArchivingButton/ArchivingButton.spec.tsx
@@ -5,9 +5,12 @@ import ArchivingButton from './ArchivingButton';
import useRoomName from '../../../hooks/useRoomName';
import useSessionContext from '../../../hooks/useSessionContext';
import { SessionContextType } from '../../../Context/SessionProvider/session';
+import useConfigContext from '../../../hooks/useConfigContext';
+import { ConfigContextType } from '../../../Context/ConfigProvider';
vi.mock('../../../hooks/useSessionContext');
vi.mock('../../../hooks/useRoomName');
+vi.mock('../../../hooks/useConfigContext');
vi.mock('../../../api/archiving', () => ({
startArchiving: vi.fn(),
@@ -18,8 +21,10 @@ describe('ArchivingButton', () => {
const mockHandleCloseMenu = vi.fn();
const mockedRoomName = 'test-room-name';
let sessionContext: SessionContextType;
+ let configContext: ConfigContextType;
const mockUseSessionContext = useSessionContext as Mock<[], SessionContextType>;
+ const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
const testArchiveId = 'test-archive-id';
beforeEach(() => {
@@ -29,8 +34,14 @@ describe('ArchivingButton', () => {
subscriberWrappers: [],
archiveId: null,
} as unknown as SessionContextType;
+ configContext = {
+ meetingRoomSettings: {
+ showArchiveButton: true,
+ },
+ } as unknown as ConfigContextType;
mockUseSessionContext.mockReturnValue(sessionContext as unknown as SessionContextType);
+ mockUseConfigContext.mockReturnValue(configContext);
});
it('renders the button correctly', () => {
@@ -86,4 +97,15 @@ describe('ArchivingButton', () => {
expect(stopArchiving).toHaveBeenCalledWith(mockedRoomName, testArchiveId);
});
});
+
+ it('is not displayed when archiving is disabled', () => {
+ mockUseConfigContext.mockReturnValue({
+ meetingRoomSettings: {
+ showArchiveButton: false,
+ },
+ } as unknown as ConfigContextType);
+
+ render();
+ expect(screen.queryByTestId('archiving-button')).not.toBeInTheDocument();
+ });
});
diff --git a/frontend/src/components/MeetingRoom/ArchivingButton/ArchivingButton.tsx b/frontend/src/components/MeetingRoom/ArchivingButton/ArchivingButton.tsx
index 09dd07cc..b739f886 100644
--- a/frontend/src/components/MeetingRoom/ArchivingButton/ArchivingButton.tsx
+++ b/frontend/src/components/MeetingRoom/ArchivingButton/ArchivingButton.tsx
@@ -6,6 +6,7 @@ import ToolbarButton from '../ToolbarButton';
import PopupDialog, { DialogTexts } from '../PopupDialog';
import { startArchiving, stopArchiving } from '../../../api/archiving';
import useSessionContext from '../../../hooks/useSessionContext';
+import useConfigContext from '../../../hooks/useConfigContext';
export type ArchivingButtonProps = {
isOverflowButton?: boolean;
@@ -21,14 +22,15 @@ export type ArchivingButtonProps = {
* @param {ArchivingButtonProps} props - the props for the component
* @property {boolean} isOverflowButton - (optional) whether the button is in the ToolbarOverflowMenu
* @property {(event?: MouseEvent | TouchEvent) => void} handleClick - (optional) click handler that closes the overflow menu in small viewports.
- * @returns {ReactElement} - The ArchivingButton component.
+ * @returns {ReactElement | false} - The ArchivingButton component.
*/
const ArchivingButton = ({
isOverflowButton = false,
handleClick,
-}: ArchivingButtonProps): ReactElement => {
+}: ArchivingButtonProps): ReactElement | false => {
const roomName = useRoomName();
const { archiveId } = useSessionContext();
+ const { meetingRoomSettings } = useConfigContext();
const isRecording = !!archiveId;
const [isModalOpen, setIsModalOpen] = useState(false);
const title = isRecording ? 'Stop recording' : 'Start recording';
@@ -82,29 +84,31 @@ const ArchivingButton = ({
};
return (
- <>
-
-
- }
- sx={{
- marginTop: isOverflowButton ? '0px' : '4px',
- }}
- isOverflowButton={isOverflowButton}
+ meetingRoomSettings.showArchiveButton && (
+ <>
+
+
+ }
+ sx={{
+ marginTop: isOverflowButton ? '0px' : '4px',
+ }}
+ isOverflowButton={isOverflowButton}
+ />
+
+
-
-
- >
+ >
+ )
);
};
export default ArchivingButton;
diff --git a/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx b/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
index 0ffab32d..b37fa18d 100644
--- a/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
+++ b/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
@@ -64,9 +64,10 @@ vi.mock('../../hooks/useConfigContext', () => {
enableDisableCapableMicrophone: true,
},
meetingRoomSettings: {
- layoutMode: 'active-speaker',
+ defaultLayoutMode: 'active-speaker',
showChat: true,
showScreenShareButton: true,
+ showArchiveButton: true,
},
}),
};
From 1c2660d58765203383540a41b3d11e8c3279531a Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Wed, 17 Sep 2025 13:22:22 -0700
Subject: [PATCH 36/58] captions button
---
config.example.json | 3 +-
.../useConfig/useConfig.spec.tsx | 2 +
.../ConfigProvider/useConfig/useConfig.tsx | 2 +
.../CaptionsButton/CaptionsButton.spec.tsx | 21 ++++++++
.../CaptionsButton/CaptionsButton.tsx | 50 ++++++++++---------
.../pages/MeetingRoom/MeetingRoom.spec.tsx | 1 +
6 files changed, 55 insertions(+), 24 deletions(-)
diff --git a/config.example.json b/config.example.json
index e2f00318..74161875 100644
--- a/config.example.json
+++ b/config.example.json
@@ -18,6 +18,7 @@
"showParticipantList": true,
"showChat": true,
"showScreenShareButton": true,
- "showArchiveButton": true
+ "showArchiveButton": true,
+ "showCaptionsButton": true
}
}
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index 02988f09..f9f86744 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -25,6 +25,7 @@ describe('useConfig', () => {
showChat: true,
showScreenShareButton: true,
showArchiveButton: true,
+ showCaptionsButton: true,
},
};
@@ -76,6 +77,7 @@ describe('useConfig', () => {
showChat: false,
showScreenShareButton: false,
showArchiveButton: false,
+ showCaptionsButton: false,
},
};
global.fetch = vi.fn().mockResolvedValue({
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index d85096d8..e27e71d4 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -24,6 +24,7 @@ export type MeetingRoomSettings = {
showChat: boolean;
showScreenShareButton: boolean;
showArchiveButton: boolean;
+ showCaptionsButton: boolean;
};
export type AppConfig = {
@@ -54,6 +55,7 @@ export const defaultConfig: AppConfig = {
showChat: true,
showScreenShareButton: true,
showArchiveButton: true,
+ showCaptionsButton: true,
},
};
diff --git a/frontend/src/components/MeetingRoom/CaptionsButton/CaptionsButton.spec.tsx b/frontend/src/components/MeetingRoom/CaptionsButton/CaptionsButton.spec.tsx
index 9af29f98..78e1997f 100644
--- a/frontend/src/components/MeetingRoom/CaptionsButton/CaptionsButton.spec.tsx
+++ b/frontend/src/components/MeetingRoom/CaptionsButton/CaptionsButton.spec.tsx
@@ -8,6 +8,8 @@ import useRoomName from '../../../hooks/useRoomName';
import { SessionContextType } from '../../../Context/SessionProvider/session';
import useSessionContext from '../../../hooks/useSessionContext';
import { SubscriberWrapper } from '../../../types/session';
+import useConfigContext from '../../../hooks/useConfigContext';
+import { ConfigContextType } from '../../../Context/ConfigProvider';
vi.mock('../../../hooks/useSessionContext');
vi.mock('../../../hooks/useRoomName');
@@ -15,8 +17,10 @@ vi.mock('../../../api/captions', () => ({
enableCaptions: vi.fn(),
disableCaptions: vi.fn(),
}));
+vi.mock('../../../hooks/useConfigContext');
const mockUseSessionContext = useSessionContext as Mock<[], SessionContextType>;
+const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
describe('CaptionsButton', () => {
const mockHandleCloseMenu = vi.fn();
@@ -30,6 +34,7 @@ describe('CaptionsButton', () => {
} as CaptionsState;
const mockedRoomName = 'test-room-name';
let sessionContext: SessionContextType;
+ let configContext: ConfigContextType;
const createSubscriberWrapper = (id: string): SubscriberWrapper => {
const mockSubscriber = {
@@ -64,7 +69,13 @@ describe('CaptionsButton', () => {
sessionContext = {
subscriberWrappers: [createSubscriberWrapper('subscriber-1')],
} as unknown as SessionContextType;
+ configContext = {
+ meetingRoomSettings: {
+ showCaptionsButton: true,
+ },
+ } as unknown as ConfigContextType;
mockUseSessionContext.mockReturnValue(sessionContext as unknown as SessionContextType);
+ mockUseConfigContext.mockReturnValue(configContext);
});
it('renders the button correctly', () => {
@@ -85,4 +96,14 @@ describe('CaptionsButton', () => {
expect(enableCaptions).toHaveBeenCalledWith(mockedRoomName);
});
});
+
+ it('is not displayed when configured to be disabled', () => {
+ mockUseConfigContext.mockReturnValue({
+ meetingRoomSettings: {
+ showCaptionsButton: false,
+ },
+ } as unknown as ConfigContextType);
+ render();
+ expect(screen.queryByTestId('captions-button')).not.toBeInTheDocument();
+ });
});
diff --git a/frontend/src/components/MeetingRoom/CaptionsButton/CaptionsButton.tsx b/frontend/src/components/MeetingRoom/CaptionsButton/CaptionsButton.tsx
index 16f33624..0c6f8b0c 100644
--- a/frontend/src/components/MeetingRoom/CaptionsButton/CaptionsButton.tsx
+++ b/frontend/src/components/MeetingRoom/CaptionsButton/CaptionsButton.tsx
@@ -5,6 +5,7 @@ import { AxiosError } from 'axios';
import useRoomName from '../../../hooks/useRoomName';
import ToolbarButton from '../ToolbarButton';
import { disableCaptions, enableCaptions } from '../../../api/captions';
+import useConfigContext from '../../../hooks/useConfigContext';
export type CaptionsState = {
isUserCaptionsEnabled: boolean;
@@ -26,13 +27,14 @@ export type CaptionsButtonProps = {
* @property {boolean} isOverflowButton - (optional) whether the button is in the ToolbarOverflowMenu
* @property {(event?: MouseEvent | TouchEvent) => void} handleClick - (optional) click handler that closes the overflow menu in small viewports.
* @property {CaptionsState} captionsState - the state of the captions, including whether they are enabled and functions to set error messages
- * @returns {ReactElement} - The CaptionsButton component.
+ * @returns {ReactElement | false} - The CaptionsButton component.
*/
const CaptionsButton = ({
isOverflowButton = false,
handleClick,
captionsState,
-}: CaptionsButtonProps): ReactElement => {
+}: CaptionsButtonProps): ReactElement | false => {
+ const { meetingRoomSettings } = useConfigContext();
const roomName = useRoomName();
const [captionsId, setCaptionsId] = useState('');
const { isUserCaptionsEnabled, setIsUserCaptionsEnabled, setCaptionsErrorResponse } =
@@ -91,27 +93,29 @@ const CaptionsButton = ({
};
return (
-
-
- ) : (
-
- )
- }
- sx={{
- marginTop: isOverflowButton ? '0px' : '4px',
- }}
- isOverflowButton={isOverflowButton}
- />
-
+ meetingRoomSettings.showCaptionsButton && (
+
+
+ ) : (
+
+ )
+ }
+ sx={{
+ marginTop: isOverflowButton ? '0px' : '4px',
+ }}
+ isOverflowButton={isOverflowButton}
+ />
+
+ )
);
};
export default CaptionsButton;
diff --git a/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx b/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
index b37fa18d..bdfc266e 100644
--- a/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
+++ b/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
@@ -68,6 +68,7 @@ vi.mock('../../hooks/useConfigContext', () => {
showChat: true,
showScreenShareButton: true,
showArchiveButton: true,
+ showCaptionsButton: true,
},
}),
};
From 7f6e5c04a9f3237191629fc38b2b5176dc5f81ed Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Wed, 17 Sep 2025 13:32:49 -0700
Subject: [PATCH 37/58] showemoji
---
config.example.json | 3 +-
.../useConfig/useConfig.spec.tsx | 2 +
.../ConfigProvider/useConfig/useConfig.tsx | 2 +
.../EmojiGridButton/EmojiGridButton.spec.tsx | 19 +++++++
.../EmojiGridButton/EmojiGridButton.tsx | 56 ++++++++++---------
.../pages/MeetingRoom/MeetingRoom.spec.tsx | 2 +
6 files changed, 57 insertions(+), 27 deletions(-)
diff --git a/config.example.json b/config.example.json
index 74161875..171a6fea 100644
--- a/config.example.json
+++ b/config.example.json
@@ -19,6 +19,7 @@
"showChat": true,
"showScreenShareButton": true,
"showArchiveButton": true,
- "showCaptionsButton": true
+ "showCaptionsButton": true,
+ "showEmojiButton": true
}
}
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index f9f86744..be086682 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -26,6 +26,7 @@ describe('useConfig', () => {
showScreenShareButton: true,
showArchiveButton: true,
showCaptionsButton: true,
+ showEmojiButton: true,
},
};
@@ -78,6 +79,7 @@ describe('useConfig', () => {
showScreenShareButton: false,
showArchiveButton: false,
showCaptionsButton: false,
+ showEmojiButton: false,
},
};
global.fetch = vi.fn().mockResolvedValue({
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index e27e71d4..ba8e195a 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -25,6 +25,7 @@ export type MeetingRoomSettings = {
showScreenShareButton: boolean;
showArchiveButton: boolean;
showCaptionsButton: boolean;
+ showEmojiButton: boolean;
};
export type AppConfig = {
@@ -56,6 +57,7 @@ export const defaultConfig: AppConfig = {
showScreenShareButton: true,
showArchiveButton: true,
showCaptionsButton: true,
+ showEmojiButton: true,
},
};
diff --git a/frontend/src/components/MeetingRoom/EmojiGridButton/EmojiGridButton.spec.tsx b/frontend/src/components/MeetingRoom/EmojiGridButton/EmojiGridButton.spec.tsx
index afd36985..6deeee33 100644
--- a/frontend/src/components/MeetingRoom/EmojiGridButton/EmojiGridButton.spec.tsx
+++ b/frontend/src/components/MeetingRoom/EmojiGridButton/EmojiGridButton.spec.tsx
@@ -3,6 +3,8 @@ import { afterEach, beforeEach, describe, expect, it, vi, Mock } from 'vitest';
import { useState } from 'react';
import * as mui from '@mui/material';
import EmojiGridButton from './EmojiGridButton';
+import useConfigContext from '../../../hooks/useConfigContext';
+import { ConfigContextType } from '../../../Context/ConfigProvider';
vi.mock('@mui/material', async () => {
const actual = await vi.importActual('@mui/material');
@@ -14,6 +16,9 @@ vi.mock('@mui/material', async () => {
vi.mock('../../../utils/emojis', () => ({
default: { FAVORITE: '🦧' },
}));
+vi.mock('../../../hooks/useConfigContext');
+
+const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
const TestComponent = ({ defaultOpenEmojiGrid = false }: { defaultOpenEmojiGrid?: boolean }) => {
const [isEmojiGridOpen, setIsEmojiGridOpen] = useState(defaultOpenEmojiGrid);
@@ -27,8 +32,16 @@ const TestComponent = ({ defaultOpenEmojiGrid = false }: { defaultOpenEmojiGrid?
};
describe('EmojiGridButton', () => {
+ let mockConfigContext: ConfigContextType;
+
beforeEach(() => {
(mui.useMediaQuery as Mock).mockReturnValue(false);
+ mockConfigContext = {
+ meetingRoomSettings: {
+ showEmojiButton: true,
+ },
+ } as unknown as ConfigContextType;
+ mockUseConfigContext.mockReturnValue(mockConfigContext);
});
afterEach(() => {
@@ -52,4 +65,10 @@ describe('EmojiGridButton', () => {
rerender();
expect(screen.getByTestId('emoji-grid')).toBeVisible();
});
+
+ it('is not displayed when configured to be hidden', () => {
+ mockConfigContext.meetingRoomSettings.showEmojiButton = false;
+ render();
+ expect(screen.queryByTestId('emoji-grid-button')).not.toBeInTheDocument();
+ });
});
diff --git a/frontend/src/components/MeetingRoom/EmojiGridButton/EmojiGridButton.tsx b/frontend/src/components/MeetingRoom/EmojiGridButton/EmojiGridButton.tsx
index 7ff24378..03046c67 100644
--- a/frontend/src/components/MeetingRoom/EmojiGridButton/EmojiGridButton.tsx
+++ b/frontend/src/components/MeetingRoom/EmojiGridButton/EmojiGridButton.tsx
@@ -3,6 +3,7 @@ import { EmojiEmotions } from '@mui/icons-material';
import { Dispatch, ReactElement, SetStateAction, useRef } from 'react';
import ToolbarButton from '../ToolbarButton';
import EmojiGrid from '../EmojiGrid/EmojiGrid';
+import useConfigContext from '../../../hooks/useConfigContext';
export type EmojiGridProps = {
isEmojiGridOpen: boolean;
@@ -20,45 +21,48 @@ export type EmojiGridProps = {
* @property {Dispatch>} setIsEmojiGridOpen - toggle whether the emoji grid is shown or hidden
* @property {boolean} isParentOpen - whether the ToolbarOverflowMenu is open
* @property {boolean} isOverflowButton - (optional) whether the button is in the ToolbarOverflowMenu
- * @returns {ReactElement} - The EmojiGridButton Component.
+ * @returns {ReactElement | false} - The EmojiGridButton Component.
*/
const EmojiGridButton = ({
isEmojiGridOpen,
setIsEmojiGridOpen,
isParentOpen,
isOverflowButton = false,
-}: EmojiGridProps): ReactElement => {
+}: EmojiGridProps): ReactElement | false => {
+ const { meetingRoomSettings } = useConfigContext();
const anchorRef = useRef(null);
const handleToggle = () => {
setIsEmojiGridOpen((prevOpen) => !prevOpen);
};
return (
- <>
-
-
- }
- ref={anchorRef}
- data-testid="emoji-grid-button"
- sx={{
- marginTop: isOverflowButton ? '0px' : '4px',
- }}
- isOverflowButton={isOverflowButton}
- />
-
+ meetingRoomSettings.showEmojiButton && (
+ <>
+
+
+ }
+ ref={anchorRef}
+ data-testid="emoji-grid-button"
+ sx={{
+ marginTop: isOverflowButton ? '0px' : '4px',
+ }}
+ isOverflowButton={isOverflowButton}
+ />
+
-
- >
+
+ >
+ )
);
};
diff --git a/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx b/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
index bdfc266e..87a97017 100644
--- a/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
+++ b/frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx
@@ -65,10 +65,12 @@ vi.mock('../../hooks/useConfigContext', () => {
},
meetingRoomSettings: {
defaultLayoutMode: 'active-speaker',
+ showParticipantList: true,
showChat: true,
showScreenShareButton: true,
showArchiveButton: true,
showCaptionsButton: true,
+ showEmojiButton: true,
},
}),
};
From 70f83690fef86f9ba40884df61638fb30264300d Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Wed, 17 Sep 2025 13:35:23 -0700
Subject: [PATCH 38/58] rename some flags
---
config.example.json | 10 +++++-----
.../ConfigProvider/useConfig/useConfig.spec.tsx | 8 ++++----
.../src/Context/ConfigProvider/useConfig/useConfig.tsx | 10 +++++-----
.../MeetingRoom/ChatButton/ChatButton.spec.tsx | 4 ++--
.../components/MeetingRoom/ChatButton/ChatButton.tsx | 2 +-
.../ParticipantListButton/ParticipantListButton.tsx | 2 +-
.../ParticipantsListButton.spec.tsx | 6 +++---
.../UnreadMessagesBadge/UnreadMessagesBadge.spec.tsx | 4 ++--
.../UnreadMessagesBadge/UnreadMessagesBadge.tsx | 2 +-
frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx | 4 ++--
10 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/config.example.json b/config.example.json
index 171a6fea..8b90467b 100644
--- a/config.example.json
+++ b/config.example.json
@@ -14,12 +14,12 @@
"allowDeviceSelection": true
},
"meetingRoomSettings": {
- "layoutMode": "active-speaker",
- "showParticipantList": true,
- "showChat": true,
- "showScreenShareButton": true,
+ "defaultLayoutMode": "active-speaker",
"showArchiveButton": true,
"showCaptionsButton": true,
- "showEmojiButton": true
+ "showChatButton": true,
+ "showEmojiButton": true,
+ "showParticipantListButton": true,
+ "showScreenShareButton": true
}
}
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index be086682..b3d6675f 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -21,8 +21,8 @@ describe('useConfig', () => {
},
meetingRoomSettings: {
defaultLayoutMode: 'active-speaker',
- showParticipantList: true,
- showChat: true,
+ showParticipantListButton: true,
+ showChatButton: true,
showScreenShareButton: true,
showArchiveButton: true,
showCaptionsButton: true,
@@ -74,8 +74,8 @@ describe('useConfig', () => {
},
meetingRoomSettings: {
defaultLayoutMode: 'grid',
- showParticipantList: false,
- showChat: false,
+ showParticipantListButton: false,
+ showChatButton: false,
showScreenShareButton: false,
showArchiveButton: false,
showCaptionsButton: false,
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index ba8e195a..3be47b5f 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -20,12 +20,12 @@ export type WaitingRoomSettings = {
export type MeetingRoomSettings = {
defaultLayoutMode: LayoutMode;
- showParticipantList: boolean;
- showChat: boolean;
- showScreenShareButton: boolean;
showArchiveButton: boolean;
showCaptionsButton: boolean;
+ showChatButton: boolean;
showEmojiButton: boolean;
+ showParticipantListButton: boolean;
+ showScreenShareButton: boolean;
};
export type AppConfig = {
@@ -52,8 +52,8 @@ export const defaultConfig: AppConfig = {
},
meetingRoomSettings: {
defaultLayoutMode: 'active-speaker',
- showParticipantList: true,
- showChat: true,
+ showParticipantListButton: true,
+ showChatButton: true,
showScreenShareButton: true,
showArchiveButton: true,
showCaptionsButton: true,
diff --git a/frontend/src/components/MeetingRoom/ChatButton/ChatButton.spec.tsx b/frontend/src/components/MeetingRoom/ChatButton/ChatButton.spec.tsx
index fbcd8ea3..3fd55651 100644
--- a/frontend/src/components/MeetingRoom/ChatButton/ChatButton.spec.tsx
+++ b/frontend/src/components/MeetingRoom/ChatButton/ChatButton.spec.tsx
@@ -14,7 +14,7 @@ const sessionContext = {
} as unknown as SessionContextType;
const mockConfigContext = {
meetingRoomSettings: {
- showChat: true,
+ showChatButton: true,
},
} as unknown as ConfigContextType;
const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
@@ -65,7 +65,7 @@ describe('ChatButton', () => {
it('should not be displayed when chat is disabled', () => {
mockUseConfigContext.mockReturnValue({
meetingRoomSettings: {
- showChat: false,
+ showChatButton: false,
},
} as unknown as ConfigContextType);
render( {}} isOpen />);
diff --git a/frontend/src/components/MeetingRoom/ChatButton/ChatButton.tsx b/frontend/src/components/MeetingRoom/ChatButton/ChatButton.tsx
index d2feeea7..1cd73b87 100644
--- a/frontend/src/components/MeetingRoom/ChatButton/ChatButton.tsx
+++ b/frontend/src/components/MeetingRoom/ChatButton/ChatButton.tsx
@@ -31,7 +31,7 @@ const ChatButton = ({
const { meetingRoomSettings } = useConfigContext();
return (
- meetingRoomSettings.showChat && (
+ meetingRoomSettings.showChatButton && (
{
beforeEach(() => {
mockUseConfigContext.mockReturnValue({
meetingRoomSettings: {
- showParticipantList: true,
+ showParticipantListButton: true,
},
} as unknown as ConfigContextType);
});
@@ -35,10 +35,10 @@ describe('ParticipantListButton', () => {
screen.getByRole('button').click();
expect(handleClick).toHaveBeenCalled();
});
- it('should not render if showParticipantList is false in config', () => {
+ it('should not render if showParticipantListButton is false in config', () => {
mockUseConfigContext.mockReturnValue({
meetingRoomSettings: {
- showParticipantList: false,
+ showParticipantListButton: false,
},
} as unknown as ConfigContextType);
render( {}} isOpen={false} participantCount={10} />);
diff --git a/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.spec.tsx b/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.spec.tsx
index c14360a9..2707dd65 100644
--- a/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.spec.tsx
+++ b/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.spec.tsx
@@ -17,7 +17,7 @@ const sessionContext = {
const LittleButton = () => {}} icon={} />;
const mockConfigContext = {
meetingRoomSettings: {
- showChat: true,
+ showChatButton: true,
},
} as unknown as ConfigContextType;
const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
@@ -179,7 +179,7 @@ describe('UnreadMessagesBadge', () => {
mockUseSessionContext.mockReturnValue(sessionContextWithMessages);
mockUseConfigContext.mockReturnValue({
meetingRoomSettings: {
- showChat: false,
+ showChatButton: false,
},
} as unknown as ConfigContextType);
diff --git a/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.tsx b/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.tsx
index 62b6a642..931c449b 100644
--- a/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.tsx
+++ b/frontend/src/components/MeetingRoom/UnreadMessagesBadge/UnreadMessagesBadge.tsx
@@ -25,7 +25,7 @@ const UnreadMessagesBadge = forwardRef(function UnreadMessagesBadge(
const { children, isToolbarOverflowMenuOpen, ...rest } = props;
const { unreadCount } = useSessionContext();
const isInvisible =
- unreadCount === 0 || isToolbarOverflowMenuOpen || !meetingRoomSettings.showChat;
+ unreadCount === 0 || isToolbarOverflowMenuOpen || !meetingRoomSettings.showChatButton;
return (
{
},
meetingRoomSettings: {
defaultLayoutMode: 'active-speaker',
- showParticipantList: true,
- showChat: true,
+ showParticipantListButton: true,
+ showChatButton: true,
showScreenShareButton: true,
showArchiveButton: true,
showCaptionsButton: true,
From 28011403de70463cfc8566987574b8e012b43a14 Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Wed, 17 Sep 2025 14:43:16 -0700
Subject: [PATCH 39/58] renaming
---
config.example.json | 8 +++----
.../useConfig/useConfig.spec.tsx | 16 ++++++-------
.../ConfigProvider/useConfig/useConfig.tsx | 23 ++++++++++++-------
.../usePreviewPublisher.tsx | 4 ++--
.../usePublisherOptions.spec.tsx | 14 +++++------
.../usePublisherOptions.tsx | 8 +++----
.../DeviceControlButton.spec.tsx | 4 ++--
.../DeviceControlButton.tsx | 8 +++----
.../DeviceSettingsMenu.spec.tsx | 6 ++---
.../DeviceSettingsMenu/DeviceSettingsMenu.tsx | 2 +-
.../CameraButton/CameraButton.spec.tsx | 2 +-
.../WaitingRoom/CameraButton/CameraButton.tsx | 4 ++--
.../pages/MeetingRoom/MeetingRoom.spec.tsx | 2 +-
13 files changed, 54 insertions(+), 47 deletions(-)
diff --git a/config.example.json b/config.example.json
index 8b90467b..4f54f53e 100644
--- a/config.example.json
+++ b/config.example.json
@@ -1,9 +1,9 @@
{
"videoSettings": {
- "backgroundEffects": true,
- "enableDisableCapableCamera": true,
- "resolution": "1280x720",
- "videoOnJoin": true
+ "allowBackgroundEffects": true,
+ "allowCameraControl": true,
+ "allowVideoOnJoin": true,
+ "defaultResolution": "1280x720"
},
"audioSettings": {
"advancedNoiseSuppression": true,
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index b3d6675f..f0b853bb 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -6,10 +6,10 @@ describe('useConfig', () => {
let nativeFetch: typeof global.fetch;
const defaultConfig: AppConfig = {
videoSettings: {
- enableDisableCapableCamera: true,
- resolution: '1280x720',
- videoOnJoin: true,
- backgroundEffects: true,
+ allowCameraControl: true,
+ defaultResolution: '1280x720',
+ allowVideoOnJoin: true,
+ allowBackgroundEffects: true,
},
audioSettings: {
advancedNoiseSuppression: true,
@@ -59,10 +59,10 @@ describe('useConfig', () => {
it('merges config.json values if loaded (mocked fetch)', async () => {
const mockConfig: AppConfig = {
videoSettings: {
- enableDisableCapableCamera: false,
- resolution: '640x480',
- videoOnJoin: false,
- backgroundEffects: false,
+ allowCameraControl: false,
+ defaultResolution: '640x480',
+ allowVideoOnJoin: false,
+ allowBackgroundEffects: false,
},
audioSettings: {
advancedNoiseSuppression: false,
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index 3be47b5f..795e8ada 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -2,10 +2,17 @@ import { useMemo, useEffect, useState } from 'react';
import { LayoutMode } from '../../../types/session';
export type VideoSettings = {
- enableDisableCapableCamera: boolean;
- resolution: '1920x1080' | '1280x960' | '1280x720' | '640x480' | '640x360' | '320x240' | '320x180';
- videoOnJoin: boolean;
- backgroundEffects: boolean;
+ allowBackgroundEffects: boolean;
+ allowCameraControl: boolean;
+ allowVideoOnJoin: boolean;
+ defaultResolution:
+ | '1920x1080'
+ | '1280x960'
+ | '1280x720'
+ | '640x480'
+ | '640x360'
+ | '320x240'
+ | '320x180';
};
export type AudioSettings = {
@@ -37,10 +44,10 @@ export type AppConfig = {
export const defaultConfig: AppConfig = {
videoSettings: {
- enableDisableCapableCamera: true,
- resolution: '1280x720',
- videoOnJoin: true,
- backgroundEffects: true,
+ allowBackgroundEffects: true,
+ allowCameraControl: true,
+ allowVideoOnJoin: true,
+ defaultResolution: '1280x720',
},
audioSettings: {
advancedNoiseSuppression: true,
diff --git a/frontend/src/Context/PreviewPublisherProvider/usePreviewPublisher/usePreviewPublisher.tsx b/frontend/src/Context/PreviewPublisherProvider/usePreviewPublisher/usePreviewPublisher.tsx
index 9ac49c67..ed9abd11 100644
--- a/frontend/src/Context/PreviewPublisherProvider/usePreviewPublisher/usePreviewPublisher.tsx
+++ b/frontend/src/Context/PreviewPublisherProvider/usePreviewPublisher/usePreviewPublisher.tsx
@@ -242,7 +242,7 @@ const usePreviewPublisher = (): PreviewPublisherContextType => {
const publisherOptions: PublisherProperties = {
insertDefaultUI: false,
videoFilter,
- resolution: config.videoSettings.resolution,
+ resolution: config.videoSettings.defaultResolution,
audioSource,
videoSource,
};
@@ -256,7 +256,7 @@ const usePreviewPublisher = (): PreviewPublisherContextType => {
}
});
addPublisherListeners(publisherRef.current);
- }, [addPublisherListeners, config.videoSettings.resolution]);
+ }, [addPublisherListeners, config.videoSettings.defaultResolution]);
/**
* Destroys the preview publisher
diff --git a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx
index d2d5a383..0539b0f8 100644
--- a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx
+++ b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx
@@ -76,8 +76,8 @@ describe('usePublisherOptions', () => {
audioOnJoin: true,
},
videoSettings: {
- resolution: '1280x720',
- videoOnJoin: true,
+ defaultResolution: '1280x720',
+ allowVideoOnJoin: true,
},
} as unknown as ConfigContextType;
mockUseConfigContext.mockReturnValue(configContext);
@@ -93,7 +93,7 @@ describe('usePublisherOptions', () => {
const { result } = renderHook(() => usePublisherOptions());
await waitFor(() => {
expect(result.current).toEqual({
- resolution: '1280x720',
+ defaultResolution: '1280x720',
publishAudio: false,
publishVideo: false,
audioSource: undefined,
@@ -136,7 +136,7 @@ describe('usePublisherOptions', () => {
const { result } = renderHook(() => usePublisherOptions());
await waitFor(() => {
expect(result.current).toEqual({
- resolution: '1280x720',
+ defaultResolution: '1280x720',
publishAudio: true,
publishVideo: true,
audioSource: '68f1d1e6f11c629b1febe51a95f8f740f8ac5cd3d4c91419bd2b52bb1a9a01cd',
@@ -167,7 +167,7 @@ describe('usePublisherOptions', () => {
});
it('should disable video publishing', async () => {
- configContext.videoSettings.videoOnJoin = false;
+ configContext.videoSettings.allowVideoOnJoin = false;
const { result } = renderHook(() => usePublisherOptions());
await waitFor(() => {
expect(result.current?.publishVideo).toBe(false);
@@ -175,10 +175,10 @@ describe('usePublisherOptions', () => {
});
it('should configure resolution from config', async () => {
- configContext.videoSettings.resolution = '640x480';
+ configContext.videoSettings.defaultResolution = '640x480';
const { result } = renderHook(() => usePublisherOptions());
await waitFor(() => {
- expect(result.current?.resolution).toBe('640x480');
+ expect(result.current?.defaultResolution).toBe('640x480');
});
});
});
diff --git a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx
index b3bdeb9e..0d25bafb 100644
--- a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx
+++ b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx
@@ -56,8 +56,8 @@ const usePublisherOptions = (): PublisherProperties | null => {
insertDefaultUI: false,
name,
publishAudio: config.audioSettings.audioOnJoin && publishAudio,
- publishVideo: config.videoSettings.videoOnJoin && publishVideo,
- resolution: config.videoSettings.resolution,
+ publishVideo: config.videoSettings.allowVideoOnJoin && publishVideo,
+ resolution: config.videoSettings.defaultResolution,
audioFilter,
videoFilter,
videoSource,
@@ -68,8 +68,8 @@ const usePublisherOptions = (): PublisherProperties | null => {
setOptions();
}, [
config.audioSettings.audioOnJoin,
- config.videoSettings.resolution,
- config.videoSettings.videoOnJoin,
+ config.videoSettings.defaultResolution,
+ config.videoSettings.allowVideoOnJoin,
user.defaultSettings,
]);
diff --git a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.spec.tsx b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.spec.tsx
index 9c50c81b..7d4aae22 100644
--- a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.spec.tsx
+++ b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.spec.tsx
@@ -71,7 +71,7 @@ describe('DeviceControlButton', () => {
enableDisableCapableMicrophone: true,
},
videoSettings: {
- enableDisableCapableCamera: true,
+ allowCameraControl: true,
},
} as unknown as ConfigContextType;
mockUseConfigContext.mockReturnValue(configContext);
@@ -161,7 +161,7 @@ describe('DeviceControlButton', () => {
});
it('is not rendered when it is configured to be disabled', async () => {
- configContext.videoSettings.enableDisableCapableCamera = false;
+ configContext.videoSettings.allowCameraControl = false;
render(
;
}
- if (!enableDisableCapableCamera) {
+ if (!allowCameraControl) {
return ;
}
if (isVideoEnabled) {
diff --git a/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx b/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
index 2878b6cd..b31a01d3 100644
--- a/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
+++ b/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
@@ -90,10 +90,10 @@ describe('DeviceSettingsMenu Component', () => {
mockedHasMediaProcessorSupport.mockReturnValue(false);
configContext = {
audioSettings: {
- enableDisableCapableCamera: true,
+ allowCameraControl: true,
},
videoSettings: {
- backgroundEffects: true,
+ allowBackgroundEffects: true,
},
} as unknown as ConfigContextType;
mockUseConfigContext.mockReturnValue(configContext);
@@ -369,7 +369,7 @@ describe('DeviceSettingsMenu Component', () => {
it('does not render the dropdown separator and background effects option when the config has disabled background effects', async () => {
configContext = {
videoSettings: {
- backgroundEffects: false,
+ allowBackgroundEffects: false,
},
} as unknown as ConfigContextType;
mockUseConfigContext.mockReturnValue(configContext);
diff --git a/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.tsx b/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.tsx
index bd2920f0..6fb92296 100644
--- a/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.tsx
+++ b/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.tsx
@@ -73,7 +73,7 @@ const DeviceSettingsMenu = ({
return (
<>
- {hasMediaProcessorSupport() && config.videoSettings.backgroundEffects && (
+ {hasMediaProcessorSupport() && config.videoSettings.allowBackgroundEffects && (
<>
diff --git a/frontend/src/components/WaitingRoom/CameraButton/CameraButton.spec.tsx b/frontend/src/components/WaitingRoom/CameraButton/CameraButton.spec.tsx
index 588ec43b..ed6e7796 100644
--- a/frontend/src/components/WaitingRoom/CameraButton/CameraButton.spec.tsx
+++ b/frontend/src/components/WaitingRoom/CameraButton/CameraButton.spec.tsx
@@ -28,7 +28,7 @@ vi.mock('../../../hooks/useConfigContext', () => {
return {
default: () => ({
videoSettings: {
- enableDisableCapableCamera: true,
+ allowCameraControl: true,
},
}),
};
diff --git a/frontend/src/components/WaitingRoom/CameraButton/CameraButton.tsx b/frontend/src/components/WaitingRoom/CameraButton/CameraButton.tsx
index fd956208..c885a735 100644
--- a/frontend/src/components/WaitingRoom/CameraButton/CameraButton.tsx
+++ b/frontend/src/components/WaitingRoom/CameraButton/CameraButton.tsx
@@ -18,7 +18,7 @@ const CameraButton = (): ReactElement | false => {
const { toggleVideo: toggleBackgroundVideoPublisher } = useBackgroundPublisherContext();
const config = useConfigContext();
const title = `Turn ${isVideoEnabled ? 'off' : 'on'} camera`;
- const canEnableOrDisableCamera = config.videoSettings.enableDisableCapableCamera;
+ const { allowCameraControl } = config.videoSettings;
const handleToggleVideo = () => {
toggleVideo();
@@ -26,7 +26,7 @@ const CameraButton = (): ReactElement | false => {
};
return (
- canEnableOrDisableCamera && (
+ allowCameraControl && (
{
return {
default: () => ({
videoSettings: {
- enableDisableCapableCamera: true,
+ allowCameraControl: true,
},
audioSettings: {
enableDisableCapableMicrophone: true,
From f4f599928f8380b56762c46b82cf0097785cb589 Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Wed, 17 Sep 2025 14:51:43 -0700
Subject: [PATCH 40/58] fixing tests
---
.../usePublisherOptions/usePublisherOptions.spec.tsx | 6 +++---
.../DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx
index 0539b0f8..c8dc7133 100644
--- a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx
+++ b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx
@@ -93,7 +93,7 @@ describe('usePublisherOptions', () => {
const { result } = renderHook(() => usePublisherOptions());
await waitFor(() => {
expect(result.current).toEqual({
- defaultResolution: '1280x720',
+ resolution: '1280x720',
publishAudio: false,
publishVideo: false,
audioSource: undefined,
@@ -136,7 +136,7 @@ describe('usePublisherOptions', () => {
const { result } = renderHook(() => usePublisherOptions());
await waitFor(() => {
expect(result.current).toEqual({
- defaultResolution: '1280x720',
+ resolution: '1280x720',
publishAudio: true,
publishVideo: true,
audioSource: '68f1d1e6f11c629b1febe51a95f8f740f8ac5cd3d4c91419bd2b52bb1a9a01cd',
@@ -178,7 +178,7 @@ describe('usePublisherOptions', () => {
configContext.videoSettings.defaultResolution = '640x480';
const { result } = renderHook(() => usePublisherOptions());
await waitFor(() => {
- expect(result.current?.defaultResolution).toBe('640x480');
+ expect(result.current?.resolution).toBe('640x480');
});
});
});
diff --git a/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx b/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
index b31a01d3..5c7deed2 100644
--- a/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
+++ b/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
@@ -90,7 +90,7 @@ describe('DeviceSettingsMenu Component', () => {
mockedHasMediaProcessorSupport.mockReturnValue(false);
configContext = {
audioSettings: {
- allowCameraControl: true,
+ advancedNoiseSuppression: true,
},
videoSettings: {
allowBackgroundEffects: true,
From ec9c5f008057eb3db496faa3a665bca642c9334a Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Thu, 18 Sep 2025 12:32:59 -0700
Subject: [PATCH 41/58] fix tests. use en.json
---
.../DeviceControlButton.tsx | 10 +-
frontend/src/locales/en.json | 2 +
yarn.lock | 198 +++++++++---------
3 files changed, 105 insertions(+), 105 deletions(-)
diff --git a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx
index bc7bc136..39d6c8ae 100644
--- a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx
+++ b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx
@@ -47,12 +47,12 @@ const DeviceControlButton = ({
let tooltipTitle: string;
if (isAudio) {
if (!enableDisableCapableMicrophone) {
- tooltipTitle = 'Microphone control is disabled in this application';
+ tooltipTitle = t('devices.audio.disabled');
} else {
tooltipTitle = audioTitle;
}
} else if (!allowCameraControl) {
- tooltipTitle = 'Camera control is disabled in this application';
+ tooltipTitle = t('devices.video.disabled');
} else {
tooltipTitle = videoTitle;
}
@@ -111,6 +111,7 @@ const DeviceControlButton = ({
)}
-
+
Date: Thu, 18 Sep 2025 12:55:52 -0700
Subject: [PATCH 42/58] renaming
---
config.example.json | 6 +++---
.../ConfigProvider/useConfig/useConfig.spec.tsx | 12 ++++++------
.../Context/ConfigProvider/useConfig/useConfig.tsx | 12 ++++++------
.../usePublisherOptions/usePublisherOptions.spec.tsx | 4 ++--
.../usePublisherOptions/usePublisherOptions.tsx | 4 ++--
.../DeviceControlButton/DeviceControlButton.spec.tsx | 4 ++--
.../DeviceControlButton/DeviceControlButton.tsx | 8 ++++----
.../DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx | 2 +-
.../ReduceNoiseTestSpeakers.spec.tsx | 4 ++--
.../ReduceNoiseTestSpeakers.tsx | 2 +-
.../components/WaitingRoom/MicButton/MicButton.tsx | 4 ++--
frontend/src/pages/MeetingRoom/MeetingRoom.spec.tsx | 2 +-
12 files changed, 32 insertions(+), 32 deletions(-)
diff --git a/config.example.json b/config.example.json
index 4f54f53e..d8f7ab06 100644
--- a/config.example.json
+++ b/config.example.json
@@ -6,9 +6,9 @@
"defaultResolution": "1280x720"
},
"audioSettings": {
- "advancedNoiseSuppression": true,
- "audioOnJoin": true,
- "enableDisableCapableMicrophone": true
+ "allowAdvancedNoiseSuppression": true,
+ "allowAudioOnJoin": true,
+ "allowMicrophoneControl": true
},
"waitingRoomSettings": {
"allowDeviceSelection": true
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index f0b853bb..0ebf0cb3 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -12,9 +12,9 @@ describe('useConfig', () => {
allowBackgroundEffects: true,
},
audioSettings: {
- advancedNoiseSuppression: true,
- audioOnJoin: true,
- enableDisableCapableMicrophone: true,
+ allowAdvancedNoiseSuppression: true,
+ allowAudioOnJoin: true,
+ allowMicrophoneControl: true,
},
waitingRoomSettings: {
allowDeviceSelection: true,
@@ -65,9 +65,9 @@ describe('useConfig', () => {
allowBackgroundEffects: false,
},
audioSettings: {
- advancedNoiseSuppression: false,
- audioOnJoin: false,
- enableDisableCapableMicrophone: false,
+ allowAdvancedNoiseSuppression: false,
+ allowAudioOnJoin: false,
+ allowMicrophoneControl: false,
},
waitingRoomSettings: {
allowDeviceSelection: false,
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index 795e8ada..af472c4d 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -16,9 +16,9 @@ export type VideoSettings = {
};
export type AudioSettings = {
- advancedNoiseSuppression: boolean;
- audioOnJoin: boolean;
- enableDisableCapableMicrophone: boolean;
+ allowAdvancedNoiseSuppression: boolean;
+ allowAudioOnJoin: boolean;
+ allowMicrophoneControl: boolean;
};
export type WaitingRoomSettings = {
@@ -50,9 +50,9 @@ export const defaultConfig: AppConfig = {
defaultResolution: '1280x720',
},
audioSettings: {
- advancedNoiseSuppression: true,
- audioOnJoin: true,
- enableDisableCapableMicrophone: true,
+ allowAdvancedNoiseSuppression: true,
+ allowAudioOnJoin: true,
+ allowMicrophoneControl: true,
},
waitingRoomSettings: {
allowDeviceSelection: true,
diff --git a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx
index c8dc7133..a33a5829 100644
--- a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx
+++ b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.spec.tsx
@@ -73,7 +73,7 @@ describe('usePublisherOptions', () => {
await deviceStore.init();
configContext = {
audioSettings: {
- audioOnJoin: true,
+ allowAudioOnJoin: true,
},
videoSettings: {
defaultResolution: '1280x720',
@@ -159,7 +159,7 @@ describe('usePublisherOptions', () => {
describe('configurable features', () => {
it('should disable audio publishing', async () => {
- configContext.audioSettings.audioOnJoin = false;
+ configContext.audioSettings.allowAudioOnJoin = false;
const { result } = renderHook(() => usePublisherOptions());
await waitFor(() => {
expect(result.current?.publishAudio).toBe(false);
diff --git a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx
index 0d25bafb..4c6d8c7f 100644
--- a/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx
+++ b/frontend/src/Context/PublisherProvider/usePublisherOptions/usePublisherOptions.tsx
@@ -55,7 +55,7 @@ const usePublisherOptions = (): PublisherProperties | null => {
initials,
insertDefaultUI: false,
name,
- publishAudio: config.audioSettings.audioOnJoin && publishAudio,
+ publishAudio: config.audioSettings.allowAudioOnJoin && publishAudio,
publishVideo: config.videoSettings.allowVideoOnJoin && publishVideo,
resolution: config.videoSettings.defaultResolution,
audioFilter,
@@ -67,7 +67,7 @@ const usePublisherOptions = (): PublisherProperties | null => {
setOptions();
}, [
- config.audioSettings.audioOnJoin,
+ config.audioSettings.allowAudioOnJoin,
config.videoSettings.defaultResolution,
config.videoSettings.allowVideoOnJoin,
user.defaultSettings,
diff --git a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.spec.tsx b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.spec.tsx
index 7d4aae22..08076461 100644
--- a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.spec.tsx
+++ b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.spec.tsx
@@ -68,7 +68,7 @@ describe('DeviceControlButton', () => {
configContext = {
audioSettings: {
- enableDisableCapableMicrophone: true,
+ allowMicrophoneControl: true,
},
videoSettings: {
allowCameraControl: true,
@@ -125,7 +125,7 @@ describe('DeviceControlButton', () => {
});
it('renders the button as disabled with greyed out icon and correct tooltip when microphone control is disabled', async () => {
- configContext.audioSettings.enableDisableCapableMicrophone = false;
+ configContext.audioSettings.allowMicrophoneControl = false;
render(
(null);
const audioTitle = isAudioEnabled ? t('devices.audio.disable') : t('devices.audio.enable');
const videoTitle = isVideoEnabled ? t('devices.video.disable') : t('devices.video.enable');
- const { enableDisableCapableMicrophone } = config.audioSettings;
+ const { allowMicrophoneControl } = config.audioSettings;
const { allowCameraControl } = config.videoSettings;
- const isButtonDisabled = isAudio ? !enableDisableCapableMicrophone : !allowCameraControl;
+ const isButtonDisabled = isAudio ? !allowMicrophoneControl : !allowCameraControl;
let tooltipTitle: string;
if (isAudio) {
- if (!enableDisableCapableMicrophone) {
+ if (!allowMicrophoneControl) {
tooltipTitle = t('devices.audio.disabled');
} else {
tooltipTitle = audioTitle;
@@ -70,7 +70,7 @@ const DeviceControlButton = ({
const renderControlIcon = () => {
if (isAudio) {
- if (!enableDisableCapableMicrophone) {
+ if (!allowMicrophoneControl) {
return ;
}
if (isAudioEnabled) {
diff --git a/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx b/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
index 5c7deed2..344df269 100644
--- a/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
+++ b/frontend/src/components/MeetingRoom/DeviceSettingsMenu/DeviceSettingsMenu.spec.tsx
@@ -90,7 +90,7 @@ describe('DeviceSettingsMenu Component', () => {
mockedHasMediaProcessorSupport.mockReturnValue(false);
configContext = {
audioSettings: {
- advancedNoiseSuppression: true,
+ allowAdvancedNoiseSuppression: true,
},
videoSettings: {
allowBackgroundEffects: true,
diff --git a/frontend/src/components/MeetingRoom/ReduceNoiseTestSpeakers/ReduceNoiseTestSpeakers.spec.tsx b/frontend/src/components/MeetingRoom/ReduceNoiseTestSpeakers/ReduceNoiseTestSpeakers.spec.tsx
index 3f739fb0..9d8ed9f6 100644
--- a/frontend/src/components/MeetingRoom/ReduceNoiseTestSpeakers/ReduceNoiseTestSpeakers.spec.tsx
+++ b/frontend/src/components/MeetingRoom/ReduceNoiseTestSpeakers/ReduceNoiseTestSpeakers.spec.tsx
@@ -50,7 +50,7 @@ describe('ReduceNoiseTestSpeakers', () => {
} as unknown as PublisherContextType;
configContext = {
audioSettings: {
- advancedNoiseSuppression: true,
+ allowAdvancedNoiseSuppression: true,
},
} as unknown as ConfigContextType;
mockUsePublisherContext.mockImplementation(() => publisherContext);
@@ -143,7 +143,7 @@ describe('ReduceNoiseTestSpeakers', () => {
it('should not render the Advanced Noise Suppression option if it is configured to be disabled', () => {
configContext = {
audioSettings: {
- advancedNoiseSuppression: false,
+ allowAdvancedNoiseSuppression: false,
},
} as unknown as ConfigContextType;
mockUseConfigContext.mockReturnValue(configContext);
diff --git a/frontend/src/components/MeetingRoom/ReduceNoiseTestSpeakers/ReduceNoiseTestSpeakers.tsx b/frontend/src/components/MeetingRoom/ReduceNoiseTestSpeakers/ReduceNoiseTestSpeakers.tsx
index 38b86b33..4ab204bf 100644
--- a/frontend/src/components/MeetingRoom/ReduceNoiseTestSpeakers/ReduceNoiseTestSpeakers.tsx
+++ b/frontend/src/components/MeetingRoom/ReduceNoiseTestSpeakers/ReduceNoiseTestSpeakers.tsx
@@ -33,7 +33,7 @@ const ReduceNoiseTestSpeakers = ({
const { publisher, isPublishing } = usePublisherContext();
const config = useConfigContext();
const [isToggled, setIsToggled] = useState(false);
- const isANSEnabled = config.audioSettings.advancedNoiseSuppression;
+ const isANSEnabled = config.audioSettings.allowAdvancedNoiseSuppression;
const handleToggle = async () => {
const newState = !isToggled;
diff --git a/frontend/src/components/WaitingRoom/MicButton/MicButton.tsx b/frontend/src/components/WaitingRoom/MicButton/MicButton.tsx
index 71dedd6c..9bd235d3 100644
--- a/frontend/src/components/WaitingRoom/MicButton/MicButton.tsx
+++ b/frontend/src/components/WaitingRoom/MicButton/MicButton.tsx
@@ -20,10 +20,10 @@ const MicButton = (): ReactElement | false => {
const title = isAudioEnabled
? t('devices.audio.microphone.state.off')
: t('devices.audio.microphone.state.on');
- const canEnableOrDisableMicrophone = config.audioSettings.enableDisableCapableMicrophone;
+ const { allowMicrophoneControl } = config.audioSettings;
return (
- canEnableOrDisableMicrophone && (
+ allowMicrophoneControl && (
{
allowCameraControl: true,
},
audioSettings: {
- enableDisableCapableMicrophone: true,
+ allowMicrophoneControl: true,
},
meetingRoomSettings: {
defaultLayoutMode: 'active-speaker',
From d5e4db60495fe59bda54cb2566c1d96ce0e399f2 Mon Sep 17 00:00:00 2001
From: Christian Pettet <71297280+cpettet@users.noreply.github.com>
Date: Thu, 18 Sep 2025 12:57:20 -0700
Subject: [PATCH 43/58] fix
---
.../MeetingRoom/DeviceControlButton/DeviceControlButton.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx
index ea296cc7..ac4a9f04 100644
--- a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx
+++ b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx
@@ -111,7 +111,6 @@ const DeviceControlButton = ({
Date: Thu, 18 Sep 2025 13:05:58 -0700
Subject: [PATCH 44/58] test fix
---
.../DeviceControlButton.tsx | 22 ++++++++++---------
1 file changed, 12 insertions(+), 10 deletions(-)
diff --git a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx
index ac4a9f04..3efe8d9a 100644
--- a/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx
+++ b/frontend/src/components/MeetingRoom/DeviceControlButton/DeviceControlButton.tsx
@@ -125,16 +125,18 @@ const DeviceControlButton = ({
)}
-
- {renderControlIcon()}
-
+
+
+ {renderControlIcon()}
+
+
Date: Thu, 18 Sep 2025 13:35:32 -0700
Subject: [PATCH 45/58] show participant list
---
config.example.json | 2 +-
.../useConfig/useConfig.spec.tsx | 4 +-
.../ConfigProvider/useConfig/useConfig.tsx | 4 +-
.../HiddenParticipantsTile.spec.tsx | 69 +++++++++++++------
.../HiddenParticipantsTile.tsx | 13 ++--
.../ParticipantListButton.tsx | 2 +-
.../ParticipantsListButton.spec.tsx | 6 +-
.../VideoTileCanvas/VideoTileCanvas.tsx | 3 -
.../pages/MeetingRoom/MeetingRoom.spec.tsx | 2 +-
.../src/pages/MeetingRoom/MeetingRoom.tsx | 1 -
10 files changed, 67 insertions(+), 39 deletions(-)
diff --git a/config.example.json b/config.example.json
index d8f7ab06..8230b88a 100644
--- a/config.example.json
+++ b/config.example.json
@@ -19,7 +19,7 @@
"showCaptionsButton": true,
"showChatButton": true,
"showEmojiButton": true,
- "showParticipantListButton": true,
+ "showParticipantList": true,
"showScreenShareButton": true
}
}
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
index 0ebf0cb3..b8436ee7 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.spec.tsx
@@ -21,7 +21,7 @@ describe('useConfig', () => {
},
meetingRoomSettings: {
defaultLayoutMode: 'active-speaker',
- showParticipantListButton: true,
+ showParticipantList: true,
showChatButton: true,
showScreenShareButton: true,
showArchiveButton: true,
@@ -74,7 +74,7 @@ describe('useConfig', () => {
},
meetingRoomSettings: {
defaultLayoutMode: 'grid',
- showParticipantListButton: false,
+ showParticipantList: false,
showChatButton: false,
showScreenShareButton: false,
showArchiveButton: false,
diff --git a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
index af472c4d..7792e898 100644
--- a/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
+++ b/frontend/src/Context/ConfigProvider/useConfig/useConfig.tsx
@@ -31,7 +31,7 @@ export type MeetingRoomSettings = {
showCaptionsButton: boolean;
showChatButton: boolean;
showEmojiButton: boolean;
- showParticipantListButton: boolean;
+ showParticipantList: boolean;
showScreenShareButton: boolean;
};
@@ -59,7 +59,7 @@ export const defaultConfig: AppConfig = {
},
meetingRoomSettings: {
defaultLayoutMode: 'active-speaker',
- showParticipantListButton: true,
+ showParticipantList: true,
showChatButton: true,
showScreenShareButton: true,
showArchiveButton: true,
diff --git a/frontend/src/components/HiddenParticipantsTile/HiddenParticipantsTile.spec.tsx b/frontend/src/components/HiddenParticipantsTile/HiddenParticipantsTile.spec.tsx
index 00fc96db..8475d1cf 100644
--- a/frontend/src/components/HiddenParticipantsTile/HiddenParticipantsTile.spec.tsx
+++ b/frontend/src/components/HiddenParticipantsTile/HiddenParticipantsTile.spec.tsx
@@ -1,11 +1,24 @@
import { fireEvent, render, screen } from '@testing-library/react';
-import { describe, it, expect, vi } from 'vitest';
+import { describe, it, expect, vi, beforeEach, Mock, afterEach } from 'vitest';
import userEvent from '@testing-library/user-event';
import { Subscriber } from '@vonage/client-sdk-video';
import { SubscriberWrapper } from '../../types/session';
import HiddenParticipantsTile from './index';
+import useConfigContext from '../../hooks/useConfigContext';
+import { ConfigContextType } from '../../Context/ConfigProvider';
+
+const mockToggleParticipantList = vi.fn();
+vi.mock('../../hooks/useSessionContext', () => ({
+ __esModule: true,
+ default: () => ({
+ toggleParticipantList: mockToggleParticipantList,
+ }),
+}));
+const mockUseConfigContext = useConfigContext as Mock<[], ConfigContextType>;
+vi.mock('../../hooks/useConfigContext');
describe('HiddenParticipantsTile', () => {
+ let configContext: ConfigContextType;
const box = { height: 100, width: 100, top: 0, left: 0 };
const hiddenSubscribers = [
{
@@ -28,9 +41,20 @@ describe('HiddenParticipantsTile', () => {
},
];
- it('should display two hidden participants', async () => {
- const mockFn = vi.fn();
+ beforeEach(() => {
+ configContext = {
+ meetingRoomSettings: {
+ showParticipantList: true,
+ },
+ } as unknown as ConfigContextType;
+ mockUseConfigContext.mockReturnValue(configContext);
+ });
+ afterEach(() => {
+ vi.resetAllMocks();
+ });
+
+ it('should display two hidden participants', async () => {
const currentHiddenSubscribers = [
...hiddenSubscribers,
{
@@ -53,13 +77,7 @@ describe('HiddenParticipantsTile', () => {
},
] as SubscriberWrapper[];
- render(
-
- );
+ render();
const button = screen.getByTestId('hidden-participants');
expect(button).toBeInTheDocument();
@@ -71,21 +89,13 @@ describe('HiddenParticipantsTile', () => {
expect(screen.getByText('JD')).toBeInTheDocument();
expect(screen.getByText('JS')).toBeInTheDocument();
- expect(mockFn).toHaveBeenCalled();
+ expect(mockToggleParticipantList).toHaveBeenCalled();
});
it('should display one hidden participant because the other one is empty', async () => {
- const mockFn = vi.fn();
-
const currentHiddenSubscribers = [...hiddenSubscribers, {}] as SubscriberWrapper[];
- render(
-
- );
+ render();
const button = screen.getByTestId('hidden-participants');
expect(button).toBeInTheDocument();
@@ -94,6 +104,23 @@ describe('HiddenParticipantsTile', () => {
expect(screen.getByText('JD')).toBeInTheDocument();
expect(screen.queryByText('JS')).not.toBeInTheDocument();
- expect(mockFn).toHaveBeenCalled();
+ expect(mockToggleParticipantList).toHaveBeenCalled();
+ });
+
+ it('does not toggle participant list when showParticipantList is disabled', async () => {
+ const currentHiddenSubscribers = [...hiddenSubscribers, {}] as SubscriberWrapper[];
+ mockUseConfigContext.mockReturnValue({
+ meetingRoomSettings: {
+ showParticipantList: false,
+ },
+ } as unknown as ConfigContextType);
+
+ render();
+
+ const button = screen.getByTestId('hidden-participants');
+ expect(button).toBeInTheDocument();
+ await userEvent.click(button);
+
+ expect(mockToggleParticipantList).not.toHaveBeenCalled();
});
});
diff --git a/frontend/src/components/HiddenParticipantsTile/HiddenParticipantsTile.tsx b/frontend/src/components/HiddenParticipantsTile/HiddenParticipantsTile.tsx
index e0239a16..f53f2476 100644
--- a/frontend/src/components/HiddenParticipantsTile/HiddenParticipantsTile.tsx
+++ b/frontend/src/components/HiddenParticipantsTile/HiddenParticipantsTile.tsx
@@ -4,11 +4,12 @@ import { Box } from 'opentok-layout-js';
import { SubscriberWrapper } from '../../types/session';
import AvatarInitials from '../AvatarInitials';
import getBoxStyle from '../../utils/helpers/getBoxStyle';
+import useSessionContext from '../../hooks/useSessionContext';
+import useConfigContext from '../../hooks/useConfigContext';
export type HiddenParticipantsTileProps = {
box: Box;
hiddenSubscribers: SubscriberWrapper[];
- handleClick: () => void;
};
/**
* HiddenParticipantsTile Component
@@ -23,17 +24,21 @@ export type HiddenParticipantsTileProps = {
const HiddenParticipantsTile = ({
box,
hiddenSubscribers,
- handleClick,
}: HiddenParticipantsTileProps): ReactElement => {
+ const { toggleParticipantList } = useSessionContext();
+ const { meetingRoomSettings } = useConfigContext();
+ const { showParticipantList } = meetingRoomSettings;
const { height, width } = box;
const diameter = Math.min(height, width) * 0.38;
return (