diff --git a/examples/prebuilt-react-integration/src/App.jsx b/examples/prebuilt-react-integration/src/App.jsx
index e49ddcb9b1..47560de72b 100644
--- a/examples/prebuilt-react-integration/src/App.jsx
+++ b/examples/prebuilt-react-integration/src/App.jsx
@@ -4,5 +4,7 @@ import { getRoomCodeFromUrl } from './utils';
export default function App() {
const roomCode = getRoomCodeFromUrl();
- return ;
+ return (
+
+ );
}
diff --git a/packages/hms-video-store/src/selectors/selectors.ts b/packages/hms-video-store/src/selectors/selectors.ts
index ce91647ea6..fb276ff10c 100644
--- a/packages/hms-video-store/src/selectors/selectors.ts
+++ b/packages/hms-video-store/src/selectors/selectors.ts
@@ -452,6 +452,7 @@ export const selectPermissions = createSelector(selectLocalPeerRole, role => rol
export const selectRecordingState = createSelector(selectRoom, room => room.recording);
export const selectRTMPState = createSelector(selectRoom, room => room.rtmp);
export const selectHLSState = createSelector(selectRoom, room => room.hls);
+export const selectTranscriptionsState = createSelector(selectRoom, room => room.transcriptions);
export const selectSessionId = createSelector(selectRoom, room => room.sessionId);
export const selectRoomStartTime = createSelector(selectRoom, room => room.startedAt);
export const selectIsLargeRoom = createSelector(selectRoom, room => !!room.isLargeRoom);
diff --git a/packages/hms-video-store/src/utils/constants.ts b/packages/hms-video-store/src/utils/constants.ts
index 07f78bc0ee..5372663c7b 100644
--- a/packages/hms-video-store/src/utils/constants.ts
+++ b/packages/hms-video-store/src/utils/constants.ts
@@ -59,7 +59,7 @@ export const HMSEvents = {
export const PROTOCOL_VERSION = '2.5';
-export const PROTOCOL_SPEC = '20240417';
+export const PROTOCOL_SPEC = '20240521';
export const HAND_RAISE_GROUP_NAME = '_handraise';
diff --git a/packages/roomkit-react/src/Prebuilt/components/AppData/AppData.tsx b/packages/roomkit-react/src/Prebuilt/components/AppData/AppData.tsx
index d781feebc8..35d3e0bf1c 100644
--- a/packages/roomkit-react/src/Prebuilt/components/AppData/AppData.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/AppData/AppData.tsx
@@ -66,8 +66,8 @@ const initialAppData = {
[POLL_STATE.pollInView]: '',
[POLL_STATE.view]: '',
},
- // by default off, so it will not appear in beam bots
- [APP_DATA.caption]: false,
+ // by default on because of on demand now
+ [APP_DATA.caption]: true,
};
export const AppData = React.memo(() => {
diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/CaptionContent.tsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/CaptionContent.tsx
new file mode 100644
index 0000000000..5a60f1ac38
--- /dev/null
+++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/CaptionContent.tsx
@@ -0,0 +1,132 @@
+import React from 'react';
+import { HMSTranscriptionMode, selectIsTranscriptionEnabled, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
+import { AlertTriangleIcon, CrossIcon } from '@100mslive/react-icons';
+import { Button } from '../../../Button';
+import { Box, Flex } from '../../../Layout';
+import { Loading } from '../../../Loading';
+import { Text } from '../../../Text';
+// @ts-ignore: No implicit Any
+import { ToastManager } from '../Toast/ToastManager';
+// @ts-ignore: No implicit Any
+import { useSetIsCaptionEnabled } from '../AppData/useUISettings';
+
+export const CaptionContent = ({ isMobile, onExit }: { isMobile: boolean; onExit: () => void }) => {
+ const DURATION = 2000;
+ const actions = useHMSActions();
+ const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);
+
+ const [isCaptionEnabled, setIsCaptionEnabled] = useSetIsCaptionEnabled();
+ return (
+ <>
+
+ {isTranscriptionEnabled ? 'Disable' : 'Enable'} Closed Caption (CC) for this session?
+
+
+
+
+ {!isMobile ? (
+
+ This will {isTranscriptionEnabled ? 'disable' : 'enable'} Closed Captions for everyone in this room. You can
+ {isTranscriptionEnabled ? 'enable' : 'disable'} it later.
+
+ ) : null}
+
+
+ {isMobile ? null : (
+
+ )}
+
+ {isMobile && isTranscriptionEnabled ? (
+
+ ) : null}
+
+
+
+ {isMobile && (
+
+ This will {isTranscriptionEnabled ? 'disable' : 'enable'} Closed Captions for everyone in this room. You can
+ {isTranscriptionEnabled ? 'enable' : 'disable'} it later.
+
+ )}
+ >
+ );
+};
diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/CaptionModal.tsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/CaptionModal.tsx
new file mode 100644
index 0000000000..37684c6b0a
--- /dev/null
+++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/CaptionModal.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { useMedia } from 'react-use';
+import { config as cssConfig, Dialog } from '../../..';
+import { Sheet } from '../../../Sheet';
+import { CaptionContent } from './CaptionContent';
+
+export const CaptionModal = ({ onOpenChange }: { onOpenChange: (value: boolean) => void }) => {
+ const isMobile = useMedia(cssConfig.media.md);
+
+ const props = {
+ isMobile,
+ onExit: () => {
+ onOpenChange(false);
+ },
+ };
+
+ if (isMobile) {
+ return (
+
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+
+
+ );
+};
diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx
index 49ea2c01de..f9f321849b 100644
--- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/DesktopOptions.tsx
@@ -6,9 +6,23 @@ import {
HLSLiveStreamingScreen_Elements,
} from '@100mslive/types-prebuilt';
import { match } from 'ts-pattern';
-import { selectAppData, selectLocalPeerID, useHMSActions, useHMSStore } from '@100mslive/react-sdk';
-import { BrbIcon, CheckIcon, HamburgerMenuIcon, InfoIcon, PipIcon, SettingsIcon } from '@100mslive/react-icons';
-import { Checkbox, Dropdown, Flex, Text, Tooltip } from '../../../..';
+import {
+ selectAppData,
+ selectIsTranscriptionEnabled,
+ selectLocalPeerID,
+ useHMSActions,
+ useHMSStore,
+} from '@100mslive/react-sdk';
+import {
+ BrbIcon,
+ CheckIcon,
+ HamburgerMenuIcon,
+ InfoIcon,
+ OpenCaptionIcon,
+ PipIcon,
+ SettingsIcon,
+} from '@100mslive/react-icons';
+import { Checkbox, Dropdown, Flex, Switch, Text, Tooltip } from '../../../..';
import IconButton from '../../../IconButton';
// @ts-ignore: No implicit any
import { PIP } from '../../PIP';
@@ -24,6 +38,7 @@ import StartRecording from '../../Settings/StartRecording';
import { StatsForNerds } from '../../StatsForNerds';
// @ts-ignore: No implicit any
import { BulkRoleChangeModal } from '../BulkRoleChangeModal';
+import { CaptionModal } from '../CaptionModal';
// @ts-ignore: No implicit any
import { FullScreenItem } from '../FullScreenItem';
import { MuteAllModal } from '../MuteAllModal';
@@ -43,6 +58,7 @@ const MODALS = {
BULK_ROLE_CHANGE: 'bulkRoleChange',
MUTE_ALL: 'muteAll',
EMBED_URL: 'embedUrl',
+ CAPTION: 'caption',
};
export const DesktopOptions = ({
@@ -59,6 +75,7 @@ export const DesktopOptions = ({
const { isBRBOn, toggleBRB } = useMyMetadata();
const isPipOn = PictureInPicture.isOn();
const isBRBEnabled = !!elements?.brb;
+ const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);
useDropdownList({ open: openModals.size > 0, name: 'MoreSettings' });
@@ -115,6 +132,23 @@ export const DesktopOptions = ({
) : null}
+ {
+ updateState(MODALS.CAPTION, true);
+ }}
+ >
+
+
+
+ Closed Captions
+
+
+ {isTranscriptionEnabled ? 'Enabled' : 'Disabled'}
+
+
+
+
{screenType !== 'hls_live_streaming' ? (
updateState(MODALS.SELF_ROLE_CHANGE, value)}
/>
)}
+ {openModals.has(MODALS.CAPTION) && (
+ updateState(MODALS.CAPTION, value)} />
+ )}
{/* {openModals.has(MODALS.EMBED_URL) && (
updateState(MODALS.EMBED_URL, value)} />
)} */}
diff --git a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx
index bf13d19d50..bb43a68ab4 100644
--- a/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx
+++ b/packages/roomkit-react/src/Prebuilt/components/MoreSettings/SplitComponents/MwebOptions.tsx
@@ -29,7 +29,7 @@ import {
SettingsIcon,
VirtualBackgroundIcon,
} from '@100mslive/react-icons';
-import { Box, Loading, Tooltip } from '../../../..';
+import { Box, Loading, Text, Tooltip } from '../../../..';
import { Sheet } from '../../../../Sheet';
// @ts-ignore: No implicit any
import IconButton from '../../../IconButton';
@@ -43,6 +43,7 @@ import SettingsModal from '../../Settings/SettingsModal';
import { ToastManager } from '../../Toast/ToastManager';
// @ts-ignore: No implicit any
import { ActionTile } from '../ActionTile';
+import { CaptionModal } from '../CaptionModal';
// @ts-ignore: No implicit any
import { ChangeNameModal } from '../ChangeNameModal';
// @ts-ignore: No implicit any
@@ -73,6 +74,7 @@ const MODALS = {
BULK_ROLE_CHANGE: 'bulkRoleChange',
MUTE_ALL: 'muteAll',
EMBED_URL: 'embedUrl',
+ CAPTION: 'caption',
};
export const MwebOptions = ({
@@ -106,9 +108,9 @@ export const MwebOptions = ({
const isLocalVideoEnabled = useHMSStore(selectIsLocalVideoEnabled);
const { startRecording, isRecordingLoading } = useRecordingHandler();
- const isCaptionPresent = useHMSStore(selectIsTranscriptionEnabled);
+ const isTranscriptionEnabled = useHMSStore(selectIsTranscriptionEnabled);
- const [isCaptionEnabled, setIsCaptionEnabled] = useSetIsCaptionEnabled();
+ const [isCaptionEnabled] = useSetIsCaptionEnabled();
useDropdownList({ open: openModals.size > 0 || openOptionsSheet || openSettingsSheet, name: 'MoreSettings' });
const updateState = (modalName: string, value: boolean) => {
@@ -193,21 +195,17 @@ export const MwebOptions = ({
{isHandRaised ? 'Lower' : 'Raise'} Hand
) : null}
- {isCaptionPresent && screenType !== 'hls_live_streaming' ? (
- {
- setIsCaptionEnabled(!isCaptionEnabled);
- }}
- >
- {isCaptionEnabled ? (
-
- ) : (
-
- )}
- {isCaptionEnabled ? 'Hide Captions' : 'Captions Disabled'}
-
- ) : null}
-
+ {
+ setOpenOptionsSheet(false);
+ updateState(MODALS.CAPTION, true);
+ }}
+ >
+ {isTranscriptionEnabled && isCaptionEnabled ? : }
+
+ Closed Caption
+
+
{isLocalVideoEnabled && !!elements?.virtual_background ? (
{
@@ -323,7 +321,9 @@ export const MwebOptions = ({
openParentSheet={() => setOpenOptionsSheet(true)}
/>
)}
-
+ {openModals.has(MODALS.CAPTION) && (
+ updateState(MODALS.CAPTION, value)} />
+ )}
{showEmojiCard && (
{
+ if (transcriptionStates && transcriptionStates.length > 0 && transcriptionStates[0].error) {
+ ToastManager.addToast({
+ title: `Failed to enable Closed Caption`,
+ variant: 'error',
+ icon: ,
+ });
+ }
+ }, [transcriptionStates]);
+
useEffect(() => {
if (mainPage !== 0) {
return;